evolution-3.6.4/modules/mail/e-mail-shell-backend.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found e-mail-shell-backend.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
clang-analyzer no-output-found e-mail-shell-backend.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  * e-mail-shell-backend.c
   3  *
   4  * This program is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU Lesser General Public
   6  * License as published by the Free Software Foundation; either
   7  * version 2 of the License, or (at your option) version 3.
   8  *
   9  * This program is distributed in the hope that it will be useful,
  10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12  * Lesser General Public License for more details.
  13  *
  14  * You should have received a copy of the GNU Lesser General Public
  15  * License along with the program; if not, see <http://www.gnu.org/licenses/>
  16  *
  17  *
  18  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
  19  *
  20  */
  21 
  22 #ifdef HAVE_CONFIG_H
  23 #include <config.h>
  24 #endif
  25 
  26 #include "e-mail-shell-backend.h"
  27 
  28 #include <glib/gi18n.h>
  29 
  30 #include <e-util/e-import.h>
  31 #include <e-util/e-util.h>
  32 
  33 #include <shell/e-shell.h>
  34 #include <shell/e-shell-window.h>
  35 
  36 #include <composer/e-msg-composer.h>
  37 
  38 #include <widgets/misc/e-preferences-window.h>
  39 #include <widgets/misc/e-web-view.h>
  40 
  41 #include <libemail-engine/e-mail-folder-utils.h>
  42 #include <libemail-engine/e-mail-session.h>
  43 #include <libemail-engine/mail-config.h>
  44 #include <libemail-engine/mail-ops.h>
  45 
  46 #include <mail/e-mail-browser.h>
  47 #include <mail/e-mail-config-assistant.h>
  48 #include <mail/e-mail-config-window.h>
  49 #include <mail/e-mail-reader.h>
  50 #include <mail/em-composer-utils.h>
  51 #include <mail/em-folder-utils.h>
  52 #include <mail/em-utils.h>
  53 #include <mail/mail-send-recv.h>
  54 #include <mail/mail-vfolder-ui.h>
  55 #include <mail/importers/mail-importer.h>
  56 #include <mail/e-mail-ui-session.h>
  57 
  58 #include <em-format/e-mail-parser.h>
  59 #include <em-format/e-mail-formatter.h>
  60 #include <em-format/e-mail-part-utils.h>
  61 
  62 #include "e-mail-shell-settings.h"
  63 #include "e-mail-shell-sidebar.h"
  64 #include "e-mail-shell-view.h"
  65 #include "em-account-prefs.h"
  66 #include "em-composer-prefs.h"
  67 #include "em-mailer-prefs.h"
  68 #include "em-network-prefs.h"
  69 
  70 #define E_MAIL_SHELL_BACKEND_GET_PRIVATE(obj) \
  71 	(G_TYPE_INSTANCE_GET_PRIVATE \
  72 	((obj), E_TYPE_MAIL_SHELL_BACKEND, EMailShellBackendPrivate))
  73 
  74 #define E_MAIL_SHELL_BACKEND_GET_PRIVATE(obj) \
  75 	(G_TYPE_INSTANCE_GET_PRIVATE \
  76 	((obj), E_TYPE_MAIL_SHELL_BACKEND, EMailShellBackendPrivate))
  77 
  78 #define BACKEND_NAME "mail"
  79 
  80 struct _EMailShellBackendPrivate {
  81 	gint mail_sync_in_progress;
  82 	guint mail_sync_source_id;
  83 	gpointer assistant; /* weak pointer, when adding new mail account */
  84 	gpointer editor;    /* weak pointer, when editing a mail account */
  85 };
  86 
  87 static void mbox_create_preview_cb (GObject *preview, GtkWidget **preview_widget);
  88 static void mbox_fill_preview_cb (GObject *preview, CamelMimeMessage *msg);
  89 
  90 G_DEFINE_DYNAMIC_TYPE (
  91 	EMailShellBackend,
  92 	e_mail_shell_backend,
  93 	E_TYPE_MAIL_BACKEND)
  94 
  95 static void
  96 mail_shell_backend_init_importers (void)
  97 {
  98 	EImportClass *import_class;
  99 	EImportImporter *importer;
 100 
 101 	import_class = g_type_class_ref (e_import_get_type ());
 102 
 103 	importer = mbox_importer_peek ();
 104 	e_import_class_add_importer (import_class, importer, NULL, NULL);
 105 	mbox_importer_set_preview_funcs (
 106 		mbox_create_preview_cb, mbox_fill_preview_cb);
 107 
 108 	importer = elm_importer_peek ();
 109 	e_import_class_add_importer (import_class, importer, NULL, NULL);
 110 
 111 	importer = pine_importer_peek ();
 112 	e_import_class_add_importer (import_class, importer, NULL, NULL);
 113 }
 114 
 115 static void
 116 mail_shell_backend_mail_icon_cb (EShellWindow *shell_window,
 117                                  const gchar *icon_name)
 118 {
 119 	GtkAction *action;
 120 
 121 	action = e_shell_window_get_shell_view_action (
 122 		shell_window, BACKEND_NAME);
 123 	gtk_action_set_icon_name (action, icon_name);
 124 }
 125 
 126 static void
 127 action_mail_folder_new_cb (GtkAction *action,
 128                            EShellWindow *shell_window)
 129 {
 130 	EMFolderTree *folder_tree = NULL;
 131 	EMailShellSidebar *mail_shell_sidebar;
 132 	EMailSession *session;
 133 	EShellSidebar *shell_sidebar;
 134 	EShellView *shell_view;
 135 	const gchar *view_name;
 136 
 137 	/* Take care not to unnecessarily load the mail shell view. */
 138 	view_name = e_shell_window_get_active_view (shell_window);
 139 	if (g_strcmp0 (view_name, BACKEND_NAME) != 0) {
 140 		EShell *shell;
 141 		EShellBackend *shell_backend;
 142 		EMailBackend *backend;
 143 
 144 		shell = e_shell_window_get_shell (shell_window);
 145 
 146 		shell_backend =
 147 			e_shell_get_backend_by_name (shell, BACKEND_NAME);
 148 		g_return_if_fail (E_IS_MAIL_BACKEND (shell_backend));
 149 
 150 		backend = E_MAIL_BACKEND (shell_backend);
 151 		session = e_mail_backend_get_session (backend);
 152 
 153 		goto exit;
 154 	}
 155 
 156 	shell_view = e_shell_window_get_shell_view (shell_window, view_name);
 157 	shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
 158 
 159 	mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar);
 160 	folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
 161 	session = em_folder_tree_get_session (folder_tree);
 162 
 163 exit:
 164 	em_folder_utils_create_folder (
 165 		GTK_WINDOW (shell_window), session, folder_tree, NULL);
 166 }
 167 
 168 static void
 169 action_mail_account_new_cb (GtkAction *action,
 170                             EShellWindow *shell_window)
 171 {
 172 	EShell *shell;
 173 	EShellBackend *shell_backend;
 174 
 175 	g_return_if_fail (shell_window != NULL);
 176 
 177 	shell = e_shell_window_get_shell (shell_window);
 178 	shell_backend = e_shell_get_backend_by_name (shell, BACKEND_NAME);
 179 	g_return_if_fail (E_IS_MAIL_SHELL_BACKEND (shell_backend));
 180 
 181 	e_mail_shell_backend_new_account (
 182 		E_MAIL_SHELL_BACKEND (shell_backend),
 183 		GTK_WINDOW (shell_window));
 184 }
 185 
 186 static void
 187 action_mail_message_new_cb (GtkAction *action,
 188                             EShellWindow *shell_window)
 189 {
 190 	EMailShellSidebar *mail_shell_sidebar;
 191 	EShellSidebar *shell_sidebar;
 192 	EShellView *shell_view;
 193 	EShell *shell;
 194 	ESourceRegistry *registry;
 195 	EMFolderTree *folder_tree;
 196 	CamelFolder *folder = NULL;
 197 	CamelStore *store;
 198 	GList *list;
 199 	const gchar *extension_name;
 200 	const gchar *view_name;
 201 	gboolean no_transport_defined;
 202 	gchar *folder_name;
 203 
 204 	shell = e_shell_window_get_shell (shell_window);
 205 	registry = e_shell_get_registry (shell);
 206 
 207 	extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT;
 208 	list = e_source_registry_list_sources (registry, extension_name);
 209 	no_transport_defined = (list == NULL);
 210 	g_list_free_full (list, (GDestroyNotify) g_object_unref);
 211 
 212 	if (no_transport_defined)
 213 		return;
 214 
 215 	/* Take care not to unnecessarily load the mail shell view. */
 216 	view_name = e_shell_window_get_active_view (shell_window);
 217 	if (g_strcmp0 (view_name, BACKEND_NAME) != 0)
 218 		goto exit;
 219 
 220 	shell_view = e_shell_window_get_shell_view (shell_window, view_name);
 221 	shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
 222 
 223 	mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar);
 224 	folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
 225 
 226 	if (em_folder_tree_get_selected (folder_tree, &store, &folder_name)) {
 227 
 228 		/* FIXME This blocks and is not cancellable. */
 229 		folder = camel_store_get_folder_sync (
 230 			store, folder_name, 0, NULL, NULL);
 231 
 232 		g_object_unref (store);
 233 		g_free (folder_name);
 234 	}
 235 
 236 exit:
 237 	em_utils_compose_new_message (shell, folder);
 238 }
 239 
 240 static GtkActionEntry item_entries[] = {
 241 
 242 	{ "mail-message-new",
 243 	  "mail-message-new",
 244 	  NC_("New", "_Mail Message"),
 245 	  "<Shift><Control>m",
 246 	  N_("Compose a new mail message"),
 247 	  G_CALLBACK (action_mail_message_new_cb) }
 248 };
 249 
 250 static GtkActionEntry source_entries[] = {
 251 
 252 	{ "mail-account-new",
 253 	  "evolution-mail",
 254 	  NC_("New", "Mail Acco_unt"),
 255 	  NULL,
 256 	  N_("Create a new mail account"),
 257 	  G_CALLBACK (action_mail_account_new_cb) },
 258 
 259 	{ "mail-folder-new",
 260 	  "folder-new",
 261 	  NC_("New", "Mail _Folder"),
 262 	  NULL,
 263 	  N_("Create a new mail folder"),
 264 	  G_CALLBACK (action_mail_folder_new_cb) }
 265 };
 266 
 267 static void
 268 mail_shell_backend_sync_store_done_cb (CamelStore *store,
 269                                        gpointer user_data)
 270 {
 271 	EMailShellBackend *mail_shell_backend = user_data;
 272 
 273 	mail_shell_backend->priv->mail_sync_in_progress--;
 274 }
 275 
 276 static gboolean
 277 mail_shell_backend_mail_sync (EMailShellBackend *mail_shell_backend)
 278 {
 279 	EShell *shell;
 280 	EShellBackend *shell_backend;
 281 	EMailBackend *backend;
 282 	EMailSession *session;
 283 	GList *list, *link;
 284 
 285 	shell_backend = E_SHELL_BACKEND (mail_shell_backend);
 286 	shell = e_shell_backend_get_shell (shell_backend);
 287 
 288 	/* Obviously we can only sync in online mode. */
 289 	if (!e_shell_get_online (shell))
 290 		goto exit;
 291 
 292 	/* If a sync is still in progress, skip this round. */
 293 	if (mail_shell_backend->priv->mail_sync_in_progress)
 294 		goto exit;
 295 
 296 	backend = E_MAIL_BACKEND (mail_shell_backend);
 297 	session = e_mail_backend_get_session (backend);
 298 
 299 	list = camel_session_list_services (CAMEL_SESSION (session));
 300 
 301 	for (link = list; link != NULL; link = g_list_next (link)) {
 302 		CamelService *service;
 303 
 304 		service = CAMEL_SERVICE (link->data);
 305 
 306 		if (!CAMEL_IS_STORE (service))
 307 			continue;
 308 
 309 		mail_shell_backend->priv->mail_sync_in_progress++;
 310 
 311 		mail_sync_store (
 312 			CAMEL_STORE (service), FALSE,
 313 			mail_shell_backend_sync_store_done_cb,
 314 			mail_shell_backend);
 315 	}
 316 
 317 	g_list_free_full (list, (GDestroyNotify) g_object_unref);
 318 
 319 exit:
 320 	return TRUE;
 321 }
 322 
 323 static gboolean
 324 mail_shell_backend_handle_uri_cb (EShell *shell,
 325                                   const gchar *uri,
 326                                   EMailShellBackend *mail_shell_backend)
 327 {
 328 	gboolean handled = FALSE;
 329 
 330 	if (g_str_has_prefix (uri, "mailto:")) {
 331 		em_utils_compose_new_message_with_mailto (shell, uri, NULL);
 332 		handled = TRUE;
 333 	}
 334 
 335 	return handled;
 336 }
 337 
 338 static void
 339 mail_shell_backend_prepare_for_quit_cb (EShell *shell,
 340                                         EActivity *activity,
 341                                         EShellBackend *shell_backend)
 342 {
 343 	EMailShellBackendPrivate *priv;
 344 
 345 	priv = E_MAIL_SHELL_BACKEND_GET_PRIVATE (shell_backend);
 346 
 347 	/* Prevent a sync from starting while trying to shutdown. */
 348 	if (priv->mail_sync_source_id > 0) {
 349 		g_source_remove (priv->mail_sync_source_id);
 350 		priv->mail_sync_source_id = 0;
 351 	}
 352 }
 353 
 354 static void
 355 mail_shell_backend_window_weak_notify_cb (EShell *shell,
 356                                           GObject *where_the_object_was)
 357 {
 358 	g_signal_handlers_disconnect_by_func (
 359 		shell, mail_shell_backend_mail_icon_cb,
 360 		where_the_object_was);
 361 }
 362 
 363 static void
 364 mail_shell_backend_window_added_cb (GtkApplication *application,
 365                                     GtkWindow *window,
 366                                     EShellBackend *shell_backend)
 367 {
 368 	EShell *shell = E_SHELL (application);
 369 	EMailBackend *backend;
 370 	EMailSession *session;
 371 	const gchar *backend_name;
 372 
 373 	backend = E_MAIL_BACKEND (shell_backend);
 374 	session = e_mail_backend_get_session (backend);
 375 
 376 	/* This applies to both the composer and signature editor. */
 377 	if (GTKHTML_IS_EDITOR (window)) {
 378 		EShellSettings *shell_settings;
 379 		GList *spell_languages;
 380 		gboolean active = TRUE;
 381 
 382 		spell_languages = e_load_spell_languages ();
 383 		gtkhtml_editor_set_spell_languages (
 384 			GTKHTML_EDITOR (window), spell_languages);
 385 		g_list_free (spell_languages);
 386 
 387 		shell_settings = e_shell_get_shell_settings (shell);
 388 
 389 		/* Express mode does not honor this setting. */
 390 		if (!e_shell_get_express_mode (shell))
 391 			active = e_shell_settings_get_boolean (
 392 				shell_settings, "composer-format-html");
 393 
 394 		gtkhtml_editor_set_html_mode (GTKHTML_EDITOR (window), active);
 395 	}
 396 
 397 	if (E_IS_MSG_COMPOSER (window)) {
 398 		/* Start the mail backend if it isn't already.  This
 399 		 * may be necessary when opening a new composer window
 400 		 * from a shell view other than mail. */
 401 		e_shell_backend_start (shell_backend);
 402 
 403 		/* Integrate the new composer into the mail module. */
 404 		em_configure_new_composer (
 405 			E_MSG_COMPOSER (window), session);
 406 		return;
 407 	}
 408 
 409 	if (!E_IS_SHELL_WINDOW (window))
 410 		return;
 411 
 412 	backend_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name;
 413 
 414 	e_shell_window_register_new_item_actions (
 415 		E_SHELL_WINDOW (window), backend_name,
 416 		item_entries, G_N_ELEMENTS (item_entries));
 417 
 418 	e_shell_window_register_new_source_actions (
 419 		E_SHELL_WINDOW (window), backend_name,
 420 		source_entries, G_N_ELEMENTS (source_entries));
 421 
 422 	g_signal_connect_swapped (
 423 		shell, "event::mail-icon",
 424 		G_CALLBACK (mail_shell_backend_mail_icon_cb), window);
 425 
 426 	g_object_weak_ref (
 427 		G_OBJECT (window), (GWeakNotify)
 428 		mail_shell_backend_window_weak_notify_cb, shell);
 429 }
 430 
 431 static void
 432 mail_shell_backend_disconnect_done_cb (GObject *source_object,
 433                                        GAsyncResult *result,
 434                                        gpointer user_data)
 435 {
 436 	CamelService *service;
 437 	EActivity *activity;
 438 	EAlertSink *alert_sink;
 439 	GError *error = NULL;
 440 
 441 	service = CAMEL_SERVICE (source_object);
 442 	activity = E_ACTIVITY (user_data);
 443 
 444 	alert_sink = e_activity_get_alert_sink (activity);
 445 
 446 	camel_service_disconnect_finish (service, result, &error);
 447 
 448 	if (e_activity_handle_cancellation (activity, error)) {
 449 		g_error_free (error);
 450 
 451 	} else if (error != NULL) {
 452 		e_alert_submit (
 453 			alert_sink,
 454 			"mail:disconnect",
 455 			camel_service_get_display_name (service),
 456 			error->message, NULL);
 457 		g_error_free (error);
 458 
 459 	} else {
 460 		e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
 461 	}
 462 
 463 	g_object_unref (activity);
 464 }
 465 
 466 static void
 467 mail_shell_backend_changes_committed_cb (EMailConfigWindow *window,
 468                                          EMailShellBackend *mail_shell_backend)
 469 {
 470 	EMailSession *session;
 471 	EShell *shell;
 472 	EShellBackend *shell_backend;
 473 	ESource *original_source;
 474 	CamelService *service;
 475 	EActivity *activity;
 476 	GCancellable *cancellable;
 477 	GList *list, *link;
 478 	const gchar *uid;
 479 
 480 	session = e_mail_config_window_get_session (window);
 481 	original_source = e_mail_config_window_get_original_source (window);
 482 
 483 	uid = e_source_get_uid (original_source);
 484 	service = camel_session_ref_service (CAMEL_SESSION (session), uid);
 485 	g_return_if_fail (service != NULL);
 486 
 487 	shell_backend = E_SHELL_BACKEND (mail_shell_backend);
 488 
 489 	shell = e_shell_backend_get_shell (shell_backend);
 490 	list = gtk_application_get_windows (GTK_APPLICATION (shell));
 491 
 492 	activity = e_activity_new ();
 493 
 494 	/* Find an EShellWindow to serve as an EAlertSink. */
 495 	for (link = list; link != NULL; link = g_list_next (link)) {
 496 		GtkWindow *window = GTK_WINDOW (link->data);
 497 
 498 		if (E_IS_SHELL_WINDOW (window)) {
 499 			EAlertSink *alert_sink = E_ALERT_SINK (window);
 500 			e_activity_set_alert_sink (activity, alert_sink);
 501 		}
 502 	}
 503 
 504 	cancellable = camel_operation_new ();
 505 	e_activity_set_cancellable (activity, cancellable);
 506 
 507 	e_shell_backend_add_activity (shell_backend, activity);
 508 
 509 	camel_service_disconnect (
 510 		service, TRUE, G_PRIORITY_DEFAULT, cancellable,
 511 		mail_shell_backend_disconnect_done_cb, activity);
 512 
 513 	g_object_unref (cancellable);
 514 
 515 	g_object_unref (service);
 516 }
 517 
 518 static void
 519 mail_shell_backend_constructed (GObject *object)
 520 {
 521 	EShell *shell;
 522 	EShellSettings *shell_settings;
 523 	EShellBackend *shell_backend;
 524 	EMailSession *mail_session;
 525 	CamelService *vstore;
 526 	GtkWidget *preferences_window;
 527 
 528 	shell_backend = E_SHELL_BACKEND (object);
 529 	shell = e_shell_backend_get_shell (shell_backend);
 530 	shell_settings = e_shell_get_shell_settings (shell);
 531 
 532 	/* Chain up to parent's constructed() method. */
 533 	G_OBJECT_CLASS (e_mail_shell_backend_parent_class)->constructed (object);
 534 
 535 	mail_shell_backend_init_importers ();
 536 
 537 	g_signal_connect (
 538 		shell, "handle-uri",
 539 		G_CALLBACK (mail_shell_backend_handle_uri_cb),
 540 		shell_backend);
 541 
 542 	g_signal_connect (
 543 		shell, "prepare-for-quit",
 544 		G_CALLBACK (mail_shell_backend_prepare_for_quit_cb),
 545 		shell_backend);
 546 
 547 	g_signal_connect (
 548 		shell, "window-added",
 549 		G_CALLBACK (mail_shell_backend_window_added_cb),
 550 		shell_backend);
 551 
 552 	e_mail_shell_settings_init (shell_backend);
 553 
 554 	/* Setup preference widget factories */
 555 	preferences_window = e_shell_get_preferences_window (shell);
 556 
 557 	e_preferences_window_add_page (
 558 		E_PREFERENCES_WINDOW (preferences_window),
 559 		"mail-accounts",
 560 		"preferences-mail-accounts",
 561 		_("Mail Accounts"),
 562 		"mail-account-management",
 563 		em_account_prefs_new,
 564 		100);
 565 
 566 	e_preferences_window_add_page (
 567 		E_PREFERENCES_WINDOW (preferences_window),
 568 		"mail",
 569 		"preferences-mail",
 570 		_("Mail Preferences"),
 571 		"index#mail-basic",
 572 		em_mailer_prefs_new,
 573 		300);
 574 
 575 	e_preferences_window_add_page (
 576 		E_PREFERENCES_WINDOW (preferences_window),
 577 		"composer",
 578 		"preferences-composer",
 579 		_("Composer Preferences"),
 580 		"index#mail-composing",
 581 		em_composer_prefs_new,
 582 		400);
 583 
 584 	e_preferences_window_add_page (
 585 		E_PREFERENCES_WINDOW (preferences_window),
 586 		"system-network-proxy",
 587 		"preferences-system-network-proxy",
 588 		_("Network Preferences"),
 589 		NULL,
 590 		em_network_prefs_new,
 591 		500);
 592 
 593 	mail_session = e_mail_backend_get_session (E_MAIL_BACKEND (object));
 594 	vstore = camel_session_ref_service (
 595 		CAMEL_SESSION (mail_session), E_MAIL_SESSION_VFOLDER_UID);
 596 	g_return_if_fail (vstore != NULL);
 597 
 598 	g_object_bind_property (
 599 		shell_settings, "mail-enable-unmatched-search-folder",
 600 		vstore, "unmatched-enabled",
 601 		G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
 602 
 603 	g_object_unref (vstore);
 604 }
 605 
 606 static void
 607 mail_shell_backend_start (EShellBackend *shell_backend)
 608 {
 609 	EMailShellBackendPrivate *priv;
 610 	EMailBackend *backend;
 611 	EMailSession *session;
 612 	EMailAccountStore *account_store;
 613 	GError *error = NULL;
 614 
 615 	priv = E_MAIL_SHELL_BACKEND_GET_PRIVATE (shell_backend);
 616 
 617 	backend = E_MAIL_BACKEND (shell_backend);
 618 	session = e_mail_backend_get_session (backend);
 619 	account_store = e_mail_ui_session_get_account_store (E_MAIL_UI_SESSION (session));
 620 
 621 	/* XXX Should we be calling this unconditionally? */
 622 	vfolder_load_storage (session);
 623 
 624 	if (!e_mail_account_store_load_sort_order (account_store, &error)) {
 625 		g_warning ("%s: %s", G_STRFUNC, error->message);
 626 		g_error_free (error);
 627 	}
 628 
 629 	if (g_getenv ("CAMEL_FLUSH_CHANGES") != NULL)
 630 		priv->mail_sync_source_id = g_timeout_add_seconds (
 631 			mail_config_get_sync_timeout (),
 632 			(GSourceFunc) mail_shell_backend_mail_sync,
 633 			shell_backend);
 634 }
 635 
 636 static gboolean
 637 mail_shell_backend_delete_junk_policy_decision (EMailBackend *backend)
 638 {
 639 	EShell *shell;
 640 	EShellSettings *shell_settings;
 641 	GSettings *settings;
 642 	gboolean delete_junk;
 643 	gint empty_date;
 644 	gint empty_days;
 645 	gint now;
 646 
 647 	shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
 648 
 649 	settings = g_settings_new ("org.gnome.evolution.mail");
 650 	shell_settings = e_shell_get_shell_settings (shell);
 651 
 652 	now = time (NULL) / 60 / 60 / 24;
 653 
 654 	delete_junk = e_shell_settings_get_boolean (
 655 		shell_settings, "mail-empty-junk-on-exit");
 656 
 657 	/* XXX No EShellSettings properties for these keys. */
 658 
 659 	empty_date = empty_days = 0;
 660 
 661 	if (delete_junk) {
 662 		empty_days = g_settings_get_int (settings, "junk-empty-on-exit-days");
 663 		empty_date = g_settings_get_int (settings, "junk-empty-date");
 664 	}
 665 
 666 	delete_junk &= (empty_days == 0) || (empty_date + empty_days <= now);
 667 
 668 	if (delete_junk) {
 669 		g_settings_set_int (settings, "junk-empty-date", now);
 670 	}
 671 
 672 	g_object_unref (settings);
 673 
 674 	return delete_junk;
 675 }
 676 
 677 static gboolean
 678 mail_shell_backend_empty_trash_policy_decision (EMailBackend *backend)
 679 {
 680 	EShell *shell;
 681 	EShellSettings *shell_settings;
 682 	GSettings *settings;
 683 	gboolean empty_trash;
 684 	gint empty_date;
 685 	gint empty_days;
 686 	gint now;
 687 
 688 	shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
 689 
 690 	settings = g_settings_new ("org.gnome.evolution.mail");
 691 	shell_settings = e_shell_get_shell_settings (shell);
 692 
 693 	now = time (NULL) / 60 / 60 / 24;
 694 
 695 	empty_trash = e_shell_settings_get_boolean (
 696 		shell_settings, "mail-empty-trash-on-exit");
 697 
 698 	/* XXX No EShellSettings properties for these keys. */
 699 
 700 	empty_date = empty_days = 0;
 701 
 702 	if (empty_trash) {
 703 		empty_days = g_settings_get_int (settings, "trash-empty-on-exit-days");
 704 		empty_date = g_settings_get_int (settings, "trash-empty-date");
 705 	}
 706 
 707 	empty_trash &= (empty_days == 0) || (empty_date + empty_days <= now);
 708 
 709 	if (empty_trash) {
 710 		g_settings_set_int (settings, "trash-empty-date", now);
 711 	}
 712 
 713 	g_object_unref (settings);
 714 
 715 	return empty_trash;
 716 }
 717 
 718 static void
 719 mail_shell_backend_dispose (GObject *object)
 720 {
 721 	EMailShellBackendPrivate *priv;
 722 
 723 	priv = E_MAIL_SHELL_BACKEND (object)->priv;
 724 
 725 	if (priv->assistant != NULL) {
 726 		g_object_remove_weak_pointer (
 727 			G_OBJECT (priv->assistant), &priv->assistant);
 728 		priv->assistant = NULL;
 729 	}
 730 
 731 	if (priv->editor != NULL) {
 732 		g_object_remove_weak_pointer (
 733 			G_OBJECT (priv->editor), &priv->editor);
 734 		priv->editor = NULL;
 735 	}
 736 
 737 	/* Chain up to parent's dispose() method. */
 738 	G_OBJECT_CLASS (e_mail_shell_backend_parent_class)->dispose (object);
 739 }
 740 
 741 static void
 742 e_mail_shell_backend_class_init (EMailShellBackendClass *class)
 743 {
 744 	GObjectClass *object_class;
 745 	EShellBackendClass *shell_backend_class;
 746 	EMailBackendClass *mail_backend_class;
 747 
 748 	g_type_class_add_private (class, sizeof (EMailShellBackendPrivate));
 749 
 750 	object_class = G_OBJECT_CLASS (class);
 751 	object_class->constructed = mail_shell_backend_constructed;
 752 	object_class->dispose = mail_shell_backend_dispose;
 753 
 754 	shell_backend_class = E_SHELL_BACKEND_CLASS (class);
 755 	shell_backend_class->shell_view_type = E_TYPE_MAIL_SHELL_VIEW;
 756 	shell_backend_class->name = BACKEND_NAME;
 757 	shell_backend_class->aliases = "";
 758 	shell_backend_class->schemes = "mailto:email";
 759 	shell_backend_class->sort_order = 200;
 760 	shell_backend_class->preferences_page = "mail-accounts";
 761 	shell_backend_class->start = mail_shell_backend_start;
 762 
 763 	mail_backend_class = E_MAIL_BACKEND_CLASS (class);
 764 	mail_backend_class->delete_junk_policy_decision =
 765 		mail_shell_backend_delete_junk_policy_decision;
 766 	mail_backend_class->empty_trash_policy_decision =
 767 		mail_shell_backend_empty_trash_policy_decision;
 768 }
 769 
 770 static void
 771 e_mail_shell_backend_class_finalize (EMailShellBackendClass *class)
 772 {
 773 }
 774 
 775 static void
 776 e_mail_shell_backend_init (EMailShellBackend *mail_shell_backend)
 777 {
 778 	mail_shell_backend->priv =
 779 		E_MAIL_SHELL_BACKEND_GET_PRIVATE (mail_shell_backend);
 780 }
 781 
 782 void
 783 e_mail_shell_backend_type_register (GTypeModule *type_module)
 784 {
 785 	/* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
 786 	 *     function, so we have to wrap it with a public function in
 787 	 *     order to register types from a separate compilation unit. */
 788 	e_mail_shell_backend_register_type (type_module);
 789 }
 790 
 791 void
 792 e_mail_shell_backend_new_account (EMailShellBackend *mail_shell_backend,
 793                                   GtkWindow *parent)
 794 {
 795 	GtkWidget *assistant;
 796 	EMailBackend *backend;
 797 	EMailSession *session;
 798 
 799 	g_return_if_fail (mail_shell_backend != NULL);
 800 	g_return_if_fail (E_IS_MAIL_SHELL_BACKEND (mail_shell_backend));
 801 
 802 	assistant = mail_shell_backend->priv->assistant;
 803 
 804 	if (assistant != NULL) {
 805 		gtk_window_present (GTK_WINDOW (assistant));
 806 		return;
 807 	}
 808 
 809 	backend = E_MAIL_BACKEND (mail_shell_backend);
 810 	session = e_mail_backend_get_session (backend);
 811 
 812 	if (assistant == NULL)
 813 		assistant = e_mail_config_assistant_new (session);
 814 
 815 	gtk_window_set_transient_for (GTK_WINDOW (assistant), parent);
 816 	gtk_widget_show (assistant);
 817 
 818 	mail_shell_backend->priv->assistant = assistant;
 819 
 820 	g_object_add_weak_pointer (
 821 		G_OBJECT (mail_shell_backend->priv->assistant),
 822 		&mail_shell_backend->priv->assistant);
 823 }
 824 
 825 void
 826 e_mail_shell_backend_edit_account (EMailShellBackend *mail_shell_backend,
 827                                    GtkWindow *parent,
 828                                    ESource *mail_account)
 829 {
 830 	EMailShellBackendPrivate *priv;
 831 	EMailBackend *backend;
 832 	EMailSession *session;
 833 
 834 	g_return_if_fail (E_IS_MAIL_SHELL_BACKEND (mail_shell_backend));
 835 	g_return_if_fail (E_IS_SOURCE (mail_account));
 836 
 837 	priv = mail_shell_backend->priv;
 838 
 839 	backend = E_MAIL_BACKEND (mail_shell_backend);
 840 	session = e_mail_backend_get_session (backend);
 841 
 842 	if (priv->editor != NULL) {
 843 		gtk_window_present (GTK_WINDOW (priv->editor));
 844 		return;
 845 	}
 846 
 847 	priv->editor = e_mail_config_window_new (session, mail_account);
 848 	gtk_window_set_transient_for (GTK_WINDOW (priv->editor), parent);
 849 	g_object_add_weak_pointer (G_OBJECT (priv->editor), &priv->editor);
 850 
 851 	g_signal_connect (
 852 		priv->editor, "changes-committed",
 853 		G_CALLBACK (mail_shell_backend_changes_committed_cb),
 854 		mail_shell_backend);
 855 
 856 	gtk_widget_show (priv->editor);
 857 }
 858 
 859 /******************* Code below here belongs elsewhere. *******************/
 860 
 861 #include "filter/e-filter-option.h"
 862 #include "shell/e-shell-settings.h"
 863 
 864 static GSList *
 865 mail_labels_get_filter_options (gboolean include_none)
 866 {
 867 	EShell *shell;
 868 	EShellBackend *shell_backend;
 869 	EMailBackend *backend;
 870 	EMailSession *session;
 871 	EMailLabelListStore *label_store;
 872 	GtkTreeModel *model;
 873 	GtkTreeIter iter;
 874 	GSList *list = NULL;
 875 	gboolean valid;
 876 
 877 	shell = e_shell_get_default ();
 878 	shell_backend = e_shell_get_backend_by_name (shell, "mail");
 879 
 880 	backend = E_MAIL_BACKEND (shell_backend);
 881 	session = e_mail_backend_get_session (backend);
 882 	label_store = e_mail_ui_session_get_label_store (
 883 		E_MAIL_UI_SESSION (session));
 884 
 885 	if (include_none) {
 886 		struct _filter_option *option;
 887 
 888 		option = g_new0 (struct _filter_option, 1);
 889 		/* Translators: The first item in the list, to be able to set rule: [Label] [is/is-not] [None] */
 890 		option->title = g_strdup (C_("label", "None"));
 891 		option->value = g_strdup ("");
 892 		list = g_slist_prepend (list, option);
 893 	}
 894 
 895 	model = GTK_TREE_MODEL (label_store);
 896 	valid = gtk_tree_model_get_iter_first (model, &iter);
 897 
 898 	while (valid) {
 899 		struct _filter_option *option;
 900 		gchar *name, *tag;
 901 
 902 		name = e_mail_label_list_store_get_name (label_store, &iter);
 903 		tag = e_mail_label_list_store_get_tag (label_store, &iter);
 904 
 905 		if (g_str_has_prefix (tag, "$Label")) {
 906 			gchar *tmp = tag;
 907 
 908 			tag = g_strdup (tag + 6);
 909 
 910 			g_free (tmp);
 911 		}
 912 
 913 		option = g_new0 (struct _filter_option, 1);
 914 		option->title = e_str_without_underscores (name);
 915 		option->value = tag;  /* takes ownership */
 916 		list = g_slist_prepend (list, option);
 917 
 918 		g_free (name);
 919 
 920 		valid = gtk_tree_model_iter_next (model, &iter);
 921 	}
 922 
 923 	return g_slist_reverse (list);
 924 }
 925 
 926 GSList *
 927 e_mail_labels_get_filter_options (void)
 928 {
 929 	return mail_labels_get_filter_options (TRUE);
 930 }
 931 
 932 GSList *
 933 e_mail_labels_get_filter_options_without_none (void)
 934 {
 935 	return mail_labels_get_filter_options (FALSE);
 936 }
 937 
 938 static const gchar *
 939 get_filter_option_value (EFilterPart *part,
 940                          const gchar *name)
 941 {
 942 	EFilterElement *elem;
 943 	EFilterOption *opt;
 944 
 945 	g_return_val_if_fail (part != NULL, NULL);
 946 	g_return_val_if_fail (name != NULL, NULL);
 947 
 948 	elem = e_filter_part_find_element (part, name);
 949 	g_return_val_if_fail (elem != NULL, NULL);
 950 	g_return_val_if_fail (E_IS_FILTER_OPTION (elem), NULL);
 951 
 952 	opt = E_FILTER_OPTION (elem);
 953 	return e_filter_option_get_current (opt);
 954 }
 955 
 956 static void
 957 append_one_label_expr (GString *out,
 958                        const gchar *versus)
 959 {
 960 	GString *encoded;
 961 
 962 	g_return_if_fail (out != NULL);
 963 	g_return_if_fail (versus != NULL);
 964 
 965 	encoded = g_string_new ("");
 966 	camel_sexp_encode_string (encoded, versus);
 967 
 968 	g_string_append_printf (
 969 		out,
 970 		" (= (user-tag \"label\") %s) (user-flag (+ \"$Label\" %s)) (user-flag %s)",
 971 		encoded->str, encoded->str, encoded->str);
 972 
 973 	g_string_free (encoded, TRUE);
 974 }
 975 
 976 void
 977 e_mail_labels_get_filter_code (EFilterElement *element,
 978                                GString *out,
 979                                EFilterPart *part)
 980 {
 981 	const gchar *label_type, *versus;
 982 	gboolean is_not;
 983 
 984 	label_type = get_filter_option_value (part, "label-type");
 985 	versus = get_filter_option_value (part, "versus");
 986 
 987 	g_return_if_fail (label_type != NULL);
 988 	g_return_if_fail (versus != NULL);
 989 
 990 	is_not = g_str_equal (label_type, "is-not");
 991 
 992 	if (!g_str_equal (label_type, "is") && !is_not) {
 993 		g_warning ("%s: Unknown label-type: '%s'", G_STRFUNC, label_type);
 994 		return;
 995 	}
 996 
 997 	/* the 'None' item has 'is-not' inverted */
 998 	if (!*versus)
 999 		is_not = !is_not;
1000 
1001 	g_string_append (out, " (match-all (");
1002 	if (is_not)
1003 		g_string_append (out, " not (");
1004 	g_string_append (out, "or");
1005 
1006 	/* the 'None' item; "is None" means "has not set any label" */
1007 	if (!*versus) {
1008 		EShell *shell;
1009 		EShellBackend *shell_backend;
1010 		EMailBackend *backend;
1011 		EMailSession *session;
1012 		EMailLabelListStore *label_store;
1013 		GtkTreeModel *model;
1014 		GtkTreeIter iter;
1015 		gboolean valid;
1016 
1017 		shell = e_shell_get_default ();
1018 		shell_backend = e_shell_get_backend_by_name (shell, "mail");
1019 
1020 		backend = E_MAIL_BACKEND (shell_backend);
1021 		session = e_mail_backend_get_session (backend);
1022 		label_store = e_mail_ui_session_get_label_store (E_MAIL_UI_SESSION (session));
1023 
1024 		model = GTK_TREE_MODEL (label_store);
1025 		valid = gtk_tree_model_get_iter_first (model, &iter);
1026 
1027 		while (valid) {
1028 			gchar *tag;
1029 
1030 			tag = e_mail_label_list_store_get_tag (label_store, &iter);
1031 
1032 			if (g_str_has_prefix (tag, "$Label")) {
1033 				gchar *tmp = tag;
1034 
1035 				tag = g_strdup (tag + 6);
1036 
1037 				g_free (tmp);
1038 			}
1039 
1040 			append_one_label_expr (out, tag);
1041 
1042 			g_free (tag);
1043 
1044 			valid = gtk_tree_model_iter_next (model, &iter);
1045 		}
1046 	} else {
1047 		append_one_label_expr (out, versus);
1048 	}
1049 
1050 	if (is_not)
1051 		g_string_append (out, ")");
1052 	g_string_append (out, " ))");
1053 }
1054 
1055 static void
1056 message_parsed_cb (GObject *source_object,
1057                    GAsyncResult *res,
1058                    gpointer user_data)
1059 {
1060 	EMailParser *parser = E_MAIL_PARSER (source_object);
1061 	EMailPartList *parts_list;
1062 	GObject *preview = user_data;
1063 	EMailDisplay *display;
1064 	SoupSession *soup_session;
1065 	GHashTable *mails;
1066 	gchar *mail_uri;
1067 
1068 	display = g_object_get_data (preview, "mbox-imp-display");
1069 
1070 	parts_list = e_mail_parser_parse_finish (parser, res, NULL);
1071 
1072 	soup_session = webkit_get_default_session ();
1073 	mails = g_object_get_data (G_OBJECT (soup_session), "mails");
1074 	if (!mails) {
1075 		mails = g_hash_table_new_full (
1076 			g_str_hash, g_str_equal,
1077 			(GDestroyNotify) g_free, NULL);
1078 		g_object_set_data (
1079 			G_OBJECT (soup_session), "mails", mails);
1080 	}
1081 	mail_uri = e_mail_part_build_uri (
1082 		parts_list->folder, parts_list->message_uid, NULL, NULL);
1083 
1084 	g_hash_table_insert (mails, mail_uri, parts_list);
1085 
1086 	e_mail_display_set_parts_list (display, parts_list);
1087 	e_mail_display_load (display, NULL);
1088 
1089 	g_object_unref (parts_list);
1090 }
1091 
1092 /* utility functions for mbox importer */
1093 static void
1094 mbox_create_preview_cb (GObject *preview,
1095                         GtkWidget **preview_widget)
1096 {
1097 	EMailDisplay *display;
1098 
1099 	g_return_if_fail (preview != NULL);
1100 	g_return_if_fail (preview_widget != NULL);
1101 
1102 	display = g_object_new (E_TYPE_MAIL_DISPLAY, NULL);
1103 	g_object_set_data_full (
1104 		preview, "mbox-imp-display",
1105 		g_object_ref (display), g_object_unref);
1106 
1107 	*preview_widget = GTK_WIDGET (display);
1108 }
1109 
1110 static void
1111 mbox_fill_preview_cb (GObject *preview,
1112                       CamelMimeMessage *msg)
1113 {
1114 	EShell *shell;
1115 	EMailDisplay *display;
1116 	EMailParser *parser;
1117 	EMailSession *mail_session;
1118 	ESourceRegistry *registry;
1119 
1120 	g_return_if_fail (preview != NULL);
1121 	g_return_if_fail (msg != NULL);
1122 
1123 	display = g_object_get_data (preview, "mbox-imp-display");
1124 	g_return_if_fail (display != NULL);
1125 
1126 	shell = e_shell_get_default ();
1127 	registry = e_shell_get_registry (shell);
1128 	mail_session = e_mail_session_new (registry);
1129 
1130 	parser = e_mail_parser_new (CAMEL_SESSION (mail_session));
1131 	e_mail_parser_parse (
1132 		parser, NULL, msg->message_id, msg,
1133 		message_parsed_cb, NULL, preview);
1134 
1135 	g_object_unref (mail_session);
1136 }