aboutsummaryrefslogtreecommitdiffstats
path: root/modules/backup-restore/evolution-backup-tool.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/backup-restore/evolution-backup-tool.c')
-rw-r--r--modules/backup-restore/evolution-backup-tool.c935
1 files changed, 935 insertions, 0 deletions
diff --git a/modules/backup-restore/evolution-backup-tool.c b/modules/backup-restore/evolution-backup-tool.c
new file mode 100644
index 0000000000..38a477e00d
--- /dev/null
+++ b/modules/backup-restore/evolution-backup-tool.c
@@ -0,0 +1,935 @@
+/*
+ * evolution-backup-tool.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/>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+
+#include <libedataserver/e-data-server-util.h>
+
+#ifdef G_OS_WIN32
+#ifdef DATADIR
+#undef DATADIR
+#endif
+#include <windows.h>
+#include <conio.h>
+#ifndef PROCESS_DEP_ENABLE
+#define PROCESS_DEP_ENABLE 0x00000001
+#endif
+#ifndef PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION
+#define PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION 0x00000002
+#endif
+#endif
+
+#include "e-util/e-util-private.h"
+#include "e-util/e-util.h"
+
+#define EVOUSERDATADIR_MAGIC "#EVO_USERDATADIR#"
+
+#define EVOLUTION "evolution"
+#define EVOLUTION_DIR "$DATADIR/"
+#define EVOLUTION_DIR_FILE EVOLUTION ".dir"
+#define GCONF_DUMP_FILE "backup-restore-gconf.xml"
+#define GCONF_DIR "/apps/evolution"
+
+static gboolean backup_op = FALSE;
+static gchar *bk_file = NULL;
+static gboolean restore_op = FALSE;
+static gchar *res_file = NULL;
+static gboolean check_op = FALSE;
+static gchar *chk_file = NULL;
+static gboolean restart_arg = FALSE;
+static gboolean gui_arg = FALSE;
+static gchar **opt_remaining = NULL;
+static gint result = 0;
+static GtkWidget *progress_dialog;
+static GtkWidget *pbar;
+static gchar *txt = NULL;
+
+static GOptionEntry options[] = {
+ { "backup", '\0', 0, G_OPTION_ARG_NONE, &backup_op,
+ N_("Back up Evolution directory"), NULL },
+ { "restore", '\0', 0, G_OPTION_ARG_NONE, &restore_op,
+ N_("Restore Evolution directory"), NULL },
+ { "check", '\0', 0, G_OPTION_ARG_NONE, &check_op,
+ N_("Check Evolution Back up"), NULL },
+ { "restart", '\0', 0, G_OPTION_ARG_NONE, &restart_arg,
+ N_("Restart Evolution"), NULL },
+ { "gui", '\0', 0, G_OPTION_ARG_NONE, &gui_arg,
+ N_("With Graphical User Interface"), NULL },
+ { G_OPTION_REMAINING, '\0', 0,
+ G_OPTION_ARG_STRING_ARRAY, &opt_remaining },
+ { NULL }
+};
+
+#define d(x)
+
+#define print_and_run(x) \
+ G_STMT_START { g_message ("%s", x); system (x); } G_STMT_END
+
+static gboolean check (const gchar *filename, gboolean *is_new_format);
+
+static GString *
+replace_string (const gchar *text,
+ const gchar *find,
+ const gchar *replace)
+{
+ const gchar *p, *next;
+ GString *str;
+ gint find_len;
+
+ g_return_val_if_fail (text != NULL, NULL);
+ g_return_val_if_fail (find != NULL, NULL);
+ g_return_val_if_fail (*find, NULL);
+
+ find_len = strlen (find);
+ str = g_string_new ("");
+
+ p = text;
+ while (next = strstr (p, find), next) {
+ if (p < next)
+ g_string_append_len (str, p, next - p);
+
+ if (replace && *replace)
+ g_string_append (str, replace);
+
+ p = next + find_len;
+ }
+
+ g_string_append (str, p);
+
+ return str;
+}
+
+static const gchar *
+strip_home_dir (const gchar *dir)
+{
+ const gchar *home_dir, *res;
+
+ g_return_val_if_fail (dir != NULL, NULL);
+
+ home_dir = g_get_home_dir ();
+ g_return_val_if_fail (home_dir != NULL, dir);
+ g_return_val_if_fail (*home_dir != '\0', dir);
+
+ res = dir;
+ if (g_str_has_prefix (res, home_dir))
+ res += strlen (home_dir);
+
+ if (*res == G_DIR_SEPARATOR)
+ res++;
+
+ return res;
+}
+
+static GString *
+replace_variables (const gchar *str)
+{
+ GString *res = NULL, *use;
+ const gchar *strip_datadir, *strip_configdir;
+
+ g_return_val_if_fail (str != NULL, NULL);
+
+ strip_datadir = strip_home_dir (e_get_user_data_dir ());
+ strip_configdir = strip_home_dir (e_get_user_config_dir ());
+
+ #define repl(_find, _replace) \
+ use = replace_string (res ? res->str : str, _find, _replace); \
+ g_return_val_if_fail (use != NULL, NULL); \
+ if (res) \
+ g_string_free (res, TRUE); \
+ res = use;
+
+ repl ("$HOME", g_get_home_dir ());
+ repl ("$TMP", g_get_tmp_dir ());
+ repl ("$DATADIR", e_get_user_data_dir ());
+ repl ("$CONFIGDIR", e_get_user_config_dir ());
+ repl ("$STRIPDATADIR", strip_datadir);
+ repl ("$STRIPCONFIGDIR", strip_configdir);
+
+ #undef repl
+
+ g_return_val_if_fail (res != NULL, NULL);
+
+ /* remove trailing dir separator */
+ while (res->len > 0 && res->str[res->len - 1] == G_DIR_SEPARATOR) {
+ g_string_truncate (res, res->len - 1);
+ }
+
+ return res;
+}
+
+static void
+replace_in_file (const gchar *filename,
+ const gchar *find,
+ const gchar *replace)
+{
+ gchar *content = NULL;
+ GError *error = NULL;
+ GString *filenamestr = NULL;
+
+ g_return_if_fail (filename != NULL);
+ g_return_if_fail (find != NULL);
+ g_return_if_fail (*find);
+ g_return_if_fail (replace != NULL);
+
+ if (strstr (filename, "$")) {
+ filenamestr = replace_variables (filename);
+
+ if (!filenamestr) {
+ g_warning (
+ "%s: Replace variables in '%s' failed!",
+ G_STRFUNC, filename);
+ return;
+ }
+
+ filename = filenamestr->str;
+ }
+
+ if (g_file_get_contents (filename, &content, NULL, &error)) {
+ GString *str = replace_string (content, find, replace);
+
+ if (str) {
+ if (!g_file_set_contents (filename, str->str, -1, &error) && error) {
+ g_warning (
+ "%s: cannot write file content, "
+ "error: %s", G_STRFUNC, error->message);
+ g_error_free (error);
+ }
+
+ g_string_free (str, TRUE);
+ } else {
+ g_warning (
+ "%s: Replace of '%s' to '%s' failed!",
+ G_STRFUNC, find, replace);
+ }
+
+ g_free (content);
+ } else if (error) {
+ g_warning (
+ "%s: Cannot read file content, error: %s",
+ G_STRFUNC, error->message);
+ g_error_free (error);
+ }
+
+ if (filenamestr)
+ g_string_free (filenamestr, TRUE);
+}
+
+static void
+run_cmd (const gchar *cmd)
+{
+ if (!cmd)
+ return;
+
+ if (strstr (cmd, "$") != NULL) {
+ /* read the doc for g_get_home_dir to know why replacing it here */
+ GString *str = replace_variables (cmd);
+
+ if (str) {
+ print_and_run (str->str);
+ g_string_free (str, TRUE);
+ }
+ } else
+ print_and_run (cmd);
+}
+
+static void
+run_evolution_no_wait (void)
+{
+ g_spawn_command_line_async (EVOLUTION, NULL);
+}
+
+static void
+write_dir_file (void)
+{
+ GString *content, *filename;
+ GError *error = NULL;
+
+ filename = replace_variables ("$HOME/" EVOLUTION_DIR_FILE);
+ g_return_if_fail (filename != NULL);
+
+ content = replace_variables (
+ "[dirs]\n"
+ "data=$STRIPDATADIR\n"
+ "config=$STRIPCONFIGDIR\n");
+ g_return_if_fail (content != NULL);
+
+ g_file_set_contents (filename->str, content->str, content->len, &error);
+
+ if (error) {
+ g_warning ("Failed to write file '%s': %s\n", filename->str, error->message);
+ g_error_free (error);
+ }
+
+ g_string_free (filename, TRUE);
+ g_string_free (content, TRUE);
+}
+
+static void
+backup (const gchar *filename,
+ GCancellable *cancellable)
+{
+ gchar *command;
+ gchar *quotedfname;
+
+ g_return_if_fail (filename && *filename);
+ quotedfname = g_shell_quote (filename);
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ txt = _("Shutting down Evolution");
+ /* FIXME Will the versioned setting always work? */
+ run_cmd (EVOLUTION " --quit");
+
+ run_cmd ("rm $DATADIR/.running");
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ txt = _("Backing Evolution accounts and settings");
+ run_cmd ("gconftool-2 --dump " GCONF_DIR " > " EVOLUTION_DIR GCONF_DUMP_FILE);
+
+ replace_in_file (
+ EVOLUTION_DIR GCONF_DUMP_FILE,
+ e_get_user_data_dir (), EVOUSERDATADIR_MAGIC);
+
+ write_dir_file ();
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ txt = _("Backing Evolution data (Mails, Contacts, Calendar, Tasks, Memos)");
+
+ /* FIXME stay on this file system ,other options?" */
+ /* FIXME compression type?" */
+ /* FIXME date/time stamp?" */
+ /* FIXME backup location?" */
+ command = g_strdup_printf (
+ "cd $HOME && tar chf - $STRIPDATADIR "
+ "$STRIPCONFIGDIR .camel_certs " EVOLUTION_DIR_FILE " | "
+ "gzip > %s", quotedfname);
+ run_cmd (command);
+ g_free (command);
+ g_free (quotedfname);
+
+ run_cmd ("rm $HOME/" EVOLUTION_DIR_FILE);
+
+ txt = _("Back up complete");
+
+ if (restart_arg) {
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ txt = _("Restarting Evolution");
+ run_evolution_no_wait ();
+ }
+
+}
+
+static void
+extract_backup_dirs (const gchar *filename,
+ gchar **data_dir,
+ gchar **config_dir)
+{
+ GKeyFile *key_file;
+ GError *error = NULL;
+
+ g_return_if_fail (filename != NULL);
+ g_return_if_fail (data_dir != NULL);
+ g_return_if_fail (config_dir != NULL);
+
+ key_file = g_key_file_new ();
+ g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, &error);
+
+ if (error) {
+ g_warning ("Failed to read '%s': %s", filename, error->message);
+ g_error_free (error);
+ } else {
+ gchar *tmp;
+
+ tmp = g_key_file_get_value (key_file, "dirs", "data", NULL);
+ if (tmp)
+ *data_dir = g_shell_quote (tmp);
+ g_free (tmp);
+
+ tmp = g_key_file_get_value (key_file, "dirs", "config", NULL);
+ if (tmp)
+ *config_dir = g_shell_quote (tmp);
+ g_free (tmp);
+ }
+
+ g_key_file_free (key_file);
+}
+
+static gint
+get_dir_level (const gchar *dir)
+{
+ gint res = 0, i;
+
+ g_return_val_if_fail (dir != NULL, -1);
+
+ for (i = 0; dir[i]; i++) {
+ if (dir[i] == '/' || dir[i] == '\\')
+ res++;
+ }
+
+ if (i > 0)
+ res++;
+
+ return res;
+}
+
+static void
+restore (const gchar *filename,
+ GCancellable *cancellable)
+{
+ gchar *command;
+ gchar *quotedfname;
+ gboolean is_new_format = FALSE;
+
+ g_return_if_fail (filename && *filename);
+
+ if (!check (filename, &is_new_format)) {
+ g_message ("Cannot restore from an incorrect archive '%s'.", filename);
+ goto end;
+ }
+
+ quotedfname = g_shell_quote (filename);
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ /* FIXME Will the versioned setting always work? */
+ txt = _("Shutting down Evolution");
+ run_cmd (EVOLUTION " --quit");
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ txt = _("Back up current Evolution data");
+ run_cmd ("mv $DATADIR $DATADIR_old");
+ run_cmd ("mv $CONFIGDIR $CONFIGDIR_old");
+ run_cmd ("mv $HOME/.camel_certs $HOME/.camel_certs_old");
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ txt = _("Extracting files from back up");
+
+ if (is_new_format) {
+ GString *dir_fn;
+ gchar *data_dir = NULL, *config_dir = NULL;
+
+ command = g_strdup_printf (
+ "cd $TMP && tar xzf %s "
+ EVOLUTION_DIR_FILE, quotedfname);
+ run_cmd (command);
+ g_free (command);
+
+ dir_fn = replace_variables ("$TMP" G_DIR_SEPARATOR_S EVOLUTION_DIR_FILE);
+ if (!dir_fn) {
+ g_warning ("Failed to create evolution's dir filename");
+ goto end;
+ }
+
+ /* data_dir and config_dir are quoted inside extract_backup_dirs */
+ extract_backup_dirs (dir_fn->str, &data_dir, &config_dir);
+
+ g_unlink (dir_fn->str);
+ g_string_free (dir_fn, TRUE);
+
+ if (!data_dir || !config_dir) {
+ g_warning (
+ "Failed to get old data_dir (%p)/"
+ "config_dir (%p)", data_dir, config_dir);
+ g_free (data_dir);
+ g_free (config_dir);
+ goto end;
+ }
+
+ g_mkdir_with_parents (e_get_user_data_dir (), 0700);
+ g_mkdir_with_parents (e_get_user_config_dir (), 0700);
+
+ command = g_strdup_printf (
+ "cd $DATADIR && tar xzf %s %s --strip-components=%d",
+ quotedfname, data_dir, get_dir_level (data_dir));
+ run_cmd (command);
+ g_free (command);
+
+ command = g_strdup_printf (
+ "cd $CONFIGDIR && tar xzf %s %s --strip-components=%d",
+ quotedfname, config_dir, get_dir_level (config_dir));
+ run_cmd (command);
+ g_free (command);
+
+ command = g_strdup_printf (
+ "cd $HOME && tar xzf %s .camel_certs", quotedfname);
+ run_cmd (command);
+ g_free (command);
+
+ g_free (data_dir);
+ g_free (config_dir);
+ } else {
+ run_cmd ("mv $HOME/.evolution $HOME/.evolution_old");
+
+ command = g_strdup_printf (
+ "cd $HOME && gzip -cd %s | tar xf -", quotedfname);
+ run_cmd (command);
+ g_free (command);
+ }
+
+ g_free (quotedfname);
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ txt = _("Loading Evolution settings");
+
+ if (is_new_format) {
+ /* new format has it in DATADIR... */
+ replace_in_file (
+ EVOLUTION_DIR GCONF_DUMP_FILE,
+ EVOUSERDATADIR_MAGIC, e_get_user_data_dir ());
+ run_cmd ("gconftool-2 --load " EVOLUTION_DIR GCONF_DUMP_FILE);
+ run_cmd ("rm " EVOLUTION_DIR GCONF_DUMP_FILE);
+ } else {
+ gchar *gconf_dump_file;
+
+ /* ... old format in ~/.evolution */
+ gconf_dump_file = g_build_filename (
+ "$HOME", ".evolution", GCONF_DUMP_FILE, NULL);
+
+ replace_in_file (
+ gconf_dump_file,
+ EVOUSERDATADIR_MAGIC,
+ e_get_user_data_dir ());
+
+ command = g_strconcat (
+ "gconftool-2 --load ", gconf_dump_file, NULL);
+ run_cmd (command);
+ g_free (command);
+
+ command = g_strconcat ("rm ", gconf_dump_file, NULL);
+ run_cmd (command);
+ g_free (command);
+
+ g_free (gconf_dump_file);
+ }
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ txt = _("Removing temporary back up files");
+ run_cmd ("rm -rf $DATADIR_old");
+ run_cmd ("rm -rf $CONFIGDIR_old");
+ run_cmd ("rm -rf $HOME/.camel_certs_old");
+ run_cmd ("rm $DATADIR/.running");
+
+ if (!is_new_format)
+ run_cmd ("rm -rf $HOME/.evolution_old");
+
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ txt = _("Reloading registry service");
+
+ /* This runs migration routines on the newly-restored data.
+ *
+ * XXX Hard-coding the whole command like this is not ideal
+ * because the "SourcesX" interface name will occasionally
+ * change and I guarantee we'll forget to update this. */
+ run_cmd (
+ "gdbus call --session "
+ "--dest org.gnome.evolution.dataserver.Sources0 "
+ "--object-path /org/gnome/evolution/dataserver/SourceManager "
+ "--method org.gnome.evolution.dataserver.SourceManager.Reload");
+
+end:
+ if (restart_arg) {
+ if (g_cancellable_is_cancelled (cancellable))
+ return;
+
+ txt = _("Restarting Evolution");
+ run_evolution_no_wait ();
+ }
+}
+
+static gboolean
+check (const gchar *filename,
+ gboolean *is_new_format)
+{
+ gchar *command;
+ gchar *quotedfname;
+ gboolean is_new = TRUE;
+
+ g_return_val_if_fail (filename && *filename, FALSE);
+ quotedfname = g_shell_quote (filename);
+
+ if (is_new_format)
+ *is_new_format = FALSE;
+
+ command = g_strdup_printf ("tar ztf %s 1>/dev/null", quotedfname);
+ result = system (command);
+ g_free (command);
+
+ g_message ("First result %d", result);
+ if (result) {
+ g_free (quotedfname);
+ return FALSE;
+ }
+
+ command = g_strdup_printf (
+ "tar ztf %s | grep -e \"%s$\"",
+ quotedfname, EVOLUTION_DIR_FILE);
+ result = system (command);
+ g_free (command);
+
+ if (result) {
+ command = g_strdup_printf (
+ "tar ztf %s | grep -e \"^\\.evolution/$\"",
+ quotedfname);
+ result = system (command);
+ g_free (command);
+ is_new = FALSE;
+ }
+
+ g_message ("Second result %d", result);
+ if (result) {
+ g_free (quotedfname);
+ return FALSE;
+ }
+
+ if (is_new) {
+ if (is_new_format)
+ *is_new_format = TRUE;
+ g_free (quotedfname);
+ return TRUE;
+ }
+
+ command = g_strdup_printf (
+ "tar ztf %s | grep -e \"^\\.evolution/%s$\"",
+ quotedfname, GCONF_DUMP_FILE);
+ result = system (command);
+ g_free (command);
+ g_free (quotedfname);
+
+ g_message ("Third result %d", result);
+
+ return result == 0;
+}
+
+static gboolean
+pbar_update (GCancellable *cancellable)
+{
+ gtk_progress_bar_pulse ((GtkProgressBar *) pbar);
+ gtk_progress_bar_set_text ((GtkProgressBar *) pbar, txt);
+
+ /* Return TRUE to reschedule the timeout. */
+ return !g_cancellable_is_cancelled (cancellable);
+}
+
+static gboolean
+finish_job (gpointer user_data)
+{
+ gtk_main_quit ();
+
+ return FALSE;
+}
+
+static gboolean
+start_job (GIOSchedulerJob *job,
+ GCancellable *cancellable,
+ gpointer user_data)
+{
+ if (backup_op)
+ backup (bk_file, cancellable);
+ else if (restore_op)
+ restore (res_file, cancellable);
+ else if (check_op)
+ check (chk_file, NULL); /* not cancellable */
+
+ g_io_scheduler_job_send_to_mainloop_async (
+ job, finish_job, NULL, (GDestroyNotify) NULL);
+
+ return FALSE;
+}
+
+static void
+dlg_response (GtkWidget *dlg,
+ gint response,
+ GCancellable *cancellable)
+{
+ /* We will cancel only backup/restore
+ * operations and not the check operation. */
+ g_cancellable_cancel (cancellable);
+
+ /* If the response is not of delete_event then destroy the event. */
+ if (response != GTK_RESPONSE_NONE)
+ gtk_widget_destroy (dlg);
+
+ /* We will kill just the tar operation. Rest of
+ * them will be just a second of microseconds.*/
+ run_cmd ("pkill tar");
+
+ if (bk_file && backup_op && response == GTK_RESPONSE_REJECT) {
+ /* Backup was canceled, delete the
+ * backup file as it is not needed now. */
+ gchar *cmd, *filename;
+
+ g_message ("Back up canceled, removing partial back up file.");
+
+ filename = g_shell_quote (bk_file);
+ cmd = g_strconcat ("rm ", filename, NULL);
+
+ run_cmd (cmd);
+
+ g_free (cmd);
+ g_free (filename);
+ }
+
+ gtk_main_quit ();
+}
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ GCancellable *cancellable;
+ gchar *file = NULL, *oper = NULL;
+ const gchar *title = NULL;
+ gint ii;
+ GError *error = NULL;
+
+#ifdef G_OS_WIN32
+ /* Reduce risks */
+ {
+ typedef BOOL (WINAPI *t_SetDllDirectoryA) (LPCSTR lpPathName);
+ t_SetDllDirectoryA p_SetDllDirectoryA;
+
+ p_SetDllDirectoryA = GetProcAddress (
+ GetModuleHandle ("kernel32.dll"),
+ "SetDllDirectoryA");
+
+ if (p_SetDllDirectoryA != NULL)
+ p_SetDllDirectoryA ("");
+ }
+#ifndef _WIN64
+ {
+ typedef BOOL (WINAPI *t_SetProcessDEPPolicy) (DWORD dwFlags);
+ t_SetProcessDEPPolicy p_SetProcessDEPPolicy;
+
+ p_SetProcessDEPPolicy = GetProcAddress (
+ GetModuleHandle ("kernel32.dll"),
+ "SetProcessDEPPolicy");
+
+ if (p_SetProcessDEPPolicy)
+ p_SetProcessDEPPolicy (
+ PROCESS_DEP_ENABLE |
+ PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION);
+ }
+#endif
+#endif
+
+ bindtextdomain (GETTEXT_PACKAGE, EVOLUTION_LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ gtk_init_with_args (
+ &argc, &argv, NULL, options, GETTEXT_PACKAGE, &error);
+
+ if (error != NULL) {
+ g_printerr ("%s\n", error->message);
+ g_error_free (error);
+ exit (EXIT_FAILURE);
+ }
+
+ if (opt_remaining != NULL) {
+ for (ii = 0; ii < g_strv_length (opt_remaining); ii++) {
+ if (backup_op) {
+ title = _("Evolution Back Up");
+ oper = _("Backing up to the folder %s");
+ bk_file = g_strdup ((gchar *) opt_remaining[ii]);
+ file = bk_file;
+ } else if (restore_op) {
+ title = _("Evolution Restore");
+ oper = _("Restoring from the folder %s");
+ res_file = g_strdup ((gchar *) opt_remaining[ii]);
+ file = res_file;
+ } else if (check_op) {
+ d(g_message ("Checking %s", (gchar *) opt_remaining[ii]));
+ chk_file = g_strdup ((gchar *) opt_remaining[ii]);
+ }
+ }
+ }
+
+ cancellable = g_cancellable_new ();
+
+ if (gui_arg && !check_op) {
+ GtkWidget *widget, *container;
+ GtkWidget *action_area;
+ GtkWidget *content_area;
+ const gchar *txt, *txt2;
+ gchar *str = NULL;
+ gchar *markup;
+
+ gtk_window_set_default_icon_name ("evolution");
+
+ /* Backup / Restore only can have GUI.
+ * We should restrict the rest. */
+ progress_dialog = gtk_dialog_new_with_buttons (
+ title, NULL,
+ GTK_DIALOG_MODAL,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_REJECT,
+ NULL);
+
+ gtk_container_set_border_width (
+ GTK_CONTAINER (progress_dialog), 12);
+ gtk_window_set_default_size (
+ GTK_WINDOW (progress_dialog), 450, 120);
+
+ action_area = gtk_dialog_get_action_area (
+ GTK_DIALOG (progress_dialog));
+ content_area = gtk_dialog_get_content_area (
+ GTK_DIALOG (progress_dialog));
+
+ /* Override GtkDialog defaults */
+ gtk_box_set_spacing (GTK_BOX (content_area), 12);
+ gtk_container_set_border_width (GTK_CONTAINER (content_area), 0);
+ gtk_box_set_spacing (GTK_BOX (action_area), 12);
+ gtk_container_set_border_width (GTK_CONTAINER (action_area), 0);
+
+ if (oper && file)
+ str = g_strdup_printf (oper, file);
+
+ container = gtk_table_new (2, 3, FALSE);
+ gtk_table_set_col_spacings (GTK_TABLE (container), 12);
+ gtk_table_set_row_spacings (GTK_TABLE (container), 12);
+ gtk_widget_show (container);
+
+ gtk_box_pack_start (
+ GTK_BOX (content_area), container, FALSE, TRUE, 0);
+
+ widget = gtk_image_new_from_stock (
+ GTK_STOCK_COPY, GTK_ICON_SIZE_DIALOG);
+ gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
+ gtk_widget_show (widget);
+
+ gtk_table_attach (
+ GTK_TABLE (container), widget, 0, 1, 0, 3,
+ GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+
+ if (backup_op) {
+ txt = _("Backing up Evolution Data");
+ txt2 = _("Please wait while Evolution is backing up your data.");
+ } else if (restore_op) {
+ txt = _("Restoring Evolution Data");
+ txt2 = _("Please wait while Evolution is restoring your data.");
+ } else {
+ g_return_val_if_reached (EXIT_FAILURE);
+ }
+
+ markup = g_markup_printf_escaped ("<b><big>%s</big></b>", txt);
+ widget = gtk_label_new (markup);
+ gtk_label_set_line_wrap (GTK_LABEL (widget), FALSE);
+ gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
+ gtk_widget_show (widget);
+ g_free (markup);
+
+ gtk_table_attach (
+ GTK_TABLE (container), widget, 1, 2, 0, 1,
+ GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
+
+ markup = g_strconcat (
+ txt2, " ", _("This may take a while depending "
+ "on the amount of data in your account."), NULL);
+ widget = gtk_label_new (markup);
+ gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+ gtk_widget_show (widget);
+ g_free (markup);
+
+ gtk_table_attach (
+ GTK_TABLE (container), widget, 1, 2, 1, 2,
+ GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
+
+ pbar = gtk_progress_bar_new ();
+
+ if (str != NULL) {
+ markup = g_markup_printf_escaped ("<i>%s</i>", str);
+ widget = gtk_label_new (markup);
+ gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+ g_free (markup);
+ g_free (str);
+
+ gtk_table_attach (
+ GTK_TABLE (container), widget, 1, 2, 2, 3,
+ GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
+ gtk_table_set_row_spacing (GTK_TABLE (container), 2, 6);
+
+ gtk_table_attach (
+ GTK_TABLE (container), pbar, 1, 2, 3, 4,
+ GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
+ } else
+ gtk_table_attach (
+ GTK_TABLE (container), pbar, 1, 2, 2, 3,
+ GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
+
+ g_signal_connect (
+ progress_dialog, "response",
+ G_CALLBACK (dlg_response), cancellable);
+ gtk_widget_show_all (progress_dialog);
+
+ } else if (check_op) {
+ /* For sanity we don't need gui */
+ check (chk_file, NULL);
+ exit (result == 0 ? 0 : 1);
+ }
+
+ if (gui_arg)
+ g_timeout_add_full (
+ G_PRIORITY_DEFAULT, 50,
+ (GSourceFunc) pbar_update,
+ g_object_ref (cancellable),
+ (GDestroyNotify) g_object_unref);
+
+ g_io_scheduler_push_job (
+ start_job, NULL,
+ (GDestroyNotify) NULL,
+ G_PRIORITY_DEFAULT, cancellable);
+
+ gtk_main ();
+
+ g_object_unref (cancellable);
+
+ return result;
+}