Evolution consists of entirely too many small utility libraries, which increases linking and loading time, places a burden on higher layers of the application (e.g. modules) which has to remember to link to all the small in-tree utility libraries, and makes it difficult to generate API documentation for these utility libraries in one Gtk-Doc module. Merge the following utility libraries under the umbrella of libeutil, and enforce a single-include policy on libeutil so we can reorganize the files as desired without disrupting its pseudo-public API. libemail-utils/libemail-utils.la libevolution-utils/libevolution-utils.la filter/libfilter.la widgets/e-timezone-dialog/libetimezonedialog.la widgets/menus/libmenus.la widgets/misc/libemiscwidgets.la widgets/table/libetable.la widgets/text/libetext.la This also merges libedataserverui from the Evolution-Data-Server module, since Evolution is its only consumer nowadays, and I'd like to make some improvements to those APIs without concern for backward-compatibility. And finally, start a Gtk-Doc module for libeutil. It's going to be a project just getting all the symbols _listed_ much less _documented_. But the skeletal structure is in place and I'm off to a good start.
325 lines
8.4 KiB
C
325 lines
8.4 KiB
C
/*
|
|
* e-convert-local-mail.c
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) version 3.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with the program; if not, see <http://www.gnu.org/licenses/>
|
|
*
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <glib/gstdio.h>
|
|
#include <camel/camel.h>
|
|
|
|
#include <shell/e-shell.h>
|
|
|
|
/* Forward Declarations */
|
|
void e_convert_local_mail (EShell *shell);
|
|
|
|
static gboolean
|
|
mail_to_maildir_migration_needed (const gchar *mail_data_dir)
|
|
{
|
|
gchar *local_store;
|
|
gchar *local_outbox;
|
|
gboolean migration_needed = FALSE;
|
|
|
|
local_store = g_build_filename (mail_data_dir, "local", NULL);
|
|
local_outbox = g_build_filename (local_store, ".Outbox", NULL);
|
|
|
|
/* If this is a fresh install (no local store exists yet)
|
|
* then obviously there's nothing to migrate to Maildir. */
|
|
if (!g_file_test (local_store, G_FILE_TEST_IS_DIR))
|
|
migration_needed = FALSE;
|
|
|
|
/* Look for a Maildir Outbox folder. */
|
|
else if (!g_file_test (local_outbox, G_FILE_TEST_IS_DIR))
|
|
migration_needed = TRUE;
|
|
|
|
g_free (local_store);
|
|
g_free (local_outbox);
|
|
|
|
return migration_needed;
|
|
}
|
|
|
|
/* Folder names with '.' are converted to '_' */
|
|
static gchar *
|
|
sanitize_maildir_folder_name (gchar *folder_name)
|
|
{
|
|
gchar *maildir_folder_name;
|
|
|
|
maildir_folder_name = g_strdup (folder_name);
|
|
g_strdelimit (maildir_folder_name, ".", '_');
|
|
|
|
return maildir_folder_name;
|
|
}
|
|
|
|
static void
|
|
copy_folder (CamelStore *mail_store,
|
|
CamelStore *maildir_store,
|
|
const gchar *mail_fname,
|
|
const gchar *maildir_fname)
|
|
{
|
|
CamelFolder *fromfolder, *tofolder;
|
|
GPtrArray *uids;
|
|
|
|
fromfolder = camel_store_get_folder_sync (
|
|
mail_store, mail_fname, 0, NULL, NULL);
|
|
if (fromfolder == NULL) {
|
|
g_warning ("Cannot find mail folder %s \n", mail_fname);
|
|
return;
|
|
}
|
|
|
|
tofolder = camel_store_get_folder_sync (
|
|
maildir_store, maildir_fname,
|
|
CAMEL_STORE_FOLDER_CREATE, NULL, NULL);
|
|
if (tofolder == NULL) {
|
|
g_warning ("Cannot create maildir folder %s \n", maildir_fname);
|
|
g_object_unref (fromfolder);
|
|
return;
|
|
}
|
|
|
|
uids = camel_folder_get_uids (fromfolder);
|
|
camel_folder_transfer_messages_to_sync (
|
|
fromfolder, uids, tofolder, FALSE, NULL, NULL, NULL);
|
|
camel_folder_free_uids (fromfolder, uids);
|
|
|
|
g_object_unref (fromfolder);
|
|
g_object_unref (tofolder);
|
|
}
|
|
|
|
static void
|
|
copy_folders (CamelStore *mail_store,
|
|
CamelStore *maildir_store,
|
|
CamelFolderInfo *fi,
|
|
CamelSession *session)
|
|
{
|
|
if (fi) {
|
|
if (!g_str_has_prefix (fi->full_name, ".#evolution")) {
|
|
gchar *maildir_folder_name;
|
|
|
|
/* sanitize folder names and copy folders */
|
|
maildir_folder_name = sanitize_maildir_folder_name (fi->full_name);
|
|
copy_folder (
|
|
mail_store, maildir_store,
|
|
fi->full_name, maildir_folder_name);
|
|
g_free (maildir_folder_name);
|
|
}
|
|
|
|
if (fi->child)
|
|
copy_folders (mail_store, maildir_store, fi->child, session);
|
|
|
|
copy_folders (mail_store, maildir_store, fi->next, session);
|
|
}
|
|
}
|
|
|
|
struct MigrateStore {
|
|
CamelSession *session;
|
|
CamelStore *mail_store;
|
|
CamelStore *maildir_store;
|
|
gboolean complete;
|
|
};
|
|
|
|
static void
|
|
migrate_stores (struct MigrateStore *ms)
|
|
{
|
|
CamelFolderInfo *mail_fi;
|
|
CamelStore *mail_store = ms->mail_store;
|
|
CamelStore *maildir_store = ms->maildir_store;
|
|
|
|
mail_fi = camel_store_get_folder_info_sync (
|
|
mail_store, NULL,
|
|
CAMEL_STORE_FOLDER_INFO_RECURSIVE |
|
|
CAMEL_STORE_FOLDER_INFO_FAST |
|
|
CAMEL_STORE_FOLDER_INFO_SUBSCRIBED,
|
|
NULL, NULL);
|
|
|
|
/* FIXME progres dialog */
|
|
copy_folders (mail_store, maildir_store, mail_fi, ms->session);
|
|
ms->complete = TRUE;
|
|
}
|
|
|
|
static void
|
|
rename_mbox_dir (ESource *mbox_source,
|
|
const gchar *mail_data_dir)
|
|
{
|
|
gchar *old_mail_dir;
|
|
gchar *new_mail_dir;
|
|
gboolean need_rename;
|
|
const gchar *mbox_uid;
|
|
|
|
mbox_uid = e_source_get_uid (mbox_source);
|
|
|
|
old_mail_dir = g_build_filename (mail_data_dir, "local", NULL);
|
|
new_mail_dir = g_build_filename (mail_data_dir, mbox_uid, NULL);
|
|
|
|
/* Rename if old directory exists and new directory does not. */
|
|
need_rename =
|
|
g_file_test (old_mail_dir, G_FILE_TEST_EXISTS) &&
|
|
!g_file_test (new_mail_dir, G_FILE_TEST_EXISTS);
|
|
|
|
if (need_rename)
|
|
g_rename (old_mail_dir, new_mail_dir);
|
|
|
|
g_free (old_mail_dir);
|
|
g_free (new_mail_dir);
|
|
}
|
|
|
|
static gboolean
|
|
migrate_mbox_to_maildir (EShell *shell,
|
|
CamelSession *session,
|
|
ESource *mbox_source)
|
|
{
|
|
ESourceRegistry *registry;
|
|
ESourceExtension *extension;
|
|
const gchar *extension_name;
|
|
CamelService *mbox_service = NULL;
|
|
CamelService *maildir_service = NULL;
|
|
CamelSettings *settings;
|
|
const gchar *data_dir;
|
|
const gchar *mbox_uid;
|
|
gchar *path;
|
|
struct MigrateStore ms;
|
|
GThread *thread;
|
|
GError *error = NULL;
|
|
|
|
registry = e_shell_get_registry (shell);
|
|
|
|
data_dir = camel_session_get_user_data_dir (session);
|
|
|
|
mbox_uid = e_source_get_uid (mbox_source);
|
|
e_source_set_display_name (mbox_source, "local_mbox");
|
|
|
|
extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
|
|
extension = e_source_get_extension (mbox_source, extension_name);
|
|
|
|
e_source_backend_set_backend_name (
|
|
E_SOURCE_BACKEND (extension), "mbox");
|
|
|
|
extension_name = e_source_camel_get_extension_name ("mbox");
|
|
extension = e_source_get_extension (mbox_source, extension_name);
|
|
settings = e_source_camel_get_settings (E_SOURCE_CAMEL (extension));
|
|
|
|
path = g_build_filename (data_dir, mbox_uid, NULL);
|
|
g_object_set (settings, "path", path, NULL);
|
|
g_free (path);
|
|
|
|
e_source_registry_commit_source_sync (
|
|
registry, mbox_source, NULL, &error);
|
|
|
|
if (error == NULL)
|
|
mbox_service = camel_session_add_service (
|
|
session, mbox_uid, "mbox",
|
|
CAMEL_PROVIDER_STORE, &error);
|
|
|
|
if (error == NULL)
|
|
maildir_service = camel_session_add_service (
|
|
session, "local", "maildir",
|
|
CAMEL_PROVIDER_STORE, &error);
|
|
|
|
if (error != NULL) {
|
|
if (mbox_service != NULL)
|
|
g_object_unref (mbox_service);
|
|
if (maildir_service != NULL)
|
|
g_object_unref (maildir_service);
|
|
g_warning ("%s: %s", G_STRFUNC, error->message);
|
|
g_error_free (error);
|
|
return FALSE;
|
|
}
|
|
|
|
g_return_val_if_fail (CAMEL_IS_STORE (mbox_service), FALSE);
|
|
g_return_val_if_fail (CAMEL_IS_STORE (maildir_service), FALSE);
|
|
|
|
camel_service_set_settings (mbox_service, settings);
|
|
|
|
settings = camel_service_ref_settings (maildir_service);
|
|
|
|
path = g_build_filename (data_dir, "local", NULL);
|
|
g_object_set (settings, "path", path, NULL);
|
|
g_mkdir (path, 0700);
|
|
g_free (path);
|
|
|
|
g_object_unref (settings);
|
|
|
|
ms.mail_store = CAMEL_STORE (mbox_service);
|
|
ms.maildir_store = CAMEL_STORE (maildir_service);
|
|
ms.session = session;
|
|
ms.complete = FALSE;
|
|
|
|
thread = g_thread_new (NULL, (GThreadFunc) migrate_stores, &ms);
|
|
while (!ms.complete)
|
|
g_main_context_iteration (NULL, TRUE);
|
|
|
|
g_object_unref (mbox_service);
|
|
g_object_unref (maildir_service);
|
|
g_thread_unref (thread);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
e_convert_local_mail (EShell *shell)
|
|
{
|
|
CamelSession *session;
|
|
ESource *mbox_source;
|
|
const gchar *user_data_dir;
|
|
const gchar *user_cache_dir;
|
|
gchar *mail_data_dir;
|
|
gchar *mail_cache_dir;
|
|
gchar *local_store;
|
|
gint response;
|
|
|
|
user_data_dir = e_get_user_data_dir ();
|
|
user_cache_dir = e_get_user_cache_dir ();
|
|
|
|
mail_data_dir = g_build_filename (user_data_dir, "mail", NULL);
|
|
mail_cache_dir = g_build_filename (user_cache_dir, "mail", NULL);
|
|
|
|
if (!mail_to_maildir_migration_needed (mail_data_dir))
|
|
goto exit;
|
|
|
|
response = e_alert_run_dialog_for_args (
|
|
e_shell_get_active_window (NULL),
|
|
"mail:ask-migrate-store", NULL);
|
|
|
|
if (response == GTK_RESPONSE_CANCEL)
|
|
exit (EXIT_SUCCESS);
|
|
|
|
mbox_source = e_source_new (NULL, NULL, NULL);
|
|
|
|
rename_mbox_dir (mbox_source, mail_data_dir);
|
|
|
|
local_store = g_build_filename (mail_data_dir, "local", NULL);
|
|
|
|
if (!g_file_test (local_store, G_FILE_TEST_EXISTS))
|
|
g_mkdir_with_parents (local_store, 0700);
|
|
|
|
g_free (local_store);
|
|
|
|
session = g_object_new (
|
|
CAMEL_TYPE_SESSION,
|
|
"online", FALSE,
|
|
"user-data-dir", mail_data_dir,
|
|
"user-cache-dir", mail_cache_dir,
|
|
NULL);
|
|
|
|
migrate_mbox_to_maildir (shell, session, mbox_source);
|
|
|
|
g_object_unref (session);
|
|
|
|
g_object_unref (mbox_source);
|
|
|
|
exit:
|
|
g_free (mail_data_dir);
|
|
g_free (mail_cache_dir);
|
|
}
|