void e_mail_store_foreach (EMailBackend *backend, GFunc func, gpointer user_data) { EMailSession *session; GList *list, *link; /* XXX This is a silly convenience function. * Could probably just get rid of it. */ g_return_if_fail (E_IS_MAIL_BACKEND (backend)); g_return_if_fail (func != NULL); session = e_mail_backend_get_session (backend); list = camel_session_list_services (CAMEL_SESSION (session)); for (link = list; link != NULL; link = g_list_next (link)) { CamelService *service = CAMEL_SERVICE (link->data); if (CAMEL_IS_STORE (service)) func (service, user_data); } g_list_free (list); }
void filter_gui_add_from_message (EMailBackend *backend, CamelMimeMessage *msg, const gchar *source, gint flags) { EMFilterContext *fc; const gchar *config_dir; gchar *user, *system; EFilterRule *rule; g_return_if_fail (E_IS_MAIL_BACKEND (backend)); g_return_if_fail (CAMEL_IS_MIME_MESSAGE (msg)); fc = em_filter_context_new (backend); config_dir = mail_session_get_config_dir (); user = g_build_filename (config_dir, "filters.xml", NULL); system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL); e_rule_context_load ((ERuleContext *) fc, system, user); g_free (system); rule = filter_rule_from_message (fc, msg, flags); e_filter_rule_set_source (rule, source); e_rule_context_add_rule_gui ((ERuleContext *)fc, rule, _("Add Filter Rule"), user); g_free (user); g_object_unref (fc); }
void e_mail_store_remove_by_account (EMailBackend *backend, EAccount *account) { EMailSession *session; CamelService *service; CamelProvider *provider; const gchar *uid; g_return_if_fail (E_IS_MAIL_BACKEND (backend)); g_return_if_fail (E_IS_ACCOUNT (account)); uid = account->uid; session = e_mail_backend_get_session (backend); service = camel_session_get_service (CAMEL_SESSION (session), uid); g_return_if_fail (CAMEL_IS_STORE (service)); provider = camel_service_get_provider (service); g_return_if_fail (provider != NULL); if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE)) return; e_mail_store_remove (backend, CAMEL_STORE (service)); }
void e_mail_store_add (EMailBackend *backend, CamelStore *store) { g_return_if_fail (E_IS_MAIL_BACKEND (backend)); g_return_if_fail (CAMEL_IS_STORE (store)); mail_store_add (backend, store, NULL); }
static void mail_browser_set_backend (EMailBrowser *browser, EMailBackend *backend) { g_return_if_fail (E_IS_MAIL_BACKEND (backend)); g_return_if_fail (browser->priv->backend == NULL); browser->priv->backend = g_object_ref (backend); }
void mail_filter_rename_folder (EMailBackend *backend, CamelStore *store, const gchar *old_folder_name, const gchar *new_folder_name) { EMFilterContext *fc; const gchar *config_dir; gchar *user, *system; GList *changed; gchar *old_uri; gchar *new_uri; g_return_if_fail (E_IS_MAIL_BACKEND (backend)); g_return_if_fail (CAMEL_IS_STORE (store)); g_return_if_fail (old_folder_name != NULL); g_return_if_fail (new_folder_name != NULL); old_uri = e_mail_folder_uri_build (store, old_folder_name); new_uri = e_mail_folder_uri_build (store, new_folder_name); fc = em_filter_context_new (backend); config_dir = mail_session_get_config_dir (); user = g_build_filename (config_dir, "filters.xml", NULL); system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL); e_rule_context_load ((ERuleContext *) fc, system, user); g_free (system); changed = e_rule_context_rename_uri ( (ERuleContext *) fc, old_uri, new_uri, g_str_equal); if (changed) { if (e_rule_context_save ((ERuleContext *) fc, user) == -1) g_warning("Could not write out changed filter rules\n"); e_rule_context_free_uri_list ((ERuleContext *) fc, changed); } g_free (user); g_object_unref (fc); g_free (old_uri); g_free (new_uri); }
void e_mail_store_remove (EMailBackend *backend, CamelStore *store) { EMailSession *session; MailFolderCache *folder_cache; EMFolderTreeModel *default_model; g_return_if_fail (E_IS_MAIL_BACKEND (backend)); g_return_if_fail (CAMEL_IS_STORE (store)); g_return_if_fail (store_table != NULL); session = e_mail_backend_get_session (backend); /* Because the store table holds a reference to each store used * as a key in it, none of them will ever be gc'ed, meaning any * call to camel_session_get_{service,store} with the same URL * will always return the same object. So this works. */ if (g_hash_table_lookup (store_table, store) == NULL) return; g_object_ref (store); g_hash_table_remove (store_table, store); folder_cache = e_mail_session_get_folder_cache (session); mail_folder_cache_note_store_remove (folder_cache, store); default_model = em_folder_tree_model_get_default (); em_folder_tree_model_remove_store (default_model, store); mail_disconnect_store (store); g_object_unref (store); }
void e_mail_store_init (EMailBackend *backend, const gchar *data_dir) { static gboolean initialized = FALSE; g_return_if_fail (E_IS_MAIL_BACKEND (backend)); /* This function is idempotent because mail * migration code may need to call it early. */ if (initialized) return; /* Initialize global variables. */ store_table = g_hash_table_new_full ( g_direct_hash, g_direct_equal, (GDestroyNotify) NULL, (GDestroyNotify) store_table_free); mail_store_load_accounts (backend, data_dir); initialized = TRUE; }
void mail_filter_delete_folder (EMailBackend *backend, CamelStore *store, const gchar *folder_name) { EMFilterContext *fc; const gchar *config_dir; gchar *user, *system; GList *deleted; gchar *uri; g_return_if_fail (E_IS_MAIL_BACKEND (backend)); g_return_if_fail (CAMEL_IS_STORE (store)); g_return_if_fail (folder_name != NULL); uri = e_mail_folder_uri_build (store, folder_name); fc = em_filter_context_new (backend); config_dir = mail_session_get_config_dir (); user = g_build_filename (config_dir, "filters.xml", NULL); system = g_build_filename (EVOLUTION_PRIVDATADIR, "filtertypes.xml", NULL); e_rule_context_load ((ERuleContext *) fc, system, user); g_free (system); deleted = e_rule_context_delete_uri ( (ERuleContext *) fc, uri, g_str_equal); if (deleted) { GString *s; guint s_count; gchar *info; GList *l; s = g_string_new(""); s_count = 0; for (l = deleted; l; l = l->next) { const gchar *name = (const gchar *) l->data; if (s_count == 0) { g_string_append (s, name); } else { if (s_count == 1) { g_string_prepend (s, " "); g_string_append (s, "\n"); } g_string_append_printf (s, " %s\n", name); } s_count++; } info = g_strdup_printf (ngettext ( /* Translators: The first %s is name of the affected * filter rule(s), the second %s is URI of the removed * folder. For more than one filter rule is each of * them on a separate line, with four spaces in front * of its name, without quotes. */ "The filter rule \"%s\" has been modified to account " "for the deleted folder\n\"%s\".", "The following filter rules\n%s have been modified " "to account for the deleted folder\n\"%s\".", s_count), s->str, folder_name); e_mail_backend_submit_alert ( backend, "mail:filter-updated", info, NULL); g_string_free (s, TRUE); g_free (info); if (e_rule_context_save ((ERuleContext *) fc, user) == -1) g_warning ("Could not write out changed filter rules\n"); e_rule_context_free_uri_list ((ERuleContext *) fc, deleted); } g_free (user); g_object_unref (fc); g_free (uri); }
CamelStore * e_mail_store_add_by_account (EMailBackend *backend, EAccount *account) { EMailSession *session; CamelService *service = NULL; CamelProvider *provider; CamelURL *url; gboolean skip = FALSE, transport_only; GError *error = NULL; g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), NULL); g_return_val_if_fail (E_IS_ACCOUNT (account), NULL); session = e_mail_backend_get_session (backend); /* check whether it's transport-only accounts */ transport_only = !account->source || !account->source->url || !*account->source->url; if (transport_only) goto handle_transport; /* Load the service, but don't connect. Check its provider, * and if this belongs in the folder tree model, add it. */ provider = camel_provider_get (account->source->url, &error); if (provider == NULL) { /* In case we do not have a provider here, we handle * the special case of having multiple mail identities * eg. a dummy account having just SMTP server defined */ goto handle_transport; } service = camel_session_add_service ( CAMEL_SESSION (session), account->uid, account->source->url, CAMEL_PROVIDER_STORE, &error); camel_service_set_display_name (service, account->name); handle_transport: if (account->transport) { /* While we're at it, add the account's transport to the * CamelSession. The transport's UID is a kludge for now. * We take the EAccount's UID and tack on "-transport". */ gchar *transport_uid; GError *transport_error = NULL; transport_uid = g_strconcat ( account->uid, "-transport", NULL); camel_session_add_service ( CAMEL_SESSION (session), transport_uid, account->transport->url, CAMEL_PROVIDER_TRANSPORT, &transport_error); g_free (transport_uid); if (transport_error) { g_warning ( "%s: Failed to add transport service: %s", G_STRFUNC, transport_error->message); g_error_free (transport_error); } } if (transport_only) return NULL; if (!CAMEL_IS_STORE (service)) goto fail; /* Do not add local-delivery files, * but make them ready for later use. */ url = camel_url_new (account->source->url, NULL); if (url != NULL) { skip = em_utils_is_local_delivery_mbox_file (url); camel_url_free (url); } if (!skip && (provider->flags & CAMEL_PROVIDER_IS_STORAGE)) e_mail_store_add (backend, CAMEL_STORE (service)); return CAMEL_STORE (service); fail: /* FIXME: Show an error dialog. */ g_warning ( "Couldn't get service: %s: %s", account->name, error ? error->message : "Not a CamelStore"); if (error) g_error_free (error); return NULL; }
/** * mail_vfolder_delete_folder: * @backend: an #EMailBackend * @store: a #CamelStore * @folder_name: a folder name * * Looks through all vfolder rules to see if @folder_name is listed as a * source for any vfolder rules. If the folder is found in the source for * any rule, it is removed and the user is alerted to the fact that the * vfolder rules have been updated. The new vfolder rules are written * to disk. * * XXX: It doesn't appear that the changes to the vfolder rules are sent * down to the camel level, however. So the actual vfolders will not change * behavior until evolution is restarted (?) * * NOTE: This function must be called from the main thread. */ static void mail_vfolder_delete_folder (EMailBackend *backend, CamelStore *store, const gchar *folder_name) { ERuleContext *rule_context; EFilterRule *rule; EMailSession *session; const gchar *source; CamelVeeFolder *vf; GString *changed; GQueue *queue; guint changed_count; gchar *uri; GList *link; g_return_if_fail (E_IS_MAIL_BACKEND (backend)); g_return_if_fail (CAMEL_IS_STORE (store)); g_return_if_fail (folder_name != NULL); if (folder_is_spethal (store, folder_name)) return; d(printf ("Deleting uri to check: %s\n", uri)); g_return_if_fail (mail_in_main_thread ()); session = e_mail_backend_get_session (backend); uri = e_mail_folder_uri_build (store, folder_name); changed_count = 0; changed = g_string_new (""); G_LOCK (vfolder); if (context == NULL) goto done; rule_context = E_RULE_CONTEXT (context); /* see if any rules directly reference this removed uri */ rule = NULL; while ((rule = e_rule_context_next_rule (rule_context, rule, NULL))) { EMVFolderRule *vf_rule = EM_VFOLDER_RULE (rule); if (!rule->name) continue; source = NULL; while ((source = em_vfolder_rule_next_source (vf_rule, source))) { /* Remove all sources that match, ignore changed events though * because the adduri call above does the work async */ if (e_mail_folder_uri_equal (CAMEL_SESSION (session), uri, source)) { vf = g_hash_table_lookup ( vfolder_hash, rule->name); if (!vf) { g_warning ("vf is NULL for %s\n", rule->name); continue; } g_signal_handlers_disconnect_matched ( rule, G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL, rule_changed, vf); em_vfolder_rule_remove_source (vf_rule, source); g_signal_connect ( rule, "changed", G_CALLBACK (rule_changed), vf); if (changed_count == 0) { g_string_append (changed, rule->name); } else { if (changed_count == 1) { g_string_prepend (changed, " "); g_string_append (changed, "\n"); } g_string_append_printf ( changed, " %s\n", rule->name); } changed_count++; source = NULL; } } } done: queue = &source_folders_remote; link = mv_find_folder (queue, session, uri); if (link != NULL) { g_free (link->data); g_queue_delete_link (queue, link); } queue = &source_folders_local; link = mv_find_folder (queue, session, uri); if (link != NULL) { g_free (link->data); g_queue_delete_link (queue, link); } G_UNLOCK (vfolder); if (changed_count > 0) { const gchar *config_dir; gchar *user, *info; info = g_strdup_printf (ngettext ( /* Translators: The first %s is name of the affected * search folder(s), the second %s is the URI of the * removed folder. For more than one search folder is * each of them on a separate line, with four spaces * in front of its name, without quotes. */ "The Search Folder \"%s\" has been modified to " "account for the deleted folder\n\"%s\".", "The following Search Folders\n%s have been modified " "to account for the deleted folder\n\"%s\".", changed_count), changed->str, uri); e_mail_backend_submit_alert ( backend, "mail:vfolder-updated", info, NULL); g_free (info); config_dir = mail_session_get_config_dir (); user = g_build_filename (config_dir, "vfolders.xml", NULL); e_rule_context_save ((ERuleContext *) context, user); g_free (user); } g_string_free (changed, TRUE); g_free (uri); }
void vfolder_edit_rule (EMailBackend *backend, const gchar *folder_uri) { GtkWidget *dialog; GtkWidget *widget; GtkWidget *container; EFilterRule *rule = NULL; EFilterRule *newrule; EMailSession *session; gchar *folder_name = NULL; g_return_if_fail (E_IS_MAIL_BACKEND (backend)); g_return_if_fail (folder_uri != NULL); session = e_mail_backend_get_session (backend); e_mail_folder_uri_parse ( CAMEL_SESSION (session), folder_uri, NULL, &folder_name, NULL); if (folder_name != NULL) { rule = e_rule_context_find_rule ( (ERuleContext *) context, folder_name, NULL); g_free (folder_name); } if (rule == NULL) { /* TODO: we should probably just create it ... */ e_mail_backend_submit_alert ( backend, "mail:vfolder-notexist", folder_uri, NULL); return; } g_object_ref (rule); newrule = e_filter_rule_clone (rule); dialog = gtk_dialog_new_with_buttons ( _("Edit Search Folder"), NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_container_set_border_width (GTK_CONTAINER (dialog), 6); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 500); gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE); container = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); gtk_box_set_spacing (GTK_BOX (container), 6); widget = e_filter_rule_get_widget ( (EFilterRule *) newrule, (ERuleContext *) context); gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); gtk_widget_show (widget); g_object_set_data_full (G_OBJECT (dialog), "vfolder-rule", rule, g_object_unref); g_object_set_data_full (G_OBJECT (dialog), "vfolder-newrule", newrule, g_object_unref); g_signal_connect (dialog, "response", G_CALLBACK (vfolder_edit_response_cb), NULL); gtk_widget_show (dialog); }
void vfolder_load_storage (EMailBackend *backend) { /* lock for loading storage, it is safe to call it more than once */ G_LOCK_DEFINE_STATIC (vfolder_hash); CamelService *service; const gchar *key; const gchar *data_dir; const gchar *config_dir; gchar *user, *storeuri; EFilterRule *rule; MailFolderCache *folder_cache; EMailSession *session; gchar *xmlfile; GConfClient *client; g_return_if_fail (E_IS_MAIL_BACKEND (backend)); G_LOCK (vfolder_hash); if (vfolder_hash) { /* we have already initialized */ G_UNLOCK (vfolder_hash); return; } vfolder_hash = g_hash_table_new (g_str_hash, g_str_equal); G_UNLOCK (vfolder_hash); data_dir = mail_session_get_data_dir (); config_dir = mail_session_get_config_dir (); session = e_mail_backend_get_session (backend); /* first, create the vfolder store, and set it up */ storeuri = g_strdup_printf("vfolder:%s/vfolder", data_dir); service = camel_session_add_service ( CAMEL_SESSION (session), "vfolder", storeuri, CAMEL_PROVIDER_STORE, NULL); if (service != NULL) { camel_service_set_display_name (service, _("Search Folders")); em_utils_connect_service_sync (service, NULL, NULL); } else { g_warning("Cannot open vfolder store - no vfolders available"); return; } g_return_if_fail (CAMEL_IS_STORE (service)); vfolder_store = CAMEL_STORE (service); g_signal_connect ( service, "folder-deleted", G_CALLBACK (store_folder_deleted_cb), backend); g_signal_connect ( service, "folder-renamed", G_CALLBACK (store_folder_renamed_cb), NULL); /* load our rules */ user = g_build_filename (config_dir, "vfolders.xml", NULL); context = em_vfolder_context_new (backend); xmlfile = g_build_filename (EVOLUTION_PRIVDATADIR, "vfoldertypes.xml", NULL); if (e_rule_context_load ((ERuleContext *) context, xmlfile, user) != 0) { g_warning("cannot load vfolders: %s\n", ((ERuleContext *)context)->error); } g_free (xmlfile); g_free (user); g_signal_connect ( context, "rule_added", G_CALLBACK (context_rule_added), context); g_signal_connect ( context, "rule_removed", G_CALLBACK (context_rule_removed), context); /* load store to mail component */ e_mail_store_add (backend, vfolder_store); /* and setup the rules we have */ rule = NULL; while ((rule = e_rule_context_next_rule ((ERuleContext *) context, rule, NULL))) { if (rule->name) { d(printf("rule added: %s\n", rule->name)); context_rule_added ((ERuleContext *) context, rule); } else { d(printf("invalid rule (%p) encountered: rule->name is NULL\n", rule)); } } g_free (storeuri); /* reenable the feature if required */ client = gconf_client_get_default (); key = "/apps/evolution/mail/display/enable_vfolders"; if (!gconf_client_get_bool (client, key, NULL)) gconf_client_set_bool (client, key, TRUE, NULL); g_object_unref (client); folder_cache = e_mail_session_get_folder_cache (session); g_signal_connect ( folder_cache, "folder-available", G_CALLBACK (folder_available_cb), backend); g_signal_connect ( folder_cache, "folder-unavailable", G_CALLBACK (folder_unavailable_cb), backend); g_signal_connect ( folder_cache, "folder-deleted", G_CALLBACK (folder_deleted_cb), backend); g_signal_connect ( folder_cache, "folder-renamed", G_CALLBACK (folder_renamed_cb), NULL); }