diff options
Diffstat (limited to 'modules/backup-restore/evolution-backup-tool.c')
-rw-r--r-- | modules/backup-restore/evolution-backup-tool.c | 935 |
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; +} |