[file-roller: 106/123] use GFile instead of 'char *'



commit 34b64f3a897c4b4e8e180c028f326bc921eb08ec
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Sun Aug 5 21:04:47 2012 +0200

    use GFile instead of 'char *'

 src/actions.c               |   12 +-
 src/dlg-add-files.c         |   43 ++-
 src/dlg-add-folder.c        |  100 +++--
 src/dlg-ask-password.c      |    6 +-
 src/dlg-batch-add.c         |   80 ++--
 src/dlg-extract.c           |   28 +-
 src/dlg-prop.c              |   13 +-
 src/dlg-update.c            |   23 +-
 src/file-utils.c            |  983 ++++++++++++++++++-------------------------
 src/file-utils.h            |   59 +--
 src/fr-archive-libarchive.c |  204 +++++++---
 src/fr-archive.c            |  793 ++++++++++++++++-------------------
 src/fr-archive.h            |   74 +---
 src/fr-command-7z.c         |    2 +-
 src/fr-command-ace.c        |    2 +-
 src/fr-command-alz.c        |    2 +-
 src/fr-command-ar.c         |    2 +-
 src/fr-command-arj.c        |    2 +-
 src/fr-command-cfile.c      |   35 +-
 src/fr-command-cpio.c       |    2 +-
 src/fr-command-dpkg.c       |    2 +-
 src/fr-command-iso.c        |    9 +-
 src/fr-command-jar.c        |   16 +-
 src/fr-command-lha.c        |    2 +-
 src/fr-command-lrzip.c      |    2 +-
 src/fr-command-rar.c        |    4 +-
 src/fr-command-rpm.c        |    2 +-
 src/fr-command-tar.c        |    6 +-
 src/fr-command-unarchiver.c |    2 +-
 src/fr-command-unstuff.c    |    2 +-
 src/fr-command-zip.c        |    2 +-
 src/fr-command-zoo.c        |    2 +-
 src/fr-command.c            |  520 ++++++++++++-----------
 src/fr-init.c               |   24 +-
 src/fr-init.h               |    2 +-
 src/fr-new-archive-dialog.c |   16 +-
 src/fr-new-archive-dialog.h |    2 +-
 src/fr-process.c            |   25 ++
 src/fr-process.h            |    6 +-
 src/fr-window.c             |  969 +++++++++++++++++++------------------------
 src/fr-window.h             |   55 +--
 src/gio-utils.c             |  942 ++++++++++++++++++------------------------
 src/gio-utils.h             |  110 +++--
 src/glib-utils.c            |  175 ++++++---
 src/glib-utils.h            |   17 +-
 src/main.c                  |  154 ++++---
 src/open-file.c             |   28 +-
 src/open-file.h             |   11 +-
 src/rar-utils.c             |    2 +-
 49 files changed, 2637 insertions(+), 2937 deletions(-)
---
diff --git a/src/actions.c b/src/actions.c
index 5bc771f..ec5b835 100644
--- a/src/actions.c
+++ b/src/actions.c
@@ -76,7 +76,7 @@ open_file_response_cb (GtkWidget *w,
 		       GtkWidget *file_sel)
 {
 	FrWindow *window = NULL;
-	char     *uri;
+	GFile    *file;
 
 	if ((response == GTK_RESPONSE_CANCEL) || (response == GTK_RESPONSE_DELETE_EVENT)) {
 		gtk_widget_destroy (file_sel);
@@ -84,9 +84,9 @@ open_file_response_cb (GtkWidget *w,
 	}
 
 	window = g_object_get_data (G_OBJECT (file_sel), "fr_window");
-	uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (file_sel));
+	file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (file_sel));
 
-	if ((window == NULL) || (uri == NULL))
+	if ((window == NULL) || (file == NULL))
 		return;
 
 	if (fr_window_archive_is_present (window))
@@ -95,9 +95,9 @@ open_file_response_cb (GtkWidget *w,
 			  "archive_loaded",
 			  G_CALLBACK (window_archive_loaded_cb),
 			  file_sel);
-	fr_window_archive_open (window, uri, GTK_WINDOW (file_sel));
+	fr_window_archive_open (window, file, GTK_WINDOW (file_sel));
 
-	g_free (uri);
+	g_object_unref (file);
 }
 
 
@@ -118,7 +118,7 @@ activate_action_open (GtkAction *action,
 						NULL);
 	gtk_dialog_set_default_response (GTK_DIALOG (file_sel), GTK_RESPONSE_OK);
 	gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (file_sel), FALSE);
-	gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (file_sel), fr_window_get_open_default_dir (window));
+	gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (file_sel), fr_window_get_open_default_dir (window), NULL);
 	_gtk_dialog_add_to_window_group (GTK_DIALOG (file_sel));
 	gtk_window_set_modal (GTK_WINDOW (file_sel), TRUE);
 
diff --git a/src/dlg-add-files.c b/src/dlg-add-files.c
index afceefe..a5a1f0c 100644
--- a/src/dlg-add-files.c
+++ b/src/dlg-add-files.c
@@ -57,44 +57,50 @@ file_sel_response_cb (GtkWidget      *widget,
 {
 	GtkFileChooser *file_sel = GTK_FILE_CHOOSER (widget);
 	FrWindow       *window = data->window;
-	char           *current_folder;
-	char           *uri;
+	GFile          *current_folder;
+	GFile          *file;
 	gboolean        update;
 	GSList         *selections, *iter;
-	GList          *item_list = NULL;
+	GList          *file_list = NULL;
 
-	current_folder = gtk_file_chooser_get_current_folder_uri (file_sel);
-	uri = gtk_file_chooser_get_uri (file_sel);
+	current_folder = gtk_file_chooser_get_current_folder_file (file_sel);
+	file = gtk_file_chooser_get_file (file_sel);
 
 	if (current_folder != NULL) {
-		g_settings_set_string (data->settings, PREF_ADD_CURRENT_FOLDER, current_folder);
+		char *uri = g_file_get_uri (current_folder);
+		g_settings_set_string (data->settings, PREF_ADD_CURRENT_FOLDER, uri);
 		fr_window_set_add_default_dir (window, current_folder);
+
+		g_free (uri);
 	}
-	if (uri != NULL) {
+
+	if (file != NULL) {
+		char *uri = g_file_get_uri (file);
 		g_settings_set_string (data->settings, PREF_ADD_FILENAME, uri);
 		g_free (uri);
 	}
 
 	if ((response == GTK_RESPONSE_CANCEL) || (response == GTK_RESPONSE_DELETE_EVENT)) {
 		gtk_widget_destroy (data->dialog);
-		g_free (current_folder);
+		_g_object_unref (current_folder);
+		_g_object_unref (file);
 		return TRUE;
 	}
 
 	if (response == GTK_RESPONSE_HELP) {
 		_gtk_show_help_dialog (GTK_WINDOW (data->dialog), "archive-edit");
-		g_free (current_folder);
+		_g_object_unref (current_folder);
+		_g_object_unref (file);
 		return TRUE;
 	}
 
 	/* check folder permissions. */
 
-	if (_g_uri_query_is_dir (current_folder) && ! _g_uri_check_permissions (current_folder, R_OK)) {
+	if (_g_file_query_is_dir (current_folder) && ! _g_file_check_permissions (current_folder, R_OK)) {
 		GtkWidget *d;
 		char      *utf8_path;
 
-		utf8_path = g_filename_display_name (current_folder);
-
+		utf8_path = g_file_get_parse_name (current_folder);
 		d = _gtk_error_dialog_new (GTK_WINDOW (window),
 					   GTK_DIALOG_MODAL,
 					   NULL,
@@ -116,16 +122,17 @@ file_sel_response_cb (GtkWidget      *widget,
 	selections = gtk_file_chooser_get_uris (file_sel);
 	for (iter = selections; iter != NULL; iter = iter->next) {
 		char *uri = iter->data;
-		item_list = g_list_prepend (item_list, g_file_new_for_uri (uri));
+		file_list = g_list_prepend (file_list, g_file_new_for_uri (uri));
 	}
 
-	if (item_list != NULL)
-		fr_window_archive_add_files (window, item_list, update);
+	if (file_list != NULL)
+		fr_window_archive_add_files (window, file_list, current_folder, update);
 
-	_g_file_list_free (item_list);
+	_g_file_list_free (file_list);
 	g_slist_foreach (selections, (GFunc) g_free, NULL);
 	g_slist_free (selections);
-	g_free (current_folder);
+	_g_object_unref (current_folder);
+	_g_object_unref (file);
 
 	gtk_widget_destroy (data->dialog);
 
@@ -178,7 +185,7 @@ add_files_cb (GtkWidget *widget,
 
 	folder = g_settings_get_string (data->settings, PREF_ADD_CURRENT_FOLDER);
 	if ((folder == NULL) || (strcmp (folder, "") == 0))
-		folder = g_strdup (fr_window_get_add_default_dir (data->window));
+		folder = g_file_get_uri (fr_window_get_add_default_dir (data->window));
 	gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (file_sel), folder);
 	g_free (folder);
 
diff --git a/src/dlg-add-folder.c b/src/dlg-add-folder.c
index 4a0e239..9736371 100644
--- a/src/dlg-add-folder.c
+++ b/src/dlg-add-folder.c
@@ -90,14 +90,13 @@ file_sel_response_cb (GtkWidget    *widget,
 {
 	GtkFileChooser *file_sel = GTK_FILE_CHOOSER (widget);
 	FrWindow       *window = data->window;
-	char           *selected_folder;
+	GFile          *selected_folder;
 	gboolean        update, follow_links;
 	const char     *include_files;
 	const char     *exclude_files;
 	const char     *exclude_folders;
 	char           *dest_dir;
-	char           *local_filename;
-
+	char           *folder_basename;
 
 	dlg_add_folder_save_last_options (data);
 
@@ -111,15 +110,15 @@ file_sel_response_cb (GtkWidget    *widget,
 		return TRUE;
 	}
 
-	selected_folder = gtk_file_chooser_get_uri (file_sel);
+	selected_folder = gtk_file_chooser_get_file (file_sel);
 
 	/* check folder permissions. */
 
-	if (! _g_uri_check_permissions (selected_folder, R_OK)) {
+	if (! _g_file_check_permissions (selected_folder, R_OK)) {
 		GtkWidget *d;
 		char      *utf8_path;
 
-		utf8_path = g_filename_display_name (selected_folder);
+		utf8_path = g_file_get_parse_name (selected_folder);
 
 		d = _gtk_error_dialog_new (GTK_WINDOW (window),
 					   GTK_DIALOG_MODAL,
@@ -131,7 +130,7 @@ file_sel_response_cb (GtkWidget    *widget,
 		gtk_widget_destroy (GTK_WIDGET (d));
 
 		g_free (utf8_path);
-		g_free (selected_folder);
+		g_object_unref (selected_folder);
 
 		return FALSE;
 	}
@@ -151,23 +150,23 @@ file_sel_response_cb (GtkWidget    *widget,
 	if (utf8_only_spaces (exclude_folders))
 		exclude_folders = NULL;
 
-	local_filename = g_filename_from_uri (selected_folder, NULL, NULL);
-	dest_dir = _g_uri_build (fr_window_get_current_location (window),
-			      _g_path_get_file_name (local_filename),
-			      NULL);
-
-	fr_window_archive_add_with_wildcard (window,
-					     include_files,
-					     exclude_files,
-					     exclude_folders,
-					     selected_folder,
-					     dest_dir,
-					     update,
-					     follow_links);
-
-	g_free (local_filename);
+	folder_basename = g_file_get_basename (selected_folder);
+	dest_dir = g_build_filename (fr_window_get_current_location (window),
+			      	     folder_basename,
+			      	     NULL);
+
+	fr_window_archive_add_with_filter (window,
+					   selected_folder,
+					   include_files,
+					   exclude_files,
+					   exclude_folders,
+					   dest_dir,
+					   update,
+					   follow_links);
+
 	g_free (dest_dir);
-	g_free (selected_folder);
+	g_free (folder_basename);
+	g_object_unref (selected_folder);
 
 	gtk_widget_destroy (data->dialog);
 
@@ -353,7 +352,7 @@ add_folder_cb (GtkWidget *widget,
 			  G_CALLBACK (file_sel_response_cb),
 			  data);
 
-	gtk_window_set_modal (GTK_WINDOW (file_sel),TRUE);
+	gtk_window_set_modal (GTK_WINDOW (file_sel), TRUE);
 	gtk_widget_show (file_sel);
 }
 
@@ -366,27 +365,27 @@ dlg_add_folder_save_last_used_options (DialogData *data,
 			               const char *options_path)
 {
 	g_free (data->last_options);
-	data->last_options = g_strdup (_g_path_get_file_name (options_path));
+	data->last_options = g_strdup (_g_path_get_basename (options_path));
 }
 
 
 static void
 sync_widgets_with_options (DialogData *data,
-			   const char *base_dir,
-			   const char *filename,
+			   GFile      *directory,
+			   GFile      *file,
 			   const char *include_files,
 			   const char *exclude_files,
 			   const char *exclude_folders,
 			   gboolean    update,
 			   gboolean    no_symlinks)
 {
-	if ((base_dir == NULL) || (strcmp (base_dir, "") == 0))
-		base_dir = fr_window_get_add_default_dir (data->window);
+	if (directory == NULL)
+		directory = fr_window_get_add_default_dir (data->window);
 
-	if ((filename != NULL) && (strcmp (filename, base_dir) != 0))
-		gtk_file_chooser_select_uri (GTK_FILE_CHOOSER (data->dialog), filename);
+	if ((file != NULL) && ! g_file_equal (file, directory))
+		gtk_file_chooser_select_file (GTK_FILE_CHOOSER (data->dialog), file, NULL);
 	else
-		gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (data->dialog), base_dir);
+		gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (data->dialog), directory, NULL);
 
 	if (include_files != NULL)
 		gtk_entry_set_text (GTK_ENTRY (data->include_files_entry), include_files);
@@ -403,14 +402,22 @@ static void
 clear_options_activate_cb (GtkMenuItem *menu_item,
 			   DialogData  *data)
 {
+	GFile *folder;
+	GFile *file;
+
+	folder = gtk_file_chooser_get_current_folder_file (GTK_FILE_CHOOSER (data->dialog));
+	file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (data->dialog));
 	sync_widgets_with_options (data,
-				   gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (data->dialog)),
-				   gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (data->dialog)),
+				   folder,
+				   file,
 				   "",
 				   "",
 				   "",
 				   FALSE,
 				   FALSE);
+
+	_g_object_unref (folder);
+	_g_object_unref (file);
 }
 
 
@@ -430,6 +437,8 @@ dlg_add_folder_load_options (DialogData *data,
 	char      *exclude_folders = NULL;
 	gboolean   update;
 	gboolean   no_symlinks;
+	GFile     *folder;
+	GFile     *file;
 
 	options_dir = _g_file_new_user_config_subdir (ADD_FOLDER_OPTIONS_DIR, TRUE);
 	options_file = g_file_get_child (options_dir, name);
@@ -446,7 +455,9 @@ dlg_add_folder_load_options (DialogData *data,
 	}
 
 	base_dir = g_key_file_get_string (key_file, "Options", "base_dir", NULL);
+	folder = g_file_new_for_uri (base_dir);
 	filename = g_key_file_get_string (key_file, "Options", "filename", NULL);
+	file = g_file_new_for_uri (filename);
 	include_files = g_key_file_get_string (key_file, "Options", "include_files", NULL);
 	exclude_files = g_key_file_get_string (key_file, "Options", "exclude_files", NULL);
 	exclude_folders = g_key_file_get_string (key_file, "Options", "exclude_folders", NULL);
@@ -454,8 +465,8 @@ dlg_add_folder_load_options (DialogData *data,
 	no_symlinks = g_key_file_get_boolean (key_file, "Options", "no_symlinks", NULL);
 
 	sync_widgets_with_options (data,
-			   	   base_dir,
-			   	   filename,
+				   folder,
+			   	   file,
 			   	   include_files,
 			   	   exclude_files,
 			   	   exclude_folders,
@@ -464,6 +475,8 @@ dlg_add_folder_load_options (DialogData *data,
 
 	dlg_add_folder_save_last_used_options (data, file_path);
 
+	_g_object_unref (file);
+	_g_object_unref (folder);
 	g_free (base_dir);
 	g_free (filename);
 	g_free (include_files);
@@ -488,9 +501,13 @@ dlg_add_folder_load_last_options (DialogData *data)
 	char     *exclude_folders = NULL;
 	gboolean  update;
 	gboolean  no_symlinks;
+	GFile    *folder;
+	GFile    *file;
 
 	base_dir = g_settings_get_string (data->settings, PREF_ADD_CURRENT_FOLDER);
+	folder = g_file_new_for_uri (base_dir);
 	filename = g_settings_get_string (data->settings, PREF_ADD_FILENAME);
+	file = g_file_new_for_uri (filename);
 	include_files = g_settings_get_string (data->settings, PREF_ADD_INCLUDE_FILES);
 	exclude_files = g_settings_get_string (data->settings, PREF_ADD_EXCLUDE_FILES);
 	exclude_folders = g_settings_get_string (data->settings, PREF_ADD_EXCLUDE_FOLDERS);
@@ -498,14 +515,16 @@ dlg_add_folder_load_last_options (DialogData *data)
 	no_symlinks = g_settings_get_boolean (data->settings, PREF_ADD_NO_SYMLINKS);
 
 	sync_widgets_with_options (data,
-			   	   base_dir,
-			   	   filename,
+				   folder,
+			   	   file,
 			   	   include_files,
 			   	   exclude_files,
 			   	   exclude_folders,
 			   	   update,
 			   	   no_symlinks);
 
+	_g_object_unref (file);
+	_g_object_unref (folder);
 	g_free (base_dir);
 	g_free (filename);
 	g_free (include_files);
@@ -555,6 +574,7 @@ dlg_add_folder_save_current_options (DialogData *data,
 	gboolean    update;
 	gboolean    no_symlinks;
 	GKeyFile   *key_file;
+	GFile      *base_dir_file;
 
 	get_options_from_widgets (data,
 				  &base_dir,
@@ -565,7 +585,9 @@ dlg_add_folder_save_current_options (DialogData *data,
 				  &update,
 				  &no_symlinks);
 
-	fr_window_set_add_default_dir (data->window, base_dir);
+	base_dir_file = g_file_new_for_uri (base_dir);
+	fr_window_set_add_default_dir (data->window, base_dir_file);
+	g_object_unref (base_dir_file);
 
 	key_file = g_key_file_new ();
 	g_key_file_set_string (key_file, "Options", "base_dir", base_dir);
diff --git a/src/dlg-ask-password.c b/src/dlg-ask-password.c
index c754876..ebf7db8 100644
--- a/src/dlg-ask-password.c
+++ b/src/dlg-ask-password.c
@@ -93,6 +93,7 @@ dlg_ask_password__common (FrWindow       *window,
 			  FrPasswordType  pwd_type)
 {
 	DialogData *data;
+	GFile      *file;
 	char       *filename;
 	char       *message;
 
@@ -113,9 +114,10 @@ dlg_ask_password__common (FrWindow       *window,
 	/* Set widgets data. */
 
 	if (data->pwd_type == FR_PASSWORD_TYPE_MAIN)
-		filename = _g_uri_display_basename (fr_window_get_archive_uri (window));
+		file = fr_window_get_archive_file (window);
 	else if (data->pwd_type == FR_PASSWORD_TYPE_PASTE_FROM)
-		filename = _g_uri_display_basename (fr_window_get_paste_archive_uri (window));
+		file = fr_window_get_archive_file_for_paste (window);
+	filename = _g_file_get_display_basename (file);
 	/* Translators: %s is a filename */
 	message = g_strdup_printf (_("Password required for \"%s\""), filename);
 	gtk_label_set_label (GTK_LABEL (_gtk_builder_get_widget (data->builder, "title_label")), message);
diff --git a/src/dlg-batch-add.c b/src/dlg-batch-add.c
index 7309874..704f209 100644
--- a/src/dlg-batch-add.c
+++ b/src/dlg-batch-add.c
@@ -135,8 +135,8 @@ add_clicked_cb (GtkWidget  *widget,
 {
 	FrWindow   *window = data->window;
 	char       *archive_name;
-	char       *archive_dir;
-	char       *archive_file;
+	GFile      *archive_folder;
+	GFile      *archive_file;
 	char       *tmp;
 	const char *archive_ext;
 	const char *mime_type;
@@ -189,14 +189,13 @@ add_clicked_cb (GtkWidget  *widget,
 
 	/* Check directory existence. */
 
-	archive_dir = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (GET_WIDGET ("a_location_filechooserbutton")));
-	if (archive_dir == NULL) {
-		g_free (archive_dir);
+	archive_folder = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (GET_WIDGET ("a_location_filechooserbutton")));
+	if (archive_folder == NULL) {
 		g_free (archive_name);
 		return;
 	}
 
-	if (! _g_uri_check_permissions (archive_dir, R_OK|W_OK|X_OK)) {
+	if (! _g_file_check_permissions (archive_folder, R_OK|W_OK|X_OK)) {
 		GtkWidget  *d;
 
 		d = _gtk_error_dialog_new (GTK_WINDOW (window),
@@ -208,18 +207,18 @@ add_clicked_cb (GtkWidget  *widget,
 		gtk_dialog_run (GTK_DIALOG (d));
 		gtk_widget_destroy (GTK_WIDGET (d));
 
-		g_free (archive_dir);
+		g_object_unref (archive_folder);
 		g_free (archive_name);
 		return;
 	}
 
-	if (! _g_uri_query_is_dir (archive_dir)) {
+	if (! _g_file_query_is_dir (archive_folder)) {
 		GtkWidget *d;
 		int        r;
 		char      *folder_name;
 		char      *msg;
 
-		folder_name = g_filename_display_name (archive_dir);
+		folder_name = _g_file_get_display_basename (archive_folder);
 		msg = g_strdup_printf (_("Destination folder \"%s\" does not exist.\n\nDo you want to create it?"), folder_name);
 		g_free (folder_name);
 
@@ -241,7 +240,7 @@ add_clicked_cb (GtkWidget  *widget,
 		do_not_add = (r != GTK_RESPONSE_YES);
 	}
 
-	if (! do_not_add && ! _g_uri_ensure_dir_exists (archive_dir, 0755, &error)) {
+	if (! do_not_add && ! _g_file_make_directory_tree (archive_folder, 0755, &error)) {
 		GtkWidget  *d;
 
 		d = _gtk_error_dialog_new (GTK_WINDOW (window),
@@ -254,7 +253,7 @@ add_clicked_cb (GtkWidget  *widget,
 		gtk_widget_destroy (GTK_WIDGET (d));
 
 		g_error_free (error);
-		g_free (archive_dir);
+		g_object_unref (archive_folder);
 		g_free (archive_name);
 		return;
 	}
@@ -273,7 +272,7 @@ add_clicked_cb (GtkWidget  *widget,
 		gtk_dialog_run (GTK_DIALOG (d));
 		gtk_widget_destroy (GTK_WIDGET (d));
 
-		g_free (archive_dir);
+		g_object_unref (archive_folder);
 		g_free (archive_name);
 
 		return;
@@ -287,9 +286,9 @@ add_clicked_cb (GtkWidget  *widget,
 	tmp = archive_name;
 	archive_name = g_strconcat (tmp, archive_ext, NULL);
 	g_free (tmp);
-	archive_file = g_strconcat (archive_dir, "/", archive_name, NULL);
+	archive_file = g_file_get_child_for_display_name (archive_folder, archive_name, NULL);
 
-	if (_g_uri_query_is_dir (archive_file)) {
+	if (_g_file_query_is_dir (archive_file)) {
 		GtkWidget  *d;
 
 		d = _gtk_error_dialog_new (GTK_WINDOW (window),
@@ -302,13 +301,13 @@ add_clicked_cb (GtkWidget  *widget,
 		gtk_widget_destroy (GTK_WIDGET (d));
 
 		g_free (archive_name);
-		g_free (archive_dir);
-		g_free (archive_file);
+		g_object_unref (archive_folder);
+		g_object_unref (archive_file);
 
 		return;
 	}
 
-	if (_g_uri_query_exists (archive_file)) {
+	if (g_file_query_exists (archive_file, NULL)) {
 		GtkWidget *d;
 		int        r;
 
@@ -326,23 +325,18 @@ add_clicked_cb (GtkWidget  *widget,
 		gtk_widget_destroy (GTK_WIDGET (d));
 
 		if (r == GTK_RESPONSE_YES) {
-			GFile  *file;
 			GError *err = NULL;
 
-			file = g_file_new_for_uri (archive_file);
-			g_file_delete (file, NULL, &err);
+			g_file_delete (archive_file, NULL, &err);
 			if (err != NULL) {
-				g_warning ("Failed to delete file %s: %s",
-					   archive_file,
-					   err->message);
+				g_warning ("Failed to delete file: %s", err->message);
 				g_clear_error (&err);
 			}
-			g_object_unref (file);
 		}
 		else {
 			g_free (archive_name);
-			g_free (archive_dir);
-			g_free (archive_file);
+			g_object_unref (archive_folder);
+			g_object_unref (archive_file);
 			return;
 		}
 	}
@@ -353,8 +347,8 @@ add_clicked_cb (GtkWidget  *widget,
 	fr_window_create_archive_and_continue (window, archive_file, mime_type, NULL);
 
 	g_free (archive_name);
-	g_free (archive_dir);
-	g_free (archive_file);
+	g_object_unref (archive_folder);
+	g_object_unref (archive_file);
 }
 
 
@@ -477,8 +471,8 @@ dlg_batch_add_files (FrWindow *window,
 	GtkSizeGroup *size_group;
 	char         *automatic_name = NULL;
 	char         *default_ext;
-	const char   *first_filename;
-	char         *parent;
+	GFile        *first_file;
+	GFile        *parent;
 	int           i;
 
 	if (file_list == NULL)
@@ -495,7 +489,7 @@ dlg_batch_add_files (FrWindow *window,
 
 	data->window = window;
 	data->file_list = file_list;
-	data->single_file = ((file_list->next == NULL) && _g_uri_query_is_file ((char*) file_list->data));
+	data->single_file = ((file_list->next == NULL) && _g_file_query_is_file (G_FILE (file_list->data)));
 	data->add_clicked = FALSE;
 
 	/* Set widgets data. */
@@ -511,27 +505,23 @@ dlg_batch_add_files (FrWindow *window,
 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("a_encrypt_header_checkbutton")), g_settings_get_boolean (data->settings_general, PREF_GENERAL_ENCRYPT_HEADER));
 	gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("a_volume_spinbutton")), (double) g_settings_get_int (data->settings, PREF_BATCH_ADD_VOLUME_SIZE) / MEGABYTE);
 
-	first_filename = (char*) file_list->data;
-	parent = _g_path_remove_level (first_filename);
+	first_file = G_FILE (file_list->data);
+	parent = g_file_get_parent (first_file);
 
 	if (file_list->next == NULL)
-		automatic_name = g_uri_unescape_string (_g_path_get_file_name ((char*) file_list->data), NULL);
-	else {
-		automatic_name = g_uri_unescape_string (_g_path_get_file_name (parent), NULL);
-		if ((automatic_name == NULL) || (automatic_name[0] == '\0')) {
-			g_free (automatic_name);
-			automatic_name = g_uri_unescape_string (_g_path_get_file_name (first_filename), NULL);
-		}
-	}
+		automatic_name = g_file_get_basename (first_file);
+	else
+		automatic_name = g_file_get_basename (parent);
 
 	_gtk_entry_set_filename_text (GTK_ENTRY (GET_WIDGET ("a_add_to_entry")), automatic_name);
 	g_free (automatic_name);
 
-	if (_g_uri_check_permissions (parent, R_OK | W_OK))
-		gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (GET_WIDGET ("a_location_filechooserbutton")), parent);
+	if (_g_file_check_permissions (parent, R_OK | W_OK))
+		gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (GET_WIDGET ("a_location_filechooserbutton")), parent, NULL);
 	else
-		gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (GET_WIDGET ("a_location_filechooserbutton")), _g_uri_get_home ());
-	g_free (parent);
+		gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (GET_WIDGET ("a_location_filechooserbutton")), _g_file_get_home (), NULL);
+
+	g_object_unref (parent);
 
 	/* archive type combobox */
 
diff --git a/src/dlg-extract.c b/src/dlg-extract.c
index 417665f..30ac922 100644
--- a/src/dlg-extract.c
+++ b/src/dlg-extract.c
@@ -74,7 +74,7 @@ extract_cb (GtkWidget   *w,
 {
 	FrWindow   *window = data->window;
 	gboolean    do_not_extract = FALSE;
-	char       *extract_to_dir;
+	GFile      *destination;
 	gboolean    overwrite;
 	gboolean    skip_newer;
 	gboolean    selected_files;
@@ -88,18 +88,18 @@ extract_cb (GtkWidget   *w,
 
 	/* collect extraction options. */
 
-	extract_to_dir = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (data->dialog));
+	destination = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (data->dialog));
 
 	/* check directory existence. */
 
-	if (! _g_uri_query_is_dir (extract_to_dir)) {
+	if (! _g_file_query_is_dir (destination)) {
 		if (! ForceDirectoryCreation) {
 			GtkWidget *d;
 			int        r;
 			char      *folder_name;
 			char      *msg;
 
-			folder_name = g_filename_display_name (extract_to_dir);
+			folder_name = _g_file_get_display_basename (destination);
 			msg = g_strdup_printf (_("Destination folder \"%s\" does not exist.\n\nDo you want to create it?"), folder_name);
 			g_free (folder_name);
 
@@ -122,7 +122,7 @@ extract_cb (GtkWidget   *w,
 				do_not_extract = TRUE;
 		}
 
-		if (! do_not_extract && ! _g_uri_ensure_dir_exists (extract_to_dir, 0755, &error)) {
+		if (! do_not_extract && ! _g_file_make_directory_tree (destination, 0755, &error)) {
 			GtkWidget  *d;
 
 			d = _gtk_error_dialog_new (GTK_WINDOW (window),
@@ -162,13 +162,13 @@ extract_cb (GtkWidget   *w,
 
 	/* check extraction directory permissions. */
 
-	if (_g_uri_query_is_dir (extract_to_dir)
-	    && ! _g_uri_check_permissions (extract_to_dir, R_OK | W_OK))
+	if (_g_file_query_is_dir (destination)
+	    && ! _g_file_check_permissions (destination, R_OK | W_OK))
 	{
 		GtkWidget *d;
 		char      *utf8_path;
 
-		utf8_path = g_filename_display_name (extract_to_dir);
+		utf8_path = _g_file_get_display_basename (destination);
 
 		d = _gtk_error_dialog_new (GTK_WINDOW (window),
 					   GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -180,12 +180,12 @@ extract_cb (GtkWidget   *w,
 		gtk_widget_destroy (GTK_WIDGET (d));
 
 		g_free (utf8_path);
-		g_free (extract_to_dir);
+		g_object_unref (destination);
 
 		return FALSE;
 	}
 
-	fr_window_set_extract_default_dir (window, extract_to_dir, TRUE);
+	fr_window_set_extract_default_dir (window, destination, TRUE);
 
 	overwrite = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->e_overwrite_checkbutton));
 	skip_newer = ! gtk_toggle_button_get_inconsistent (GTK_TOGGLE_BUTTON (data->e_not_newer_checkbutton)) && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->e_not_newer_checkbutton));
@@ -214,7 +214,7 @@ extract_cb (GtkWidget   *w,
 		file_list = fr_window_get_file_list_pattern (window, pattern);
 		if (file_list == NULL) {
 			gtk_widget_destroy (data->dialog);
-			g_free (extract_to_dir);
+			g_object_unref (destination);
 			return FALSE;
 		}
 	}
@@ -234,7 +234,7 @@ extract_cb (GtkWidget   *w,
 
 	fr_window_archive_extract (window,
 				   file_list,
-				   extract_to_dir,
+				   destination,
 				   base_dir,
 				   skip_newer,
 				   overwrite ? FR_OVERWRITE_YES : FR_OVERWRITE_NO,
@@ -242,7 +242,7 @@ extract_cb (GtkWidget   *w,
 				   TRUE);
 
 	_g_string_list_free (file_list);
-	g_free (extract_to_dir);
+	g_free (destination);
 	g_free (base_dir);
 
 	return TRUE;
@@ -445,7 +445,7 @@ dlg_extract__common (FrWindow *window,
 
 	/* Set widgets data. */
 
-	gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (file_sel), fr_window_get_extract_default_dir (window));
+	gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (file_sel), fr_window_get_extract_default_dir (window), NULL);
 
 	if (data->selected_files != NULL)
 		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->e_selected_radiobutton), TRUE);
diff --git a/src/dlg-prop.c b/src/dlg-prop.c
index 64e33dc..446a668 100644
--- a/src/dlg-prop.c
+++ b/src/dlg-prop.c
@@ -51,6 +51,7 @@ dlg_prop (FrWindow *window)
 	DialogData *data;
 	GtkWidget  *ok_button;
 	GtkWidget  *label;
+	GFile      *parent;
 	char       *s;
 	goffset     size, uncompressed_size;
 	char       *utf8_name;
@@ -73,16 +74,16 @@ dlg_prop (FrWindow *window)
 	/* Set widgets data. */
 
 	label = _gtk_builder_get_widget (data->builder, "p_path_label");
-	s = _g_path_remove_level (fr_window_get_archive_uri (window));
-	utf8_name = g_filename_display_name (s);
+	parent = g_file_get_parent (fr_window_get_archive_file (window));
+	utf8_name = _g_file_get_display_basename (parent);
 	gtk_label_set_text (GTK_LABEL (label), utf8_name);
 	g_free (utf8_name);
-	g_free (s);
+	g_object_unref (parent);
 
 	/**/
 
 	label = _gtk_builder_get_widget (data->builder, "p_name_label");
-	utf8_name = _g_uri_display_basename (fr_window_get_archive_uri (window));
+	utf8_name = _g_file_get_display_basename (fr_window_get_archive_file (window));
 	gtk_label_set_text (GTK_LABEL (label), utf8_name);
 
 	title_txt = g_strdup_printf (_("%s Properties"), utf8_name);
@@ -94,14 +95,14 @@ dlg_prop (FrWindow *window)
 	/**/
 
 	label = _gtk_builder_get_widget (data->builder, "p_date_label");
-	s = _g_time_to_string (_g_uri_get_file_mtime (fr_window_get_archive_uri (window)));
+	s = _g_time_to_string (_g_file_get_file_mtime (fr_window_get_archive_file (window)));
 	gtk_label_set_text (GTK_LABEL (label), s);
 	g_free (s);
 
 	/**/
 
 	label = _gtk_builder_get_widget (data->builder, "p_size_label");
-	size = _g_uri_get_file_size (fr_window_get_archive_uri (window));
+	size = _g_file_get_file_size (fr_window_get_archive_file (window));
 	s = g_format_size (size);
 	gtk_label_set_text (GTK_LABEL (label), s);
 	g_free (s);
diff --git a/src/dlg-update.c b/src/dlg-update.c
index a1b2c8c..ba850d4 100644
--- a/src/dlg-update.c
+++ b/src/dlg-update.c
@@ -129,20 +129,21 @@ update_file_list (DialogData *data)
 
 	gtk_list_store_clear (GTK_LIST_STORE (data->list_model));
 	for (scan = data->file_list; scan; scan = scan->next) {
-		char     *utf8_name;
+		char     *display_name;
 		OpenFile *file = scan->data;
 
 		gtk_list_store_append (GTK_LIST_STORE (data->list_model),
 				       &iter);
 
-		utf8_name = g_filename_display_name (_g_path_get_file_name (file->path));
+		display_name = _g_file_get_display_basename (file->extracted_file);
 		gtk_list_store_set (GTK_LIST_STORE (data->list_model),
 				    &iter,
 				    IS_SELECTED_COLUMN, TRUE,
-				    NAME_COLUMN, utf8_name,
+				    NAME_COLUMN, display_name,
 				    DATA_COLUMN, file,
 				    -1);
-		g_free (utf8_name);
+
+		g_free (display_name);
 	}
 
 	/* update the labels */
@@ -150,16 +151,14 @@ update_file_list (DialogData *data)
 	if (n_files == 1) {
 		OpenFile *file = data->file_list->data;
 		char     *file_name;
-		char     *unescaped;
 		char     *archive_name;
 		char     *label;
 		char     *markup;
 
 		/* primary text */
 
-		file_name = g_filename_display_name (_g_path_get_file_name (file->path));
-		unescaped = g_uri_unescape_string (fr_window_get_archive_uri (data->window), NULL);
-		archive_name = g_path_get_basename (unescaped);
+		file_name = _g_file_get_display_basename (file->extracted_file);
+		archive_name = _g_file_get_display_basename (fr_window_get_archive_file (data->window));
 		label = g_markup_printf_escaped (_("Update the file \"%s\" in the archive \"%s\"?"), file_name, archive_name);
 		markup = g_strdup_printf ("<big><b>%s</b></big>", label);
 		gtk_label_set_markup (GTK_LABEL (data->update_file_primary_text_label), markup);
@@ -167,7 +166,6 @@ update_file_list (DialogData *data)
 		g_free (markup);
 		g_free (label);
 		g_free (archive_name);
-		g_free (unescaped);
 		g_free (file_name);
 
 		/* secondary text */
@@ -180,15 +178,13 @@ update_file_list (DialogData *data)
 		g_free (label);
 	}
 	else if (n_files > 1) {
-		char *unescaped;
 		char *archive_name;
 		char *label;
 		char *markup;
 
 		/* primary text */
 
-		unescaped = g_uri_unescape_string (fr_window_get_archive_uri (data->window), NULL);
-		archive_name = g_path_get_basename (unescaped);
+		archive_name = _g_file_get_display_basename (fr_window_get_archive_file (data->window));
 		label = g_markup_printf_escaped (_("Update the files in the archive \"%s\"?"), archive_name);
 		markup = g_strdup_printf ("<big><b>%s</b></big>", label);
 		gtk_label_set_markup (GTK_LABEL (data->update_files_primary_text_label), markup);
@@ -196,7 +192,6 @@ update_file_list (DialogData *data)
 		g_free (markup);
 		g_free (label);
 		g_free (archive_name);
-		g_free (unescaped);
 
 		/* secondary text */
 
@@ -393,7 +388,7 @@ dlg_update_add_file (gpointer  dialog,
 
 	for (scan = data->file_list; scan; scan = scan->next) {
 		OpenFile *test = scan->data;
-		if (_g_uri_cmp (test->extracted_uri, file->extracted_uri) == 0)
+		if (_g_file_cmp_uris (test->extracted_file, file->extracted_file) == 0)
 			return;
 	}
 
diff --git a/src/file-utils.c b/src/file-utils.c
index 8d18143..a4cdcdd 100644
--- a/src/file-utils.c
+++ b/src/file-utils.c
@@ -46,306 +46,127 @@
 #define BUF_SIZE 4096
 #define FILE_PREFIX    "file://"
 #define FILE_PREFIX_L  7
-#define SPECIAL_DIR(x) ((strcmp ((x), "..") == 0) || (strcmp ((x), ".") == 0))
+#define IS_SPECIAL_DIR(x) ((strcmp ((x), "..") == 0) || (strcmp ((x), ".") == 0))
 
 
-gboolean
-_g_uri_query_exists (const char *uri)
-{
-	GFile     *file;
-	gboolean   exists;
-
-	if (uri == NULL)
-		return FALSE;
-
-	file = g_file_new_for_uri (uri);
-	exists = g_file_query_exists (file, NULL);
-	g_object_unref (file);
-
-	return exists;
-}
-
-
-static gboolean
-_g_uri_is_filetype (const char *uri,
-		    GFileType   file_type)
-{
-	gboolean   result = FALSE;
-	GFile     *file;
-	GFileInfo *info;
-	GError    *error = NULL;
-
-	file = g_file_new_for_uri (uri);
-
-	if (! g_file_query_exists (file, NULL)) {
-		g_object_unref (file);
-		return FALSE;
-	}
-
-	info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, &error);
-	if (error == NULL) {
-		result = (g_file_info_get_file_type (info) == file_type);
-	}
-	else {
-		g_warning ("Failed to get file type for uri %s: %s", uri, error->message);
-		g_error_free (error);
-	}
-
-	g_object_unref (info);
-	g_object_unref (file);
-
-	return result;
-}
-
-
-gboolean
-_g_uri_query_is_file (const char *uri)
-{
-	return _g_uri_is_filetype (uri, G_FILE_TYPE_REGULAR);
-}
+/* path */
 
 
-gboolean
-_g_uri_query_is_dir (const char *uri)
-{
-	return _g_uri_is_filetype (uri, G_FILE_TYPE_DIRECTORY);
-}
+static const char *try_folder[] = { "cache", "~", "tmp", NULL };
 
 
-char *
-_g_uri_create_alternative (const char *folder,
-			   const char *name)
+static const char *
+get_nth_temp_folder_to_try (int n)
 {
-	char *new_uri = NULL;
-	int   n = 1;
+        const char *folder;
 
-	do {
-		g_free (new_uri);
-		if (n == 1)
-			new_uri = g_strconcat (folder, "/", name, NULL);
-		else
-			new_uri = g_strdup_printf ("%s/%s%%20(%d)", folder, name, n);
-		n++;
-	}
-	while (_g_uri_query_exists (new_uri));
+        folder = try_folder[n];
+        if (strcmp (folder, "cache") == 0)
+                folder = g_get_user_cache_dir ();
+        else if (strcmp (folder, "~") == 0)
+                folder = g_get_home_dir ();
+        else if (strcmp (folder, "tmp") == 0)
+                folder = g_get_tmp_dir ();
 
-	return new_uri;
+        return folder;
 }
 
 
 char *
-_g_uri_create_alternative_for_uri (const char *uri)
+_g_path_get_temp_work_dir (const char *parent_folder)
 {
-	char *base_uri;
-	char *new_uri;
+        guint64  max_size = 0;
+        char    *best_folder = NULL;
+        int      i;
+        char    *template;
+        char    *result = NULL;
 
-	base_uri = _g_path_remove_level (uri);
-	new_uri = _g_uri_create_alternative (base_uri, _g_path_get_file_name (uri));
-	g_free (base_uri);
+        if (parent_folder == NULL) {
+                /* find the folder with more free space. */
 
-	return new_uri;
-}
+                for (i = 0; try_folder[i] != NULL; i++) {
+                        const char *folder;
+                        GFile      *file;
+                        guint64     size;
 
+                        folder = get_nth_temp_folder_to_try (i);
+                        file = g_file_new_for_path (folder);
+                        size = _g_file_get_free_space (file);
+                        g_object_unref (file);
 
-gboolean
-_g_uri_query_dir_is_empty (const char *uri)
-{
-	GFile           *file;
-	GFileEnumerator *file_enum;
-	GFileInfo       *info;
-	GError          *error = NULL;
-	int              n = 0;
+                        if (max_size < size) {
+                                max_size = size;
+                                g_free (best_folder);
+                                best_folder = g_strdup (folder);
+                        }
+                }
+        }
+        else
+                best_folder = g_strdup (parent_folder);
 
-	file = g_file_new_for_uri (uri);
+        if (best_folder == NULL)
+                return NULL;
 
-	if (! g_file_query_exists (file, NULL)) {
-		g_object_unref (file);
-		return TRUE;
-	}
-
-	file_enum = g_file_enumerate_children (file, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, &error);
-	if (error != NULL) {
-		g_warning ("Failed to enumerate children of %s: %s", uri, error->message);
-		g_error_free (error);
-		g_object_unref (file_enum);
-		g_object_unref (file);
-		return TRUE;
-	}
-
-	while ((n == 0) && ((info = g_file_enumerator_next_file (file_enum, NULL, &error)) != NULL)) {
-		if (error != NULL) {
-			g_warning ("Encountered error while enumerating children of %s (ignoring): %s", uri, error->message);
-			g_error_free (error);
-		}
-		else if (! SPECIAL_DIR (g_file_info_get_name (info)))
-			n++;
-		g_object_unref (info);
-	}
+        template = g_strconcat (best_folder, "/.fr-XXXXXX", NULL);
+        result = mkdtemp (template);
 
-	g_object_unref (file);
-	g_object_unref (file_enum);
+        if ((result == NULL) || (*result == '\0')) {
+                g_free (template);
+                result = NULL;
+        }
 
-	return (n == 0);
+        return result;
 }
 
 
-gboolean
-_g_uri_dir_contains_one_object (const char *uri)
-{
-	GFile           *file;
-	GFileEnumerator *file_enum;
-	GFileInfo       *info;
-	GError          *err = NULL;
-	int              n = 0;
+/* GFile */
 
-	file = g_file_new_for_uri (uri);
 
-	if (! g_file_query_exists (file, NULL)) {
-		g_object_unref (file);
-		return FALSE;
-	}
+static gboolean
+_g_file_is_filetype (GFile     *file,
+		     GFileType  file_type)
+{
+	gboolean   result = FALSE;
+	GFileInfo *info;
 
-	file_enum = g_file_enumerate_children (file, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, &err);
-	if (err != NULL) {
-		g_warning ("Failed to enumerate children of %s: %s", uri, err->message);
-		g_error_free (err);
-		g_object_unref (file_enum);
-		g_object_unref (file);
+	if (! g_file_query_exists (file, NULL))
 		return FALSE;
-	}
-
-	while ((info = g_file_enumerator_next_file (file_enum, NULL, &err)) != NULL) {
-		const char *name;
-
-		if (err != NULL) {
-			g_warning ("Encountered error while enumerating children of %s, ignoring: %s", uri, err->message);
-			g_error_free (err);
-			g_object_unref (info);
-			continue;
-		}
-
-		name = g_file_info_get_name (info);
-		if (strcmp (name, ".") == 0 || strcmp (name, "..") == 0) {
-			g_object_unref (info);
- 			continue;
-		}
 
+	info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, NULL);
+	if (info != NULL) {
+		result = (g_file_info_get_file_type (info) == file_type);
 		g_object_unref (info);
-
-		if (++n > 1)
-			break;
 	}
 
-	g_object_unref (file);
-	g_object_unref (file_enum);
-
-	return (n == 1);
+	return result;
 }
 
 
-char *
-_g_uri_get_dir_content_if_unique (const char  *uri)
+gboolean
+_g_file_query_is_file (GFile *file)
 {
-	GFile           *file;
-	GFileEnumerator *file_enum;
-	GFileInfo       *info;
-	GError          *err = NULL;
-	char            *content_uri = NULL;
-
-	file = g_file_new_for_uri (uri);
-
-	if (! g_file_query_exists (file, NULL)) {
-		g_object_unref (file);
-		return NULL;
-	}
-
-	file_enum = g_file_enumerate_children (file, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, &err);
-	if (err != NULL) {
-		g_warning ("Failed to enumerate children of %s: %s", uri, err->message);
-		g_error_free (err);
-		return NULL;
-	}
-
-	while ((info = g_file_enumerator_next_file (file_enum, NULL, &err)) != NULL) {
-		const char *name;
-
-		if (err != NULL) {
-			g_warning ("Failed to get info while enumerating children: %s", err->message);
-			g_clear_error (&err);
-			g_object_unref (info);
-			continue;
-		}
-
-		name = g_file_info_get_name (info);
-		if ((strcmp (name, ".") == 0) || (strcmp (name, "..") == 0)) {
-			g_object_unref (info);
-			continue;
-		}
-
-		if (content_uri != NULL) {
-			g_free (content_uri);
-			g_object_unref (info);
-			content_uri = NULL;
-			break;
-		}
-
-		content_uri = _g_uri_build (uri, name, NULL);
-		g_object_unref (info);
-	}
-
-	if (err != NULL) {
-		g_warning ("Failed to get info after enumerating children: %s", err->message);
-		g_clear_error (&err);
-	}
-
-	g_object_unref (file_enum);
-	g_object_unref (file);
-
-	return content_uri;
+	return _g_file_is_filetype (file, G_FILE_TYPE_REGULAR);
 }
 
 
-goffset
-_g_uri_get_file_size (const char *uri)
+gboolean
+_g_file_query_is_dir (GFile *file)
 {
-	goffset    size = 0;
-	GFile     *file;
-	GFileInfo *info;
-	GError    *err = NULL;
-
-	if ((uri == NULL) || (*uri == '\0'))
-		return 0;
-
-	file = g_file_new_for_uri (uri);
-	info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE, 0, NULL, &err);
-	if (err == NULL) {
-		size = g_file_info_get_size (info);
-	}
-	else {
-		g_warning ("Failed to get file size for %s: %s", uri, err->message);
-		g_error_free (err);
-	}
-
-	g_object_unref (info);
-	g_object_unref (file);
-
-	return size;
+	return _g_file_is_filetype (file, G_FILE_TYPE_DIRECTORY);
 }
 
 
 static time_t
-_g_uri_get_file_time_type (const char *uri,
-			   const char *type)
+_g_file_get_file_time_type (GFile      *file,
+			    const char *type)
 {
 	time_t     result = 0;
-	GFile     *file;
 	GFileInfo *info;
 	GError    *err = NULL;
 
-	if ((uri == NULL) || (*uri == '\0'))
+	if (file == NULL)
  		return 0;
 
-	file = g_file_new_for_uri (uri);
 	info = g_file_query_info (file, type, 0, NULL, &err);
 	if (err == NULL) {
 		result = (time_t) g_file_info_get_attribute_uint64 (info, type);
@@ -357,398 +178,145 @@ _g_uri_get_file_time_type (const char *uri,
 	}
 
 	g_object_unref (info);
-	g_object_unref (file);
 
 	return result;
 }
 
 
-time_t
-_g_uri_get_file_mtime (const char *uri)
-{
-	return _g_uri_get_file_time_type (uri, G_FILE_ATTRIBUTE_TIME_MODIFIED);
-}
-
-
-time_t
-_g_uri_get_file_ctime (const char *uri)
-{
-	return _g_uri_get_file_time_type (uri, G_FILE_ATTRIBUTE_TIME_CREATED);
-}
-
-
-gboolean
-_g_uri_ensure_dir_exists (const char  *uri,
-			  mode_t       mode,
-			  GError     **error)
-{
-	GFile  *dir;
-	GError *priv_error = NULL;
-
-	if (uri == NULL)
-		return FALSE;
-
-	if (error == NULL)
-		error = &priv_error;
-
-	dir = g_file_new_for_uri (uri);
-	if (! _g_file_make_directory_tree (dir, mode, error)) {
-		g_warning ("could create directory %s: %s", uri, (*error)->message);
-		if (priv_error != NULL)
-			g_clear_error (&priv_error);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-
-const char *
-_g_uri_get_mime_type (const char *uri,
-                      gboolean    fast_file_type)
-{
-	GFile      *file;
-	GFileInfo  *info;
-	GError     *err = NULL;
- 	const char *result = NULL;
-
- 	file = g_file_new_for_uri (uri);
-	info = g_file_query_info (file,
-				  fast_file_type ?
-				  G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE :
-				  G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
-				  0, NULL, &err);
-	if (info == NULL) {
-		g_warning ("could not get content type for %s: %s", uri, err->message);
-		g_clear_error (&err);
-	}
-	else {
-		result = _g_str_get_static (g_file_info_get_content_type (info));
-		g_object_unref (info);
-	}
-
-	g_object_unref (file);
-
-	return result;
-}
-
-
-/* -- _g_uri_remove_directory -- */
-
-
-static gboolean
-delete_directory_recursive (GFile   *dir,
-			    GError **error)
+goffset
+_g_file_get_file_size (GFile *file)
 {
-	char            *uri;
-	GFileEnumerator *file_enum;
-	GFileInfo       *info;
-	gboolean         error_occurred = FALSE;
-
-	if (error != NULL)
-		*error = NULL;
-
-	file_enum = g_file_enumerate_children (dir,
-					       G_FILE_ATTRIBUTE_STANDARD_NAME ","
-					       G_FILE_ATTRIBUTE_STANDARD_TYPE,
-					       0, NULL, error);
-
-	uri = g_file_get_uri (dir);
-	while (! error_occurred && (info = g_file_enumerator_next_file (file_enum, NULL, error)) != NULL) {
-		char  *child_uri;
-		GFile *child;
-
-		child_uri = _g_uri_build (uri, g_file_info_get_name (info), NULL);
-		child = g_file_new_for_uri (child_uri);
+	goffset    size = 0;
+	GFileInfo *info;
+	GError    *error = NULL;
 
-		switch (g_file_info_get_file_type (info)) {
-		case G_FILE_TYPE_DIRECTORY:
-			if (! delete_directory_recursive (child, error))
-				error_occurred = TRUE;
-			break;
-		default:
-			if (! g_file_delete (child, NULL, error))
-				error_occurred = TRUE;
-			break;
-		}
+	if (file == NULL)
+		return 0;
 
-		g_object_unref (child);
-		g_free (child_uri);
+	info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE, 0, NULL, &error);
+	if (info != NULL) {
+		size = g_file_info_get_size (info);
 		g_object_unref (info);
 	}
-	g_free (uri);
-
-	if (! error_occurred && ! g_file_delete (dir, NULL, error))
- 		error_occurred = TRUE;
-
-	g_object_unref (file_enum);
-
-	return ! error_occurred;
-}
-
-
-gboolean
-_g_uri_remove_directory (const char *uri)
-{
-	GFile     *dir;
-	gboolean   result;
-	GError    *error = NULL;
-
-	dir = g_file_new_for_uri (uri);
-	result = delete_directory_recursive (dir, &error);
-	if (! result) {
-		g_warning ("Cannot delete %s: %s", uri, error->message);
-		g_clear_error (&error);
+	else {
+		g_warning ("%s", error->message);
+		g_error_free (error);
 	}
-	g_object_unref (dir);
-
-	return result;
-}
-
-
-gboolean
-_g_uri_check_permissions (const char *uri,
-		   int         mode)
-{
-	GFile    *file;
-	gboolean  result;
-
-	file = g_file_new_for_uri (uri);
-	result = _g_file_check_permissions (file, mode);
-
-	g_object_unref (file);
 
-	return result;
-}
-
-
-/* path */
-
-
-gboolean
-_g_path_query_is_dir (const char *path)
-{
-	char     *uri;
-	gboolean  result;
-
-	uri = g_filename_to_uri (path, NULL, NULL);
-	result = _g_uri_query_is_dir (uri);
-	g_free (uri);
-
-	return result;
-}
-
-
-goffset
-_g_path_get_file_size (const char *path)
-{
-	char    *uri;
-	goffset  result;
-
-	uri = g_filename_to_uri (path, NULL, NULL);
-	result = _g_uri_get_file_size (uri);
-	g_free (uri);
-
-	return result;
-}
-
-
-time_t
-_g_path_get_file_mtime (const char *path)
-{
-	char   *uri;
-	time_t  result;
-
-	uri = g_filename_to_uri (path, NULL, NULL);
-	result = _g_uri_get_file_mtime (uri);
-	g_free (uri);
-
-	return result;
-}
-
-
-gboolean
-_g_path_make_directory_tree (const char  *path,
-		   	     mode_t       mode,
-		   	     GError     **error)
-{
-	char     *uri;
-	gboolean  result;
-
-	uri = g_filename_to_uri (path, NULL, NULL);
-	result = _g_uri_ensure_dir_exists (uri, mode, error);
-	g_free (uri);
-
-	return result;
+	return size;
 }
 
 
-const char*
-_g_path_get_mime_type (const char *filename,
-                       gboolean    fast_file_type)
+time_t
+_g_file_get_file_mtime (GFile *file)
 {
-	char       *uri;
-	const char *mime_type;
+	return _g_file_get_file_time_type (file, G_FILE_ATTRIBUTE_TIME_MODIFIED);
+}
 
-	uri = g_filename_to_uri (filename, NULL, NULL);
-	mime_type = _g_uri_get_mime_type (uri, fast_file_type);
-	g_free (uri);
 
-	return mime_type;
+time_t
+_g_file_get_file_ctime (GFile *file)
+{
+	return _g_file_get_file_time_type (file, G_FILE_ATTRIBUTE_TIME_CREATED);
 }
 
 
-guint64
-_g_path_get_free_space (const char *path)
+const char *
+_g_file_get_mime_type (GFile    *file,
+                       gboolean  fast_file_type)
 {
-	guint64    freespace = 0;
-	GFile     *file;
-	GFileInfo *info;
-	GError    *err = NULL;
+	GFileInfo  *info;
+	GError     *error = NULL;
+ 	const char *result = NULL;
 
-	file = g_file_new_for_path (path);
-	info = g_file_query_filesystem_info (file, G_FILE_ATTRIBUTE_FILESYSTEM_FREE, NULL, &err);
-	if (info != NULL) {
-		freespace = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE);
-		g_object_unref (info);
+ 	info = g_file_query_info (file,
+				  (fast_file_type ?
+				   G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE :
+				   G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE),
+				  0,
+				  NULL,
+				  &error);
+	if (info == NULL) {
+		g_warning ("%s", error->message);
+		g_clear_error (&error);
 	}
 	else {
-		g_warning ("Could not get filesystem free space on volume that contains %s: %s", path, err->message);
-		g_error_free (err);
+		result = _g_str_get_static (g_file_info_get_content_type (info));
+		g_object_unref (info);
 	}
-	g_object_unref (file);
 
-	return freespace;
+	return result;
 }
 
 
 gboolean
-_g_path_remove_directory (const char *path)
+_g_file_is_temp_dir (GFile *file)
 {
-	char     *uri;
-	gboolean  result;
+	gboolean  result = FALSE;
+	char     *path;
 
+	path = g_file_get_path (file);
 	if (path == NULL)
-		return TRUE;
+		result = TRUE;
+	else if (strcmp (g_get_tmp_dir (), path) == 0)
+		result = TRUE;
+	else if (_g_path_is_parent_of (g_get_tmp_dir (), path))
+		result = TRUE;
+	else
+		result = _g_file_is_temp_work_dir (file);
 
-	uri = g_filename_to_uri (path, NULL, NULL);
-	result = _g_uri_remove_directory (uri);
-	g_free (uri);
+	g_free (path);
 
 	return result;
 }
 
 
-static const char *try_folder[] = { "cache", "~", "tmp", NULL };
-
-
-static char *
-ith_temp_folder_to_try (int n)
+GFile *
+_g_file_create_alternative (GFile      *folder,
+			    const char *name)
 {
-	const char *folder;
-
-	folder = try_folder[n];
-	if (strcmp (folder, "cache") == 0)
-		folder = g_get_user_cache_dir ();
-	else if (strcmp (folder, "~") == 0)
-		folder = g_get_home_dir ();
-	else if (strcmp (folder, "tmp") == 0)
-		folder = g_get_tmp_dir ();
-
-	return g_strdup (folder);
-}
+	GFile *file = NULL;
+	int    n = 1;
 
+	do {
+		char *new_name;
 
-char *
-_g_path_get_temp_work_dir (const char *parent_folder)
-{
-	guint64  max_size = 0;
-	char    *best_folder = NULL;
-	int      i;
-	char    *template;
-	char    *result = NULL;
-
-	if (parent_folder == NULL) {
-		/* find the folder with more free space. */
-
-		for (i = 0; try_folder[i] != NULL; i++) {
-			char    *folder;
-			guint64  size;
-
-			folder = ith_temp_folder_to_try (i);
-			size = _g_path_get_free_space (folder);
-			if (max_size < size) {
-				max_size = size;
-				g_free (best_folder);
-				best_folder = folder;
-			}
-			else
-				g_free (folder);
-		}
-	}
-	else
-		best_folder = g_strdup (parent_folder);
+		_g_object_unref (file);
 
-	if (best_folder == NULL)
-		return NULL;
+		if (n == 1)
+			new_name = g_strdup (name);
+		else
+			new_name = g_strdup_printf ("%s (%d)", name, n);
+		n++;
 
-	template = g_strconcat (best_folder, "/.fr-XXXXXX", NULL);
-	result = mkdtemp (template);
+		file = g_file_get_child (folder, new_name);
 
-	if ((result == NULL) || (*result == '\0')) {
-		g_free (template);
-		result = NULL;
+		g_free (new_name);
 	}
+	while (g_file_query_exists (file, NULL));
 
-	return result;
+	return file;
 }
 
 
-gboolean
-_g_path_is_temp_work_dir (const char *path)
+GFile *
+_g_file_create_alternative_for_file (GFile *file)
 {
-	int i;
-
-	if (strncmp (path, "file://", 7) == 0)
-		path = path + 7;
-	else if (path[0] != '/')
-		return FALSE;
-
-	for (i = 0; try_folder[i] != NULL; i++) {
-		char *folder;
+	GFile *parent;
+	char  *name;
+	GFile *new_file;
 
-		folder = ith_temp_folder_to_try (i);
-		if (strncmp (path, folder, strlen (folder)) == 0) {
-			if (strncmp (path + strlen (folder), "/.fr-", 5) == 0) {
-				g_free (folder);
-				return TRUE;
-			}
-		}
-
-		g_free (folder);
-	}
-
-	return FALSE;
-}
+	parent = g_file_get_parent (file);
+	name = g_file_get_basename (file);
+	new_file = _g_file_create_alternative (parent, name);
 
+	g_free (name);
+	g_object_unref (parent);
 
-gboolean
-_g_path_is_temp_dir (const char *path)
-{
-	if (strncmp (path, "file://", 7) == 0)
-		path = path + 7;
-	if (strcmp (g_get_tmp_dir (), path) == 0)
-		return TRUE;
-	if (_g_path_is_parent_of (g_get_tmp_dir (), path))
-		return TRUE;
-	else
-		return _g_path_is_temp_work_dir (path);
+	return new_file;
 }
 
 
-/* GFile */
-
-
 gboolean
 _g_file_check_permissions (GFile *file,
 			   int    mode)
@@ -829,6 +397,50 @@ _g_file_make_directory_tree (GFile    *dir,
 }
 
 
+gboolean
+_g_file_remove_directory (GFile         *directory,
+			  GCancellable  *cancellable,
+			  GError       **error)
+{
+	GFileEnumerator *enumerator;
+	GFileInfo       *info;
+	gboolean         error_occurred = FALSE;
+
+	enumerator = g_file_enumerate_children (directory,
+					        G_FILE_ATTRIBUTE_STANDARD_NAME ","
+					        G_FILE_ATTRIBUTE_STANDARD_TYPE,
+					        0,
+					        cancellable,
+					        error);
+
+	while (! error_occurred && (info = g_file_enumerator_next_file (enumerator, cancellable, error)) != NULL) {
+		GFile *child;
+
+		child = g_file_get_child (directory, g_file_info_get_name (info));
+		switch (g_file_info_get_file_type (info)) {
+		case G_FILE_TYPE_DIRECTORY:
+			if (! _g_file_remove_directory (child, cancellable, error))
+				error_occurred = TRUE;
+			break;
+		default:
+			if (! g_file_delete (child, cancellable, error))
+				error_occurred = TRUE;
+			break;
+		}
+
+		g_object_unref (child);
+		g_object_unref (info);
+	}
+
+	if (! error_occurred && ! g_file_delete (directory, cancellable, error))
+ 		error_occurred = TRUE;
+
+	g_object_unref (enumerator);
+
+	return ! error_occurred;
+}
+
+
 GFile *
 _g_file_new_user_config_subdir (const char *child_name,
 			        gboolean    create_child)
@@ -852,6 +464,213 @@ _g_file_new_user_config_subdir (const char *child_name,
 }
 
 
+GFile *
+_g_file_get_dir_content_if_unique (GFile *file)
+{
+	GFileEnumerator *enumarator;
+	GFileInfo       *info;
+	GError          *error = NULL;
+	GFile           *content = NULL;
+
+	if (! g_file_query_exists (file, NULL)) {
+		g_object_unref (file);
+		return NULL;
+	}
+
+	enumarator = g_file_enumerate_children (file, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, &error);
+	if (error != NULL) {
+		g_warning ("%s", error->message);
+		g_error_free (error);
+		return NULL;
+	}
+
+	while ((info = g_file_enumerator_next_file (enumarator, NULL, &error)) != NULL) {
+		const char *name;
+
+		if (error != NULL) {
+			g_warning ("Failed to get info while enumerating children: %s", error->message);
+			g_clear_error (&error);
+			g_object_unref (info);
+			continue;
+		}
+
+		name = g_file_info_get_name (info);
+		if ((strcmp (name, ".") == 0) || (strcmp (name, "..") == 0)) {
+			g_object_unref (info);
+			continue;
+		}
+
+		if (content != NULL) {
+			g_object_unref (content);
+			g_object_unref (info);
+			content = NULL;
+			break;
+		}
+
+		content = g_file_get_child (file, name);
+
+		g_object_unref (info);
+	}
+
+	if (error != NULL) {
+		g_warning ("Failed to get info after enumerating children: %s", error->message);
+		g_clear_error (&error);
+	}
+
+	g_object_unref (enumarator);
+
+	return content;
+}
+
+
+guint64
+_g_file_get_free_space (GFile *file)
+{
+	GFileInfo *info;
+	guint64    freespace = 0;
+	GError    *error = NULL;
+
+	info = g_file_query_filesystem_info (file, G_FILE_ATTRIBUTE_FILESYSTEM_FREE, NULL, &error);
+	if (info != NULL) {
+		freespace = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE);
+		g_object_unref (info);
+	}
+	else {
+		g_warning ("%s", error->message);
+		g_error_free (error);
+	}
+
+	return freespace;
+}
+
+
+GFile *
+_g_file_get_temp_work_dir (GFile *parent_folder)
+{
+	char  *parent_path;
+	char  *tmp;
+	GFile *file;
+
+	parent_path = (parent_folder != NULL) ? g_file_get_path (parent_folder) : NULL;
+	tmp = _g_path_get_temp_work_dir (parent_path);
+	file = g_file_new_for_path (tmp);
+
+	g_free (tmp);
+	g_free (parent_path);
+
+	return file;
+}
+
+
+gboolean
+_g_file_is_temp_work_dir (GFile *file)
+{
+	gboolean  result = FALSE;
+	char     *path;
+	int       i;
+
+	path = g_file_get_path (file);
+	if (path[0] != '/')
+		return FALSE;
+
+	for (i = 0; try_folder[i] != NULL; i++) {
+		const char *folder;
+
+		folder = get_nth_temp_folder_to_try (i);
+		if (strncmp (path, folder, strlen (folder)) == 0) {
+			if (strncmp (path + strlen (folder), "/.fr-", 5) == 0) {
+				result = TRUE;
+				break;
+			}
+		}
+	}
+
+	return result;
+}
+
+
+gboolean
+_g_file_query_dir_is_empty (GFile *file)
+{
+	GFileEnumerator *enumerator;
+	GFileInfo       *info;
+	GError          *error = NULL;
+	int              n = 0;
+
+	if (! g_file_query_exists (file, NULL))
+		return TRUE;
+
+	enumerator = g_file_enumerate_children (file, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, &error);
+	if (error != NULL) {
+		g_warning ("%s", error->message);
+		g_error_free (error);
+		g_object_unref (enumerator);
+		return TRUE;
+	}
+
+	while ((n == 0) && ((info = g_file_enumerator_next_file (enumerator, NULL, &error)) != NULL)) {
+		if (error != NULL) {
+			g_warning ("%s", error->message);
+			g_error_free (error);
+		}
+		else if (! IS_SPECIAL_DIR (g_file_info_get_name (info)))
+			n++;
+		g_object_unref (info);
+	}
+
+	g_object_unref (enumerator);
+
+	return (n == 0);
+}
+
+
+gboolean
+_g_file_dir_contains_one_object (GFile *file)
+{
+	GFileEnumerator *enumerator;
+	GFileInfo       *info;
+	GError          *error = NULL;
+	int              n = 0;
+
+	if (! g_file_query_exists (file, NULL))
+		return FALSE;
+
+	enumerator = g_file_enumerate_children (file, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, &error);
+	if (error != NULL) {
+		g_warning ("%s", error->message);
+		g_error_free (error);
+		g_object_unref (enumerator);
+		return FALSE;
+	}
+
+	while ((info = g_file_enumerator_next_file (enumerator, NULL, &error)) != NULL) {
+		const char *name;
+
+		if (error != NULL) {
+			g_warning ("%s", error->message);
+			g_error_free (error);
+			g_object_unref (info);
+			continue;
+		}
+
+		name = g_file_info_get_name (info);
+		if (strcmp (name, ".") == 0 || strcmp (name, "..") == 0) {
+			g_object_unref (info);
+ 			continue;
+		}
+
+		g_object_unref (info);
+
+		if (++n > 1)
+			break;
+	}
+
+	g_object_unref (enumerator);
+
+	return (n == 1);
+}
+
+
 /* program */
 
 
diff --git a/src/file-utils.h b/src/file-utils.h
index 54b6882..056f5c9 100644
--- a/src/file-utils.h
+++ b/src/file-utils.h
@@ -27,56 +27,39 @@
 #include <unistd.h>
 #include <gio/gio.h>
 
-/* uri */
-
-gboolean            _g_uri_query_exists                   (const char  *uri);
-gboolean            _g_uri_query_is_file                  (const char  *uri);
-gboolean            _g_uri_query_is_dir                   (const char  *uri);
-char *              _g_uri_create_alternative             (const char  *folder,
-							   const char  *name);
-char *              _g_uri_create_alternative_for_uri     (const char  *uri);
-gboolean            _g_uri_query_dir_is_empty             (const char  *uri);
-gboolean            _g_uri_dir_contains_one_object        (const char  *uri);
-char *              _g_uri_get_dir_content_if_unique      (const char  *uri);
-goffset             _g_uri_get_file_size                  (const char  *uri);
-
-time_t              _g_uri_get_file_mtime                 (const char  *uri);
-
-time_t              _g_uri_get_file_ctime                 (const char  *uri);
-gboolean            _g_uri_ensure_dir_exists              (const char  *uri,
-							   mode_t       mode,
-							   GError     **error);
-const char*         _g_uri_get_mime_type                  (const char  *uri,
-							   gboolean     fast_file_type);
-gboolean            _g_uri_remove_directory               (const char  *uri);
-gboolean            _g_uri_check_permissions              (const char  *uri,
-							   int          mode);
-
 /* path */
 
-gboolean            _g_path_query_is_dir                  (const char  *path);
-goffset             _g_path_get_file_size                 (const char  *path);
-time_t              _g_path_get_file_mtime                (const char  *path);
-gboolean            _g_path_make_directory_tree           (const char  *path,
-							   mode_t       mode,
-							   GError     **error);
-const char*         _g_path_get_mime_type                 (const char  *filename,
-							   gboolean     fast_file_type);
-guint64             _g_path_get_free_space                (const char  *path);
-gboolean            _g_path_remove_directory              (const char  *path);
-char *              _g_path_get_temp_work_dir             (const char  *parent_folder);
-gboolean            _g_path_is_temp_work_dir              (const char  *path);
-gboolean            _g_path_is_temp_dir                   (const char  *path);
+char *              _g_path_get_temp_work_dir             (const char *parent_folder);
 
 /* GFile */
 
+gboolean            _g_file_query_is_file                 (GFile       *file);
+gboolean            _g_file_query_is_dir                  (GFile       *file);
+goffset             _g_file_get_file_size                 (GFile       *file);
+time_t              _g_file_get_file_mtime                (GFile       *file);
+time_t              _g_file_get_file_ctime                (GFile       *file);
+const char*         _g_file_get_mime_type                 (GFile       *file,
+							   gboolean     fast_file_type);
+gboolean            _g_file_is_temp_dir                   (GFile       *file);
+GFile *             _g_file_create_alternative            (GFile       *folder,
+							   const char  *name);
+GFile *             _g_file_create_alternative_for_file   (GFile       *file);
 gboolean            _g_file_check_permissions             (GFile       *file,
 							   int          mode);
 gboolean            _g_file_make_directory_tree           (GFile       *dir,
 							   mode_t       mode,
 							   GError     **error);
+gboolean            _g_file_remove_directory              (GFile         *directory,
+							   GCancellable  *cancellable,
+							   GError       **error);
 GFile *             _g_file_new_user_config_subdir        (const char  *child_name,
 						    	   gboolean     create_);
+GFile *             _g_file_get_dir_content_if_unique     (GFile       *file);
+guint64             _g_file_get_free_space                (GFile       *file);
+GFile *             _g_file_get_temp_work_dir             (GFile       *parent_folder);
+gboolean            _g_file_is_temp_work_dir              (GFile       *file);
+gboolean            _g_file_query_dir_is_empty            (GFile       *file);
+gboolean            _g_file_dir_contains_one_object       (GFile       *file);
 
 /* program */
 
diff --git a/src/fr-archive-libarchive.c b/src/fr-archive-libarchive.c
index 4ecd270..c8066f1 100644
--- a/src/fr-archive-libarchive.c
+++ b/src/fr-archive-libarchive.c
@@ -35,7 +35,7 @@
 #include "typedefs.h"
 
 
-#define BUFFER_SIZE (10 * 1024)
+#define BUFFER_SIZE (64 * 1024)
 #define FILE_ATTRIBUTES_NEEDED_BY_ARCHIVE_ENTRY ("standard::*,time::*,access::*,unix::*")
 
 
@@ -43,7 +43,8 @@ G_DEFINE_TYPE (FrArchiveLibarchive, fr_archive_libarchive, FR_TYPE_ARCHIVE)
 
 
 struct _FrArchiveLibarchivePrivate {
-	int dummy;
+	gssize compressed_size;
+	gssize uncompressed_size;
 };
 
 
@@ -173,6 +174,11 @@ load_data_open (struct archive *a,
 	if (load_data->error != NULL)
 		return ARCHIVE_FATAL;
 
+	if (g_simple_async_result_get_source_tag (load_data->result) == fr_archive_list) {
+		FR_ARCHIVE_LIBARCHIVE (load_data->archive)->priv->compressed_size = 0;
+		FR_ARCHIVE_LIBARCHIVE (load_data->archive)->priv->uncompressed_size = 0;
+	}
+
 	load_data->istream = (GInputStream *) g_file_read (fr_archive_get_file (load_data->archive),
 							   load_data->cancellable,
 							   &load_data->error);
@@ -186,16 +192,26 @@ load_data_read (struct archive  *a,
 		const void     **buff)
 {
 	LoadData *load_data = client_data;
+	gssize    bytes;
 
 	if (load_data->error != NULL)
 		return -1;
 
 	*buff = load_data->buffer;
-	return g_input_stream_read (load_data->istream,
+	bytes =g_input_stream_read (load_data->istream,
 				    load_data->buffer,
 				    load_data->buffer_size,
 				    load_data->cancellable,
 				    &load_data->error);
+
+	/* update the progress only if listing the content */
+	if (g_simple_async_result_get_source_tag (load_data->result) == fr_archive_list) {
+		fr_archive_progress_set_completed_bytes (load_data->archive,
+							 g_seekable_tell (G_SEEKABLE (load_data->istream)));
+		FR_ARCHIVE_LIBARCHIVE (load_data->archive)->priv->compressed_size += bytes;
+	}
+
+	return bytes;
 }
 
 
@@ -220,6 +236,43 @@ load_data_close (struct archive *a,
 /* -- list -- */
 
 
+static goffset
+_g_file_get_size (GFile        *file,
+		  GCancellable *cancellable)
+{
+	GFileInfo *info;
+	goffset    size;
+
+	info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE, 0, cancellable, NULL);
+	if (info == NULL)
+		return 0;
+
+	size = g_file_info_get_size (info);
+	g_object_unref (info);
+
+	return size;
+}
+
+
+#if 1 /* FIXME: delete if not needed */
+
+static gssize
+_archive_read_data_skip (struct archive *a)
+{
+	int         r;
+	const void *buff;
+	size_t      size;
+	int64_t     offset;
+
+	while ((r = archive_read_data_block (a, &buff, &size, &offset)) == ARCHIVE_OK)
+		/* void */;
+
+	return (r == ARCHIVE_EOF) ? (gssize) offset + size : 0;
+}
+
+#endif
+
+
 static void
 list_archive_thread (GSimpleAsyncResult *result,
 		     GObject            *object,
@@ -229,9 +282,13 @@ list_archive_thread (GSimpleAsyncResult *result,
 	struct archive       *a;
 	struct archive_entry *entry;
 	int                   r;
+	gssize                skipped_size = 0;
 
 	load_data = g_simple_async_result_get_op_res_gpointer (result);
 
+	fr_archive_progress_set_total_bytes (load_data->archive,
+					     _g_file_get_size (fr_archive_get_file (load_data->archive), cancellable));
+
 	a = archive_read_new ();
 	archive_read_support_filter_all (a);
 	archive_read_support_format_all (a);
@@ -245,8 +302,10 @@ list_archive_thread (GSimpleAsyncResult *result,
 
 		file_data = file_data_new ();
 
-		if (archive_entry_size_is_set (entry))
+		if (archive_entry_size_is_set (entry)) {
 			file_data->size =  archive_entry_size (entry);
+			FR_ARCHIVE_LIBARCHIVE (load_data->archive)->priv->uncompressed_size += file_data->size;
+		}
 
 		if (archive_entry_mtime_is_set (entry))
 			file_data->modified =  archive_entry_mtime (entry);
@@ -268,7 +327,7 @@ list_archive_thread (GSimpleAsyncResult *result,
 		if (file_data->dir)
 			file_data->name = _g_path_get_dir_name (file_data->full_path);
 		else
-			file_data->name = g_strdup (_g_path_get_file_name (file_data->full_path));
+			file_data->name = g_strdup (_g_path_get_basename (file_data->full_path));
 		file_data->path = _g_path_remove_level (file_data->full_path);
 
 		/*
@@ -281,10 +340,15 @@ list_archive_thread (GSimpleAsyncResult *result,
 
 		fr_archive_add_file (load_data->archive, file_data);
 
-		archive_read_data_skip (a);
+		skipped_size += _archive_read_data_skip (a);
 	}
 	archive_read_free (a);
 
+	g_print ("compressed size: %" G_GSSIZE_FORMAT ", uncompressed size: %" G_GSSIZE_FORMAT ", skipped: %" G_GSSIZE_FORMAT "\n",
+			FR_ARCHIVE_LIBARCHIVE (load_data->archive)->priv->compressed_size,
+			FR_ARCHIVE_LIBARCHIVE (load_data->archive)->priv->uncompressed_size,
+			skipped_size);
+
 	if ((load_data->error == NULL) && (r != ARCHIVE_EOF) && (archive_error_string (a) != NULL))
 		load_data->error = g_error_new_literal (FR_ERROR, FR_ERROR_COMMAND_ERROR, archive_error_string (a));
 	if (load_data->error == NULL)
@@ -404,7 +468,7 @@ extract_archive_thread (GSimpleAsyncResult *result,
 		}
 
 		fullpath = (*pathname == '/') ? g_strdup (pathname) : g_strconcat ("/", pathname, NULL);
-		file = g_file_get_child (extract_data->destination, _g_path_get_basename (fullpath, extract_data->base_dir, extract_data->junk_paths));
+		file = g_file_get_child (extract_data->destination, _g_path_get_relative_basename (fullpath, extract_data->base_dir, extract_data->junk_paths));
 
 		/* honor the skip_older and overwrite options */
 
@@ -544,7 +608,7 @@ extract_archive_thread (GSimpleAsyncResult *result,
 static void
 fr_archive_libarchive_extract_files (FrArchive           *archive,
 				     GList               *file_list,
-				     const char          *destination,
+				     GFile               *destination,
 				     const char          *base_dir,
 				     gboolean             skip_older,
 				     gboolean             overwrite,
@@ -571,7 +635,7 @@ fr_archive_libarchive_extract_files (FrArchive           *archive,
 	load_data->buffer = g_new (char, load_data->buffer_size);
 
 	extract_data->file_list = _g_string_list_dup (file_list);
-	extract_data->destination = g_file_new_for_uri (destination);
+	extract_data->destination = g_object_ref (destination);
 	extract_data->base_dir = g_strdup (base_dir);
 	extract_data->skip_older = skip_older;
 	extract_data->overwrite = overwrite;
@@ -1096,6 +1160,8 @@ save_archive_thread (GSimpleAsyncResult *result,
 
 			rb = archive_write_finish_entry (b);
 		}
+		else if (action == WRITE_ACTION_SKIP_ENTRY)
+			fr_archive_progress_inc_completed_bytes (load_data->archive, archive_entry_size (r_entry));
 
 		archive_entry_free (w_entry);
 	}
@@ -1202,9 +1268,30 @@ static void
 _add_files_begin (SaveData *save_data,
 		  gpointer  user_data)
 {
-	AddData *add_data = user_data;
+	AddData  *add_data = user_data;
+	LoadData *load_data = LOAD_DATA (save_data);
+
+	fr_archive_progress_set_total_files (load_data->archive, add_data->n_files_to_add);
+
+	if (load_data->archive->files_to_add_size == 0) {
+		GList *files_to_add;
+		GList *scan;
 
-	fr_archive_progress_set_total_files (LOAD_DATA (save_data)->archive, add_data->n_files_to_add);
+		files_to_add = g_hash_table_get_values (add_data->files_to_add);
+		for (scan = files_to_add; scan; scan = scan->next) {
+			AddFile *add_file = scan->data;
+
+			if (g_cancellable_is_cancelled (load_data->cancellable))
+				break;
+
+			load_data->archive->files_to_add_size += _g_file_get_size (add_file->file, load_data->cancellable);
+		}
+
+		g_list_free (files_to_add);
+	}
+
+	fr_archive_progress_set_total_bytes (load_data->archive,
+			FR_ARCHIVE_LIBARCHIVE (load_data->archive)->priv->uncompressed_size + load_data->archive->files_to_add_size);
 }
 
 
@@ -1253,6 +1340,9 @@ _add_files_end (SaveData *save_data,
 	for (scan = remaining_files; (load_data->error == NULL) && scan; scan = scan->next) {
 		AddFile *add_file = scan->data;
 
+		if (g_cancellable_is_cancelled (load_data->cancellable))
+			break;
+
 		if (_archive_write_file (save_data->b,
 					 save_data,
 					 add_file,
@@ -1261,6 +1351,8 @@ _add_files_end (SaveData *save_data,
 		{
 			break;
 		}
+
+		fr_archive_progress_inc_completed_files (load_data->archive, 1);
 	}
 
 	g_list_free (remaining_files);
@@ -1270,7 +1362,7 @@ _add_files_end (SaveData *save_data,
 static void
 fr_archive_libarchive_add_files (FrArchive           *archive,
 				 GList               *file_list,
-				 const char          *base_dir_uri,
+				 GFile               *base_dir,
 				 const char          *dest_dir,
 				 gboolean             update,
 				 gboolean             recursive,
@@ -1283,29 +1375,31 @@ fr_archive_libarchive_add_files (FrArchive           *archive,
 				 gpointer             user_data)
 {
 	AddData *add_data;
-	GFile   *base_dir;
 	GList   *scan;
 
-	g_return_if_fail (base_dir_uri != NULL);
+	g_return_if_fail (base_dir != NULL);
 
 	add_data = add_data_new ();
 
-	base_dir = g_file_new_for_uri (base_dir_uri);
 	if (dest_dir != NULL)
-		dest_dir = dest_dir[0] == '/' ? dest_dir + 1 : dest_dir;
+		dest_dir = (dest_dir[0] == '/' ? dest_dir + 1 : dest_dir);
 	else
 		dest_dir = "";
-	for (scan = file_list; scan; scan = scan->next) {
-		char  *relative_pathname = scan->data;
-		char  *full_pathname;
-		GFile *file;
 
-		full_pathname = g_build_filename (dest_dir, relative_pathname, NULL);
-		file = g_file_get_child (base_dir, relative_pathname);
-		g_hash_table_insert (add_data->files_to_add, full_pathname, add_file_new (file, full_pathname));
+	for (scan = file_list; scan; scan = scan->next) {
+		GFile *file = G_FILE (scan->data);
+		char  *relative_pathname;
+		char  *archive_pathname;
+
+		relative_pathname = g_file_get_relative_path (base_dir, file);
+		archive_pathname = g_build_filename (dest_dir, relative_pathname, NULL);
+		g_hash_table_insert (add_data->files_to_add,
+				     g_strdup (archive_pathname),
+				     add_file_new (file, archive_pathname));
 		add_data->n_files_to_add++;
 
-		g_object_unref (file);
+		g_free (archive_pathname);
+		g_free (relative_pathname);
 	}
 
 	_fr_archive_libarchive_save (archive,
@@ -1324,8 +1418,6 @@ fr_archive_libarchive_add_files (FrArchive           *archive,
 				     _add_files_entry_action,
 				     add_data,
 				     (GDestroyNotify) add_data_free);
-
-	g_object_unref (base_dir);
 }
 
 
@@ -1531,7 +1623,7 @@ fr_archive_libarchive_rename (FrArchive           *archive,
 
 static void
 fr_archive_libarchive_paste_clipboard (FrArchive           *archive,
-				       char                *archive_uri,
+				       GFile               *archive_file,
 				       char                *password,
 				       gboolean             encrypt_header,
 				       FrCompression        compression,
@@ -1539,7 +1631,7 @@ fr_archive_libarchive_paste_clipboard (FrArchive           *archive,
 				       FrClipboardOp        op,
 				       char                *base_dir,
 				       GList               *files,
-				       char                *tmp_dir,
+				       GFile               *tmp_dir,
 				       char                *current_dir,
 				       GCancellable        *cancellable,
 				       GAsyncReadyCallback  callback,
@@ -1556,17 +1648,14 @@ fr_archive_libarchive_paste_clipboard (FrArchive           *archive,
 	for (scan = files; scan; scan = scan->next) {
 		const char *old_name = (char *) scan->data;
 		char       *new_name;
-		char       *filename;
 		GFile      *file;
 
 		new_name = g_build_filename (current_dir, old_name + strlen (base_dir) - 1, NULL);
-		filename = g_build_filename (tmp_dir, old_name, NULL);
-		file = g_file_new_for_path (filename);
+		file = _g_file_append_path (tmp_dir, old_name, NULL);
 		g_hash_table_insert (add_data->files_to_add, new_name, add_file_new (file, new_name));
 		add_data->n_files_to_add++;
 
 		g_object_unref (file);
-		g_free (filename);
 	}
 
 	_fr_archive_libarchive_save (archive,
@@ -1593,8 +1682,7 @@ fr_archive_libarchive_paste_clipboard (FrArchive           *archive,
 
 static void
 fr_archive_libarchive_add_dropped_files (FrArchive           *archive,
-					 GList               *files,
-					 const char          *base_dir,
+					 GList               *file_list,
 					 const char          *dest_dir,
 					 const char          *password,
 					 gboolean             encrypt_header,
@@ -1607,29 +1695,24 @@ fr_archive_libarchive_add_dropped_files (FrArchive           *archive,
 	AddData *add_data;
 	GList   *scan;
 
-	g_return_if_fail (base_dir != NULL);
-
 	add_data = add_data_new ();
 
 	if (dest_dir[0] == '/')
 		dest_dir += 1;
 
-	for (scan = files; scan; scan = scan->next) {
-		const char *uri = (char *) scan->data;
-		char       *filepath;
-		char       *archive_pathname;
-		GFile      *file;
-
-		filepath = g_filename_from_uri (uri, NULL, NULL);
-		if (filepath == NULL)
-			continue;
-
-		archive_pathname = g_build_filename (dest_dir, _g_path_get_file_name (filepath), NULL);
-		file = g_file_new_for_uri (uri);
-		g_hash_table_insert (add_data->files_to_add, archive_pathname, add_file_new (file, archive_pathname));
-
-		g_object_unref (file);
-		g_free (filepath);
+	for (scan = file_list; scan; scan = scan->next) {
+		GFile *file = G_FILE (scan->data);
+		char  *basename;
+		char  *archive_pathname;
+
+		basename = g_file_get_basename (file);
+		archive_pathname = g_build_filename (dest_dir, basename, NULL);
+		g_hash_table_insert (add_data->files_to_add,
+				     g_strdup (archive_pathname),
+				     add_file_new (file, archive_pathname));
+
+		g_free (archive_pathname);
+		g_free (basename);
 	}
 
 	_fr_archive_libarchive_save (archive,
@@ -1676,18 +1759,15 @@ fr_archive_libarchive_update_open_files (FrArchive           *archive,
 	     scan_file && scan_dir;
 	     scan_file = scan_file->next, scan_dir = scan_dir->next)
 	{
-		char  *temp_dir = scan_dir->data;
-		char  *relative_pathname = scan_file->data;
-		char  *full_pathname;
-		GFile *file;
-
-		full_pathname = g_build_filename (temp_dir, relative_pathname, NULL);
-		file = g_file_new_for_path (full_pathname);
-		g_hash_table_insert (add_data->files_to_add, g_strdup (relative_pathname), add_file_new (file, relative_pathname));
+		GFile *temp_dir = G_FILE (scan_dir->data);
+		GFile *extracted_file = G_FILE (scan_file->data);
+		char  *archive_pathname;
+
+		archive_pathname = g_file_get_relative_path (temp_dir, extracted_file);
+		g_hash_table_insert (add_data->files_to_add, g_strdup (archive_pathname), add_file_new (extracted_file, archive_pathname));
 		add_data->n_files_to_add++;
 
-		g_object_unref (file);
-		g_free (full_pathname);
+		g_free (archive_pathname);
 	}
 
 	_fr_archive_libarchive_save (archive,
diff --git a/src/fr-archive.c b/src/fr-archive.c
index bf49693..b8273b3 100644
--- a/src/fr-archive.c
+++ b/src/fr-archive.c
@@ -45,7 +45,7 @@
 
 
 #define FILE_ARRAY_INITIAL_SIZE	256
-#define PROGRESS_DELAY          100
+#define PROGRESS_DELAY          50
 
 
 char *action_names[] = { "NONE",
@@ -90,7 +90,7 @@ struct _FrArchivePrivate {
 	/* others */
 
 	gboolean       creating_archive;
-	char          *extraction_destination;
+	GFile         *extraction_destination;
 	gboolean       have_write_permissions;     /* true if we have the
 						    * permissions to write the
 						    * file. */
@@ -916,6 +916,23 @@ fr_archive_open_finish (GFile         *file,
 }
 
 
+static gboolean
+_fr_archive_update_progress_cb (gpointer user_data)
+{
+	FrArchive *archive = user_data;
+	fr_archive_progress (archive, fr_archive_progress_get_fraction (archive));
+	return TRUE;
+}
+
+
+static void
+_fr_archive_activate_progress_update (FrArchive *archive)
+{
+	if (archive->priv->progress_event == 0)
+		archive->priv->progress_event = g_timeout_add (PROGRESS_DELAY, _fr_archive_update_progress_cb, archive);
+}
+
+
 void
 fr_archive_list (FrArchive           *archive,
 		 const char          *password,
@@ -925,6 +942,8 @@ fr_archive_list (FrArchive           *archive,
 {
 	g_return_if_fail (archive != NULL);
 
+	_fr_archive_activate_progress_update (archive);
+
 	if (archive->files != NULL) {
 		g_hash_table_remove_all (archive->files_hash);
 		_g_ptr_array_free_full (archive->files, (GFunc) file_data_free, NULL);
@@ -963,6 +982,8 @@ fr_archive_operation_finish (FrArchive     *archive,
 		}
 	}
 
+	archive->files_to_add_size = 0;
+
 	if (! success && (error != NULL) && g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
 		g_error_free (*error);
 		*error = g_error_new_literal (FR_ERROR, FR_ERROR_STOPPED, "");
@@ -972,57 +993,12 @@ fr_archive_operation_finish (FrArchive     *archive,
 }
 
 
-static gboolean
-_fr_archive_update_progress_cb (gpointer user_data)
-{
-	FrArchive *archive = user_data;
-	fr_archive_progress (archive, fr_archive_progress_get_fraction (archive));
-	return TRUE;
-}
-
-
-void
-fr_archive_add_files (FrArchive           *archive,
-		      GList               *file_list,
-		      const char          *base_dir,
-		      const char          *dest_dir,
-		      gboolean             update,
-		      gboolean             recursive,
-		      const char          *password,
-		      gboolean             encrypt_header,
-		      FrCompression        compression,
-		      guint                volume_size,
-		      GCancellable        *cancellable,
-		      GAsyncReadyCallback  callback,
-		      gpointer             user_data)
-{
-	g_return_if_fail (! archive->read_only);
-
-	fr_archive_action_started (archive, FR_ACTION_ADDING_FILES);
-	archive->priv->progress_event = g_timeout_add (PROGRESS_DELAY, _fr_archive_update_progress_cb, archive);
-
-	FR_ARCHIVE_GET_CLASS (archive)->add_files (archive,
-						   file_list,
-						   base_dir,
-						   dest_dir,
-						   update,
-						   recursive,
-						   password,
-						   encrypt_header,
-						   compression,
-						   volume_size,
-						   cancellable,
-						   callback,
-						   user_data);
-}
-
-
-/* -- add with wildcard -- */
+/* -- fr_archive_add_files -- */
 
 
 typedef struct {
 	FrArchive           *archive;
-	char                *source_dir;
+	GFile               *base_dir;
 	char                *dest_dir;
 	gboolean             update;
 	char                *password;
@@ -1032,285 +1008,230 @@ typedef struct {
 	GCancellable        *cancellable;
 	GAsyncReadyCallback  callback;
 	gpointer             user_data;
-} AddWithWildcardData;
+	FileFilter          *include_files_filter;
+	FileFilter          *exclude_files_filter;
+	FileFilter          *exclude_directories_filter;
+} AddData;
 
 
 static void
-add_with_wildcard_data_free (AddWithWildcardData *aww_data)
+add_data_free (AddData *add_data)
 {
-	g_free (aww_data->source_dir);
-	g_free (aww_data->dest_dir);
-	g_free (aww_data->password);
-	_g_object_unref (aww_data->cancellable);
-	g_free (aww_data);
+	file_filter_unref (add_data->include_files_filter);
+	file_filter_unref (add_data->exclude_files_filter);
+	file_filter_unref (add_data->exclude_directories_filter);
+	_g_object_unref (add_data->base_dir);
+	g_free (add_data->dest_dir);
+	g_free (add_data->password);
+	_g_object_unref (add_data->cancellable);
+	g_free (add_data);
 }
 
 
 static void
-add_with_wildcard__step2 (GList    *file_list,
-			  GList    *dir_list,
-			  GError   *error,
-			  gpointer  data)
+fr_archive_add_files_ready_cb (GList    *file_info_list, /* FileInfo list */
+		      	       GError   *error,
+		      	       gpointer  user_data)
 {
-	AddWithWildcardData *aww_data = data;
-	FrArchive           *archive = aww_data->archive;
-	GSimpleAsyncResult  *result;
+	AddData            *add_data = user_data;
+	FrArchive          *archive = add_data->archive;
+	GSimpleAsyncResult *result;
 
 	result = g_simple_async_result_new (G_OBJECT (archive),
-					    aww_data->callback,
-					    aww_data->user_data,
-					    fr_archive_add_with_wildcard);
+					    add_data->callback,
+					    add_data->user_data,
+					    fr_archive_add_files);
 
 	if (error != NULL) {
 		g_simple_async_result_set_from_error (result, error);
 		g_simple_async_result_complete_in_idle (result);
 	}
 	else {
-		if (archive->propAddCanStoreFolders) {
-			file_list = g_list_concat (file_list, dir_list);
-			dir_list = NULL;
-		}
+		GList *file_list;
+		GList *scan;
+
+		archive->files_to_add_size = 0;
+
+		file_list = NULL;
+		for (scan = file_info_list; scan; scan = scan->next) {
+			FileInfo *data = scan->data;
+
+			switch (g_file_info_get_file_type (data->info)) {
+			case G_FILE_TYPE_REGULAR:
+			case G_FILE_TYPE_DIRECTORY:
+			case G_FILE_TYPE_SYMBOLIC_LINK:
+				break;
+			default: /* ignore any other type */
+				continue;
+			}
 
-		if (file_list == NULL)
-			g_simple_async_result_complete_in_idle (result);
+			if (! archive->propAddCanStoreFolders && (g_file_info_get_file_type (data->info) == G_FILE_TYPE_DIRECTORY))
+				continue;
+
+			file_list = g_list_prepend (file_list, g_object_ref (data->file));
+			archive->files_to_add_size += g_file_info_get_size (data->info);
+		}
+		file_list = g_list_reverse (file_list);
+
+		if (file_list != NULL) {
+			fr_archive_action_started (archive, FR_ACTION_ADDING_FILES);
+			_fr_archive_activate_progress_update (archive);
+
+			FR_ARCHIVE_GET_CLASS (archive)->add_files (add_data->archive,
+								   file_list,
+								   add_data->base_dir,
+								   add_data->dest_dir,
+								   add_data->update,
+								   FALSE,
+								   add_data->password,
+								   add_data->encrypt_header,
+								   add_data->compression,
+								   add_data->volume_size,
+								   add_data->cancellable,
+								   add_data->callback,
+								   add_data->user_data);
+		}
 		else
-			fr_archive_add_files (aww_data->archive,
-					      file_list,
-					      aww_data->source_dir,
-					      aww_data->dest_dir,
-					      aww_data->update,
-					      FALSE,
-					      aww_data->password,
-					      aww_data->encrypt_header,
-					      aww_data->compression,
-					      aww_data->volume_size,
-					      aww_data->cancellable,
-					      aww_data->callback,
-					      aww_data->user_data);
+			g_simple_async_result_complete_in_idle (result);
 	}
 
 	g_object_unref (result);
-	_g_string_list_free (file_list);
-	_g_string_list_free (dir_list);
-	add_with_wildcard_data_free (aww_data);
+	add_data_free (add_data);
 }
 
 
 void
-fr_archive_add_with_wildcard (FrArchive           *archive,
-			      const char          *include_files,
-			      const char          *exclude_files,
-			      const char          *exclude_folders,
-			      const char          *source_dir,
-			      const char          *dest_dir,
-			      gboolean             update,
-			      gboolean             follow_links,
-			      const char          *password,
-			      gboolean             encrypt_header,
-			      FrCompression        compression,
-			      guint                volume_size,
-			      GCancellable        *cancellable,
-			      GAsyncReadyCallback  callback,
-			      gpointer             user_data)
+fr_archive_add_files (FrArchive           *archive,
+		      GList               *file_list,
+		      GFile               *base_dir,
+		      const char          *dest_dir,
+		      gboolean             update,
+		      const char          *password,
+		      gboolean             encrypt_header,
+		      FrCompression        compression,
+		      guint                volume_size,
+		      GCancellable        *cancellable,
+		      GAsyncReadyCallback  callback,
+		      gpointer             user_data)
+
 {
-	AddWithWildcardData *aww_data;
+	AddData *add_data;
 
 	g_return_if_fail (! archive->read_only);
 
-	aww_data = g_new0 (AddWithWildcardData, 1);
-	aww_data->archive = archive;
-	aww_data->source_dir = g_strdup (source_dir);
-	aww_data->dest_dir = g_strdup (dest_dir);
-	aww_data->update = update;
-	aww_data->password = g_strdup (password);
-	aww_data->encrypt_header = encrypt_header;
-	aww_data->compression = compression;
-	aww_data->volume_size = volume_size;
-	aww_data->cancellable = _g_object_ref (cancellable);
-	aww_data->callback = callback;
-	aww_data->user_data = user_data;
+	add_data = g_new0 (AddData, 1);
+	add_data->archive = archive;
+	add_data->base_dir = _g_object_ref (base_dir);
+	add_data->dest_dir = g_strdup (dest_dir);
+	add_data->update = update;
+	add_data->password = g_strdup (password);
+	add_data->encrypt_header = encrypt_header;
+	add_data->compression = compression;
+	add_data->volume_size = volume_size;
+	add_data->cancellable = _g_object_ref (cancellable);
+	add_data->callback = callback;
+	add_data->user_data = user_data;
 
 	fr_archive_action_started (archive, FR_ACTION_GETTING_FILE_LIST);
 
-	g_directory_list_async (source_dir,
-				source_dir,
-				TRUE,
-				follow_links,
-				TRUE,
-				FALSE,
-				include_files,
-				exclude_files,
-				exclude_folders,
-				FALSE,
-				aww_data->cancellable,
-				add_with_wildcard__step2,
-				aww_data);
+	_g_file_list_query_info_async (file_list,
+				       FILE_LIST_RECURSIVE | FILE_LIST_NO_BACKUP_FILES,
+				       (G_FILE_ATTRIBUTE_STANDARD_NAME ","
+					G_FILE_ATTRIBUTE_STANDARD_SIZE ","
+					G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN ","
+					G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP),
+				       cancellable,
+				       NULL,
+				       NULL,
+				       fr_archive_add_files_ready_cb,
+				       add_data);
 }
 
 
-/* -- fr_archive_add_directory -- */
+/* -- fr_archive_add_files_with_filter -- */
 
 
-typedef struct {
-	FrArchive           *archive;
-	char                *base_dir;
-	char                *dest_dir;
-	gboolean             update;
-	char                *password;
-	gboolean             encrypt_header;
-	FrCompression        compression;
-	guint                volume_size;
-	GCancellable        *cancellable;
-	GAsyncReadyCallback  callback;
-	gpointer             user_data;
-} AddDirectoryData;
-
-
-static void
-add_directory_data_free (AddDirectoryData *ad_data)
+static gboolean
+directory_filter_cb (GFile     *file,
+		     GFileInfo *info,
+		     gpointer   user_data)
 {
-	g_free (ad_data->base_dir);
-	g_free (ad_data->dest_dir);
-	g_free (ad_data->password);
-	_g_object_unref (ad_data->cancellable);
-	g_free (ad_data);
+	AddData *add_data = user_data;
+
+	return ! file_filter_empty (add_data->exclude_directories_filter)
+			&& file_filter_matches (add_data->exclude_directories_filter, file);
 }
 
 
-static void
-add_directory__step2 (GList    *file_list,
-		      GList    *dir_list,
-		      GError   *error,
-		      gpointer  user_data)
+static gboolean
+file_filter_cb (GFile     *file,
+		GFileInfo *info,
+		gpointer   user_data)
 {
-	AddDirectoryData   *ad_data = user_data;
-	FrArchive          *archive = ad_data->archive;
-	GSimpleAsyncResult *result;
-
-	result = g_simple_async_result_new (G_OBJECT (archive),
-					    ad_data->callback,
-					    ad_data->user_data,
-					    fr_archive_add_directory);
+	AddData *add_data = user_data;
 
-	if (error != NULL) {
-		_g_string_list_free (dir_list);
-
-		g_simple_async_result_set_from_error (result, error);
-		g_simple_async_result_complete_in_idle (result);
-	}
-	else {
-		if (archive->propAddCanStoreFolders) {
-			file_list = g_list_concat (file_list, dir_list);
-			dir_list = NULL;
-		}
-
-		if (file_list == NULL)
-			g_simple_async_result_complete_in_idle (result);
-		else
-			fr_archive_add_files (ad_data->archive,
-					      file_list,
-					      ad_data->base_dir,
-					      ad_data->dest_dir,
-					      ad_data->update,
-					      FALSE,
-					      ad_data->password,
-					      ad_data->encrypt_header,
-					      ad_data->compression,
-					      ad_data->volume_size,
-					      ad_data->cancellable,
-					      ad_data->callback,
-					      ad_data->user_data);
-	}
+	if (file_filter_matches (add_data->include_files_filter, file))
+		return FALSE;
 
-	_g_string_list_free (file_list);
-	_g_string_list_free (dir_list);
-	g_object_unref (result);
-	add_directory_data_free (ad_data);
+	return ! file_filter_empty (add_data->exclude_files_filter)
+			&& file_filter_matches (add_data->exclude_files_filter, file);
 }
 
 
 void
-fr_archive_add_directory (FrArchive           *archive,
-			  const char          *directory,
-			  const char          *base_dir,
-			  const char          *dest_dir,
-			  gboolean             update,
-			  const char          *password,
-			  gboolean             encrypt_header,
-			  FrCompression        compression,
-			  guint                volume_size,
-			  GCancellable        *cancellable,
-			  GAsyncReadyCallback  callback,
-			  gpointer             user_data)
-
-{
-	AddDirectoryData *ad_data;
+fr_archive_add_files_with_filter (FrArchive           *archive,
+				  GFile               *source_dir,
+				  const char          *include_files,
+				  const char          *exclude_files,
+				  const char          *exclude_directories,
+				  const char          *dest_dir,
+				  gboolean             update,
+				  gboolean             follow_links,
+				  const char          *password,
+				  gboolean             encrypt_header,
+				  FrCompression        compression,
+				  guint                volume_size,
+				  GCancellable        *cancellable,
+				  GAsyncReadyCallback  callback,
+				  gpointer             user_data)
+{
+	AddData *add_data;
+	GList   *file_list;
 
 	g_return_if_fail (! archive->read_only);
 
-	ad_data = g_new0 (AddDirectoryData, 1);
-	ad_data->archive = archive;
-	ad_data->base_dir = g_strdup (base_dir);
-	ad_data->dest_dir = g_strdup (dest_dir);
-	ad_data->update = update;
-	ad_data->password = g_strdup (password);
-	ad_data->encrypt_header = encrypt_header;
-	ad_data->compression = compression;
-	ad_data->volume_size = volume_size;
-	ad_data->cancellable = _g_object_ref (cancellable);
-	ad_data->callback = callback;
-	ad_data->user_data = user_data;
+	add_data = g_new0 (AddData, 1);
+	add_data->archive = archive;
+	add_data->base_dir = _g_object_ref (source_dir);
+	add_data->dest_dir = g_strdup (dest_dir);
+	add_data->update = update;
+	add_data->password = g_strdup (password);
+	add_data->encrypt_header = encrypt_header;
+	add_data->compression = compression;
+	add_data->volume_size = volume_size;
+	add_data->cancellable = _g_object_ref (cancellable);
+	add_data->callback = callback;
+	add_data->user_data = user_data;
+	add_data->include_files_filter = file_filter_new (include_files);
+	add_data->exclude_files_filter = file_filter_new (exclude_files);
+	add_data->exclude_directories_filter = file_filter_new (exclude_directories);
 
 	fr_archive_action_started (archive, FR_ACTION_GETTING_FILE_LIST);
 
-	g_directory_list_all_async (directory,
-				    base_dir,
-				    TRUE,
-				    cancellable,
-				    add_directory__step2,
-				    ad_data);
-}
-
-
-void
-fr_archive_add_items (FrArchive           *archive,
-		      GList               *item_list,
-		      const char          *base_dir,
-		      const char          *dest_dir,
-		      gboolean             update,
-		      const char          *password,
-		      gboolean             encrypt_header,
-		      FrCompression        compression,
-		      guint                volume_size,
-		      GCancellable        *cancellable,
-		      GAsyncReadyCallback  callback,
-		      gpointer             user_data)
-
-{
-	AddDirectoryData *ad_data;
-
-	g_return_if_fail (! archive->read_only);
+	file_list = g_list_prepend (NULL, source_dir);
+	_g_file_list_query_info_async (file_list,
+				       FILE_LIST_RECURSIVE | FILE_LIST_NO_BACKUP_FILES,
+				       (G_FILE_ATTRIBUTE_STANDARD_NAME ","
+					G_FILE_ATTRIBUTE_STANDARD_SIZE ","
+					G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN ","
+					G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP),
+				       cancellable,
+				       directory_filter_cb,
+				       file_filter_cb,
+				       fr_archive_add_files_ready_cb,
+				       add_data);
 
-	ad_data = g_new0 (AddDirectoryData, 1);
-	ad_data->archive = archive;
-	ad_data->base_dir = g_strdup (base_dir);
-	ad_data->dest_dir = g_strdup (dest_dir);
-	ad_data->update = update;
-	ad_data->password = g_strdup (password);
-	ad_data->encrypt_header = encrypt_header;
-	ad_data->compression = compression;
-	ad_data->volume_size = volume_size;
-	ad_data->cancellable = _g_object_ref (cancellable);
-	ad_data->callback = callback;
-	ad_data->user_data = user_data;
-
-	fr_archive_action_started (archive, FR_ACTION_GETTING_FILE_LIST);
-
-	g_list_items_async (item_list,
-			    base_dir,
-			    cancellable,
-			    add_directory__step2,
-			    ad_data);
+	g_list_free (file_list);
 }
 
 
@@ -1335,10 +1256,39 @@ fr_archive_remove (FrArchive           *archive,
 }
 
 
+static gsize
+_fr_archive_get_file_list_size (FrArchive *archive,
+				GList     *file_list)
+{
+	gsize     total_size = 0;
+	gboolean  local_file_list = FALSE;
+	GList    *scan;
+
+	if (file_list == NULL) {
+		file_list = g_hash_table_get_keys (archive->files_hash);
+		local_file_list = TRUE;
+	}
+
+	for (scan = file_list; scan; scan = scan->next) {
+		const char *original_path = scan->data;
+		FileData   *file_data;
+
+		file_data = g_hash_table_lookup (archive->files_hash, original_path);
+		if (file_data != NULL)
+			total_size += file_data->size;
+	}
+
+	if (local_file_list)
+		g_list_free (file_list);
+
+	return total_size;
+}
+
+
 void
-fr_archive_extract (FrArchive           *self,
+fr_archive_extract (FrArchive           *archive,
 		    GList               *file_list,
-		    const char          *destination,
+		    GFile               *destination,
 		    const char          *base_dir,
 		    gboolean             skip_older,
 		    gboolean             overwrite,
@@ -1348,57 +1298,23 @@ fr_archive_extract (FrArchive           *self,
 		    GAsyncReadyCallback  callback,
 		    gpointer             user_data)
 {
-	g_free (self->priv->extraction_destination);
-	self->priv->extraction_destination = g_strdup (destination);
-
-	self->priv->progress_event = g_timeout_add (PROGRESS_DELAY, _fr_archive_update_progress_cb, self);
-
-	FR_ARCHIVE_GET_CLASS (self)->extract_files (self,
-						    file_list,
-						    destination,
-						    base_dir,
-						    skip_older,
-						    overwrite,
-						    junk_paths,
-						    password,
-						    cancellable,
-						    callback,
-						    user_data);
-}
-
-
-void
-fr_archive_extract_to_local (FrArchive           *self,
-			     GList               *file_list,
-			     const char          *destination_path,
-			     const char          *base_dir,
-			     gboolean             skip_older,
-			     gboolean             overwrite,
-			     gboolean             junk_paths,
-			     const char          *password,
-			     GCancellable        *cancellable,
-			     GAsyncReadyCallback  callback,
-			     gpointer             user_data)
-{
-	char *destination_uri;
-
-	destination_uri = g_filename_to_uri (destination_path, NULL, NULL);
-	if (destination_uri == NULL)
-		return;
-
-	fr_archive_extract (self,
-			    file_list,
-			    destination_uri,
-			    base_dir,
-			    skip_older,
-			    overwrite,
-			    junk_paths,
-			    password,
-			    cancellable,
-			    callback,
-			    user_data);
-
-	g_free (destination_uri);
+	_g_object_unref (archive->priv->extraction_destination);
+	archive->priv->extraction_destination = g_object_ref (destination);
+
+	fr_archive_progress_set_total_bytes (archive, _fr_archive_get_file_list_size (archive, file_list));
+	_fr_archive_activate_progress_update (archive);
+
+	FR_ARCHIVE_GET_CLASS (archive)->extract_files (archive,
+						       file_list,
+						       destination,
+						       base_dir,
+						       skip_older,
+						       overwrite,
+						       junk_paths,
+						       password,
+						       cancellable,
+						       callback,
+						       user_data);
 }
 
 
@@ -1441,42 +1357,41 @@ get_desired_destination_for_archive (GFile *file)
 }
 
 
-static char *
+static GFile *
 get_extract_here_destination (GFile   *file,
 			      GError **error)
 {
+	GFile *directory = NULL;
 	char  *desired_destination;
-	char  *destination = NULL;
 	int    n = 1;
-	GFile *directory;
 
 	desired_destination = get_desired_destination_for_archive (file);
 	do {
+		char *uri;
+
 		*error = NULL;
 
-		g_free (destination);
+		_g_object_unref (directory);
 		if (n == 1)
-			destination = g_strdup (desired_destination);
+			uri = g_strdup (desired_destination);
 		else
-			destination = g_strdup_printf ("%s%%20(%d)", desired_destination, n);
-
-		directory = g_file_new_for_uri (destination);
+			uri = g_strdup_printf ("%s%%20(%d)", desired_destination, n);
+		directory = g_file_new_for_uri (uri);
 		g_file_make_directory (directory, NULL, error);
-		g_object_unref (directory);
-
 		n++;
+
+		g_free (uri);
 	}
 	while (g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_EXISTS));
 
-	g_free (desired_destination);
-
 	if (*error != NULL) {
 		g_warning ("could not create destination folder: %s\n", (*error)->message);
-		g_free (destination);
-		destination = NULL;
+		_g_clear_object (&directory);
 	}
 
-	return destination;
+	g_free (desired_destination);
+
+	return directory;
 }
 
 
@@ -1490,7 +1405,7 @@ fr_archive_extract_here (FrArchive           *archive,
 			 GAsyncReadyCallback  callback,
 			 gpointer             user_data)
 {
-	char   *destination;
+	GFile  *destination;
 	GError *error = NULL;
 
 	destination = get_extract_here_destination (archive->priv->file, &error);
@@ -1522,27 +1437,23 @@ fr_archive_extract_here (FrArchive           *archive,
 			    callback,
 			    user_data);
 
-	g_free (destination);
+	g_object_unref (destination);
 
 	return TRUE;
 }
 
 
 void
-fr_archive_set_last_extraction_destination (FrArchive  *archive,
-					    const char *uri)
+fr_archive_set_last_extraction_destination (FrArchive *archive,
+					    GFile     *folder)
 {
-	if (uri == archive->priv->extraction_destination)
-		return;
-
-	g_free (archive->priv->extraction_destination);
-	archive->priv->extraction_destination = NULL;
-	if (uri != NULL)
-		archive->priv->extraction_destination = g_strdup (uri);
+	_g_clear_object (&archive->priv->extraction_destination);
+	if (folder != NULL)
+		archive->priv->extraction_destination = g_object_ref (folder);
 }
 
 
-const char *
+GFile *
 fr_archive_get_last_extraction_destination (FrArchive *archive)
 {
 	return archive->priv->extraction_destination;
@@ -1593,7 +1504,7 @@ fr_archive_rename (FrArchive           *archive,
 
 void
 fr_archive_paste_clipboard (FrArchive           *archive,
-			    char                *archive_uri,
+			    GFile               *file,
 			    char                *password,
 			    gboolean             encrypt_header,
 			    FrCompression        compression,
@@ -1601,14 +1512,14 @@ fr_archive_paste_clipboard (FrArchive           *archive,
 			    FrClipboardOp        op,
 			    char                *base_dir,
 			    GList               *files,
-			    char                *tmp_dir,
+			    GFile               *tmp_dir,
 			    char                *current_dir,
 			    GCancellable        *cancellable,
 			    GAsyncReadyCallback  callback,
 			    gpointer             user_data)
 {
 	FR_ARCHIVE_GET_CLASS (archive)->paste_clipboard (archive,
-							 archive_uri,
+							 file,
 							 password,
 							 encrypt_header,
 							 compression,
@@ -1630,7 +1541,6 @@ fr_archive_paste_clipboard (FrArchive           *archive,
 struct _DroppedItemsData {
 	FrArchive           *archive;
 	GList               *item_list;
-	char                *base_dir;
 	char                *dest_dir;
 	char                *password;
 	gboolean             encrypt_header;
@@ -1645,7 +1555,6 @@ struct _DroppedItemsData {
 static DroppedItemsData *
 dropped_items_data_new (FrArchive           *archive,
 			GList               *item_list,
-			const char          *base_dir,
 			const char          *dest_dir,
 			const char          *password,
 			gboolean             encrypt_header,
@@ -1659,9 +1568,7 @@ dropped_items_data_new (FrArchive           *archive,
 
 	data = g_new0 (DroppedItemsData, 1);
 	data->archive = archive;
-	data->item_list = _g_string_list_dup (item_list);
-	if (base_dir != NULL)
-		data->base_dir = g_strdup (base_dir);
+	data->item_list = _g_object_list_ref (item_list);
 	if (dest_dir != NULL)
 		data->dest_dir = g_strdup (dest_dir);
 	if (password != NULL)
@@ -1682,8 +1589,7 @@ dropped_items_data_free (DroppedItemsData *data)
 {
 	if (data == NULL)
 		return;
-	_g_string_list_free (data->item_list);
-	g_free (data->base_dir);
+	_g_object_list_unref (data->item_list);
 	g_free (data->dest_dir);
 	g_free (data->password);
 	_g_object_unref (data->cancellable);
@@ -1695,34 +1601,33 @@ static gboolean
 all_files_in_same_dir (GList *list)
 {
 	gboolean  same_dir = TRUE;
-	char     *first_basedir;
+	GFile    *first_parent;
 	GList    *scan;
 
 	if (list == NULL)
 		return FALSE;
 
-	first_basedir = _g_path_remove_level (list->data);
-	if (first_basedir == NULL)
+	first_parent = g_file_get_parent (G_FILE (list->data));
+	if (first_parent == NULL)
 		return TRUE;
 
-	for (scan = list->next; scan; scan = scan->next) {
-		char *path = scan->data;
-		char *basedir;
+	for (scan = list->next; same_dir && scan; scan = scan->next) {
+		GFile *file = G_FILE (scan->data);
+		GFile *parent;
 
-		basedir = _g_path_remove_level (path);
-		if (basedir == NULL) {
+		parent = g_file_get_parent (file);
+		if (parent == NULL) {
 			same_dir = FALSE;
 			break;
 		}
 
-		if (strcmp (first_basedir, basedir) != 0) {
+		if (_g_file_cmp_uris (first_parent, parent) != 0)
 			same_dir = FALSE;
-			g_free (basedir);
-			break;
-		}
-		g_free (basedir);
+
+		g_object_unref (parent);
 	}
-	g_free (first_basedir);
+
+	g_object_unref (first_parent);
 
 	return same_dir;
 }
@@ -1787,14 +1692,14 @@ add_dropped_items (DroppedItemsData *data)
 	 * fr_archive_add_items... */
 
 	if (all_files_in_same_dir (list)) {
-		char *first_base_dir;
+		GFile *first_parent;
 
 		data->item_list = NULL;
 
-		first_base_dir = _g_path_remove_level (list->data);
-		fr_archive_add_items (FR_ARCHIVE (archive),
+		first_parent = g_file_get_parent (G_FILE (list->data));
+		fr_archive_add_files (FR_ARCHIVE (archive),
 				      list,
-				      first_base_dir,
+				      first_parent,
 				      data->dest_dir,
 				      FALSE,
 				      data->password,
@@ -1805,38 +1710,41 @@ add_dropped_items (DroppedItemsData *data)
 				      add_dropped_items_ready_cb,
 				      data);
 
-		g_free (first_base_dir);
-		_g_string_list_free (list);
+		g_object_unref (first_parent);
+		_g_object_list_unref (list);
 		return;
 	}
 
 	/* ...else add a directory at a time. */
 
 	for (scan = list; scan; scan = scan->next) {
-		char *path = scan->data;
-		char *base_dir;
+		GFile *file = G_FILE (scan->data);
+		GList *singleton;
+		GFile *parent;
 
-		if (! _g_uri_query_is_dir (path))
+		if (! _g_file_query_is_dir (file))
 			continue;
 
 		data->item_list = g_list_remove_link (list, scan);
 
-		base_dir = _g_path_remove_level (path);
-		fr_archive_add_directory (FR_ARCHIVE (archive),
-					  _g_path_get_file_name (path),
-					  base_dir,
-					  data->dest_dir,
-					  FALSE,
-					  data->password,
-					  data->encrypt_header,
-					  data->compression,
-					  data->volume_size,
-					  data->cancellable,
-					  add_dropped_items_ready_cb,
-					  data);
-
-		g_free (base_dir);
-		g_free (path);
+		singleton = g_list_prepend (NULL, file);
+		parent = g_file_get_parent (file);
+		fr_archive_add_files (FR_ARCHIVE (archive),
+				      singleton,
+				      parent,
+				      data->dest_dir,
+				      FALSE,
+				      data->password,
+				      data->encrypt_header,
+				      data->compression,
+				      data->volume_size,
+				      data->cancellable,
+				      add_dropped_items_ready_cb,
+				      data);
+
+		g_list_free (singleton);
+		g_object_unref (parent);
+		g_object_unref (file);
 
 		return;
 	}
@@ -1848,23 +1756,14 @@ add_dropped_items (DroppedItemsData *data)
 	data->item_list = NULL;
 
 	if (all_files_in_same_dir (list)) {
-		char  *first_basedir;
-		GList *only_names_list = NULL;
-
-		first_basedir = _g_path_remove_level (list->data);
-		for (scan = list; scan; scan = scan->next) {
-			char *name;
-
-			name = g_uri_unescape_string (_g_path_get_file_name (scan->data), NULL);
-			only_names_list = g_list_prepend (only_names_list, name);
-		}
+		GFile *first_parent;
 
+		first_parent = g_file_get_parent (G_FILE (list->data));
 		fr_archive_add_files (FR_ARCHIVE (archive),
-				      only_names_list,
-				      first_basedir,
+				      list,
+				      first_parent,
 				      data->dest_dir,
 				      FALSE,
-				      FALSE,
 				      data->password,
 				      data->encrypt_header,
 				      data->compression,
@@ -1873,8 +1772,8 @@ add_dropped_items (DroppedItemsData *data)
 				      add_dropped_items_ready_cb,
 				      data);
 
-		_g_string_list_free (only_names_list);
-		g_free (first_basedir);
+		g_object_unref (first_parent);
+		_g_object_list_unref (list);
 	}
 	else
 		/* ...else call the archive specific function to add the files in the
@@ -1882,7 +1781,6 @@ add_dropped_items (DroppedItemsData *data)
 
 		FR_ARCHIVE_GET_CLASS (archive)->add_dropped_files (archive,
 								   list,
-								   data->base_dir,
 								   data->dest_dir,
 								   data->password,
 								   data->encrypt_header,
@@ -1899,7 +1797,6 @@ add_dropped_items (DroppedItemsData *data)
 void
 fr_archive_add_dropped_items (FrArchive           *archive,
 			      GList               *item_list,
-			      const char          *base_dir,
 			      const char          *dest_dir,
 			      const char          *password,
 			      gboolean             encrypt_header,
@@ -1911,7 +1808,6 @@ fr_archive_add_dropped_items (FrArchive           *archive,
 {
 	GSimpleAsyncResult *result;
 	GList              *scan;
-	char               *archive_uri;
 
 	result = g_simple_async_result_new (G_OBJECT (archive),
 					    callback,
@@ -1930,9 +1826,8 @@ fr_archive_add_dropped_items (FrArchive           *archive,
 	}
 
 	/* FIXME: make this check for all the add actions */
-	archive_uri = g_file_get_uri (archive->priv->file);
 	for (scan = item_list; scan; scan = scan->next) {
-		if (_g_uri_cmp (scan->data, archive_uri) == 0) {
+		if (_g_file_cmp_uris (G_FILE (scan->data), archive->priv->file) == 0) {
 			GError *error;
 
 			error = g_error_new_literal (FR_ERROR, FR_ERROR_GENERIC, _("You can't add an archive to itself."));
@@ -1940,17 +1835,14 @@ fr_archive_add_dropped_items (FrArchive           *archive,
 			g_simple_async_result_complete_in_idle (result);
 
 			g_error_free (error);
-			g_free (archive_uri);
 			return;
 		}
 	}
-	g_free (archive_uri);
 
 	if (archive->priv->dropped_items_data != NULL)
 		dropped_items_data_free (archive->priv->dropped_items_data);
 	archive->priv->dropped_items_data = dropped_items_data_new (archive,
 								    item_list,
-								    base_dir,
 								    dest_dir,
 								    password,
 								    encrypt_header,
@@ -2005,7 +1897,7 @@ fr_archive_change_name (FrArchive  *archive,
 	GFile      *parent;
 	GFile      *file;
 
-	name = _g_path_get_file_name (filename);
+	name = _g_path_get_basename (filename);
 
 	parent = g_file_get_parent (archive->priv->file);
 	file = g_file_get_child (parent, name);;
@@ -2111,7 +2003,11 @@ fr_archive_progress_inc_completed_files (FrArchive *self,
 
 	g_mutex_lock (&self->priv->progress_mutex);
 	self->priv->completed_files += new_completed;
-	fraction = (double) self->priv->completed_files / (self->priv->total_files + 1);
+	if (self->priv->total_files > 0)
+		fraction = (double) self->priv->completed_files / (self->priv->total_files + 1);
+	else
+		fraction = 0.0;
+	/*g_print ("%d / %d  : %f\n", self->priv->completed_files, self->priv->total_files + 1, fraction);*/
 	g_mutex_unlock (&self->priv->progress_mutex);
 
 	return fraction;
@@ -2130,6 +2026,36 @@ fr_archive_progress_set_total_bytes (FrArchive *self,
 }
 
 
+static double
+_set_completed_bytes (FrArchive *self,
+		      gsize      completed_bytes)
+{
+	double fraction;
+
+	self->priv->completed_bytes = completed_bytes;
+	if (self->priv->total_bytes > 0)
+		fraction = (double) self->priv->completed_bytes / (self->priv->total_bytes + 1);
+	else
+		fraction = 0.0;
+	/*g_print ("%" G_GSIZE_FORMAT " / %" G_GSIZE_FORMAT "  : %f\n", self->priv->completed_bytes, self->priv->total_bytes + 1, fraction);*/
+
+	return fraction;
+}
+
+
+double
+fr_archive_progress_set_completed_bytes (FrArchive *self,
+					 gsize      completed_bytes)
+{
+	double fraction;
+
+	g_mutex_lock (&self->priv->progress_mutex);
+	fraction = _set_completed_bytes (self, completed_bytes);
+	g_mutex_unlock (&self->priv->progress_mutex);
+
+	return fraction;
+}
+
 double
 fr_archive_progress_inc_completed_bytes (FrArchive *self,
 					 gsize      new_completed)
@@ -2137,9 +2063,7 @@ fr_archive_progress_inc_completed_bytes (FrArchive *self,
 	double fraction;
 
 	g_mutex_lock (&self->priv->progress_mutex);
-	self->priv->completed_bytes += new_completed;
-	fraction = (double) self->priv->completed_bytes / (self->priv->total_bytes + 1);
-	/*g_print ("%" G_GSIZE_FORMAT " / %" G_GSIZE_FORMAT "  : %f\n", self->priv->completed_bytes, self->priv->total_bytes + 1, fraction);*/
+	fraction = _set_completed_bytes (self, self->priv->completed_bytes + new_completed);
 	g_mutex_unlock (&self->priv->progress_mutex);
 
 	return fraction;
@@ -2176,21 +2100,21 @@ fr_archive_add_file (FrArchive *self,
 
 
 gboolean
-_g_uri_is_archive (const char *uri)
+_g_file_is_archive (GFile *file)
 {
-	GFile      *file;
 	const char *mime_type = NULL;
 	gboolean    is_archive = FALSE;
 	char       *buffer;
 	int         buffer_size;
 
-	file = g_file_new_for_uri (uri);
 	buffer_size = BUFFER_SIZE_FOR_PRELOAD;
 	buffer = g_new (char, buffer_size);
 
 	if (g_load_file_in_buffer (file, buffer, buffer_size, NULL)) {
-		gboolean result_uncertain;
+		char     *uri;
+		gboolean  result_uncertain;
 
+		uri = g_file_get_uri (file);
 		mime_type = g_content_type_guess (uri, (guchar *) buffer, buffer_size, &result_uncertain);
 		if (result_uncertain) {
 			mime_type = get_mime_type_from_magic_numbers (buffer, buffer_size);
@@ -2208,10 +2132,11 @@ _g_uri_is_archive (const char *uri)
 				}
 			}
 		}
+
+		g_free (uri);
 	}
 
 	g_free (buffer);
-	g_object_unref (file);
 
 	return is_archive;
 }
diff --git a/src/fr-archive.h b/src/fr-archive.h
index 88a71c0..a4b78cc 100644
--- a/src/fr-archive.h
+++ b/src/fr-archive.h
@@ -91,6 +91,7 @@ struct _FrArchive {
 	/*<protected>*/
 
 	gboolean       extract_here;
+	gssize         files_to_add_size;
 
 	/* features. */
 
@@ -202,7 +203,7 @@ struct _FrArchiveClass {
 	void          (*stoppable)         (FrArchive           *archive,
 			           	    gboolean             value);
 	void          (*working_archive)   (FrArchive           *archive,
-			           	    const char          *filename);
+			           	    const char          *uri);
 
 	/*< virtual functions >*/
 
@@ -224,8 +225,8 @@ struct _FrArchiveClass {
 					    GAsyncReadyCallback  callback,
 					    gpointer             user_data);
 	void          (*add_files)         (FrArchive           *archive,
-					    GList               *file_list,
-					    const char          *base_dir,
+					    GList               *file_list, /* GFile list */
+					    GFile               *base_dir,
 					    const char          *dest_dir,
 					    gboolean             update,
 					    gboolean             recursive,
@@ -238,7 +239,7 @@ struct _FrArchiveClass {
 					    gpointer             user_data);
 	void          (*extract_files)     (FrArchive           *archive,
 	    				    GList               *file_list,
-	    				    const char          *destination,
+	    				    GFile               *destination,
 	    				    const char          *base_dir,
 	    				    gboolean             skip_older,
 	    				    gboolean             overwrite,
@@ -270,7 +271,7 @@ struct _FrArchiveClass {
 					    GAsyncReadyCallback  callback,
 					    gpointer             user_data);
 	void          (*paste_clipboard)   (FrArchive           *archive,
-					    char                *archive_uri,
+					    GFile               *archive_file,
 					    char                *password,
 					    gboolean             encrypt_header,
 					    FrCompression        compression,
@@ -278,14 +279,13 @@ struct _FrArchiveClass {
 					    FrClipboardOp        op,
 					    char                *base_dir,
 					    GList               *files,
-					    char                *tmp_dir,
+					    GFile               *tmp_dir,
 					    char                *current_dir,
 					    GCancellable        *cancellable,
 					    GAsyncReadyCallback  callback,
 					    gpointer             user_data);
 	void          (*add_dropped_files) (FrArchive           *archive,
 				   	    GList               *item_list,
-				   	    const char          *base_dir,
 				   	    const char          *dest_dir,
 				   	    const char          *password,
 				   	    gboolean             encrypt_header,
@@ -340,11 +340,10 @@ gboolean      fr_archive_operation_finish        (FrArchive           *archive,
 						  GAsyncResult        *result,
 						  GError             **error);
 void          fr_archive_add_files               (FrArchive           *archive,
-						  GList               *file_list,
-						  const char          *base_dir,
+						  GList               *file_list, /* GFile list */
+						  GFile               *base_dir,
 						  const char          *dest_dir,
 						  gboolean             update,
-						  gboolean             recursive,
 						  const char          *password,
 						  gboolean             encrypt_header,
 						  FrCompression        compression,
@@ -352,11 +351,11 @@ void          fr_archive_add_files               (FrArchive           *archive,
 						  GCancellable        *cancellable,
 						  GAsyncReadyCallback  callback,
 						  gpointer             user_data);
-void          fr_archive_add_with_wildcard       (FrArchive           *archive,
+void          fr_archive_add_files_with_filter   (FrArchive           *archive,
+						  GFile               *base_dir,
 						  const char          *include_files,
 						  const char          *exclude_files,
 						  const char          *exclude_folders,
-						  const char          *base_dir,
 						  const char          *dest_dir,
 						  gboolean             update,
 						  gboolean             follow_links,
@@ -367,30 +366,6 @@ void          fr_archive_add_with_wildcard       (FrArchive           *archive,
 						  GCancellable        *cancellable,
 						  GAsyncReadyCallback  callback,
 						  gpointer             user_data);
-void          fr_archive_add_directory           (FrArchive           *archive,
-						  const char          *directory,
-						  const char          *base_dir,
-						  const char          *dest_dir,
-						  gboolean             update,
-						  const char          *password,
-						  gboolean             encrypt_header,
-						  FrCompression        compression,
-						  guint                volume_size,
-						  GCancellable        *cancellable,
-						  GAsyncReadyCallback  callback,
-						  gpointer             user_data);
-void          fr_archive_add_items               (FrArchive           *archive,
-						  GList               *item_list,
-						  const char          *base_dir,
-						  const char          *dest_dir,
-						  gboolean             update,
-						  const char          *password,
-						  gboolean             encrypt_header,
-						  FrCompression        compression,
-						  guint                volume_size,
-						  GCancellable        *cancellable,
-						  GAsyncReadyCallback  callback,
-						  gpointer             user_data);
 void          fr_archive_remove                  (FrArchive           *archive,
 						  GList               *file_list,
 						  FrCompression        compression,
@@ -399,18 +374,7 @@ void          fr_archive_remove                  (FrArchive           *archive,
 						  gpointer             user_data);
 void          fr_archive_extract                 (FrArchive           *archive,
 						  GList               *file_list,
-						  const char          *dest_uri,
-						  const char          *base_dir,
-						  gboolean             skip_older,
-						  gboolean             overwrite,
-						  gboolean             junk_path,
-						  const char          *password,
-		       	       	       	          GCancellable        *cancellable,
-		       	       	       	          GAsyncReadyCallback  callback,
-		       	       	       	          gpointer             user_data);
-void          fr_archive_extract_to_local        (FrArchive           *archive,
-						  GList               *file_list,
-						  const char          *dest_path,
+						  GFile               *destination,
 						  const char          *base_dir,
 						  gboolean             skip_older,
 						  gboolean             overwrite,
@@ -429,8 +393,8 @@ gboolean      fr_archive_extract_here            (FrArchive           *archive,
 		       	       	       	          gpointer             user_data);
 void          fr_archive_set_last_extraction_destination
 						 (FrArchive           *archive,
-						  const char          *uri);
-const char *  fr_archive_get_last_extraction_destination
+						  GFile               *folder);
+GFile *       fr_archive_get_last_extraction_destination
 						 (FrArchive           *archive);
 void          fr_archive_test                    (FrArchive           *archive,
 						  const char          *password,
@@ -449,7 +413,7 @@ void          fr_archive_rename                  (FrArchive           *archive,
 						  GAsyncReadyCallback  callback,
 						  gpointer             user_data);
 void          fr_archive_paste_clipboard         (FrArchive           *archive,
-						  char                *archive_uri,
+						  GFile               *file,
 						  char                *password,
 						  gboolean             encrypt_header,
 						  FrCompression        compression,
@@ -457,14 +421,13 @@ void          fr_archive_paste_clipboard         (FrArchive           *archive,
 						  FrClipboardOp        op,
 						  char                *base_dir,
 						  GList               *files,
-						  char                *tmp_dir,
+						  GFile               *tmp_dir,
 						  char                *current_dir,
 		       	       	       	          GCancellable        *cancellable,
 		       	       	       	          GAsyncReadyCallback  callback,
 		       	       	       	          gpointer             user_data);
 void          fr_archive_add_dropped_items       (FrArchive           *archive,
 						  GList               *item_list,
-						  const char          *base_dir,
 						  const char          *dest_dir,
 						  const char          *password,
 						  gboolean             encrypt_header,
@@ -508,6 +471,9 @@ double        fr_archive_progress_inc_completed_files
 						  int                  new_completed);
 void          fr_archive_progress_set_total_bytes (FrArchive           *archive,
 						  gsize                total);
+double        fr_archive_progress_set_completed_bytes
+						 (FrArchive           *self,
+						  gsize                completed_bytes);
 double        fr_archive_progress_inc_completed_bytes
 						 (FrArchive           *archive,
 						  gsize                new_completed);
@@ -517,6 +483,6 @@ void          fr_archive_add_file                (FrArchive           *archive,
 
 /* utilities */
 
-gboolean      _g_uri_is_archive                  (const char          *uri);
+gboolean      _g_file_is_archive                 (GFile               *file);
 
 #endif /* FR_ARCHIVE_H */
diff --git a/src/fr-command-7z.c b/src/fr-command-7z.c
index f407d89..ab59fa9 100644
--- a/src/fr-command-7z.c
+++ b/src/fr-command-7z.c
@@ -126,7 +126,7 @@ list__process_line (char     *line,
 				if (fdata->dir)
 					fdata->name = _g_path_get_dir_name (fdata->full_path);
 				else
-					fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+					fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
 				fdata->path = _g_path_remove_level (fdata->full_path);
 				fr_archive_add_file (archive, fdata);
 				self->fdata = NULL;
diff --git a/src/fr-command-ace.c b/src/fr-command-ace.c
index 24a31bf..3ddbc45 100644
--- a/src/fr-command-ace.c
+++ b/src/fr-command-ace.c
@@ -142,7 +142,7 @@ process_line (char     *line,
 
 	g_strfreev (fields);
 
-	fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+	fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
 	fdata->path = _g_path_remove_level (fdata->full_path);
 
 	if (*fdata->name == 0)
diff --git a/src/fr-command-alz.c b/src/fr-command-alz.c
index adfeb0a..5be8306 100644
--- a/src/fr-command-alz.c
+++ b/src/fr-command-alz.c
@@ -134,7 +134,7 @@ process_line (char     *line,
 		fdata->name = _g_path_get_dir_name (fdata->full_path);
 	}
 	else {
-		fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+		fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
 	}
 
 	fdata->path = _g_path_remove_level (fdata->full_path);
diff --git a/src/fr-command-ar.c b/src/fr-command-ar.c
index eea3786..84c49e5 100644
--- a/src/fr-command-ar.c
+++ b/src/fr-command-ar.c
@@ -170,7 +170,7 @@ process_line (char     *line,
 	g_strfreev (fields);
 	g_free (field_name);
 
-	fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+	fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
 	fdata->path = _g_path_remove_level (fdata->full_path);
 
 	if (*fdata->name == 0)
diff --git a/src/fr-command-arj.c b/src/fr-command-arj.c
index 19646ef..c603fdf 100644
--- a/src/fr-command-arj.c
+++ b/src/fr-command-arj.c
@@ -120,7 +120,7 @@ list__process_line (char     *line,
 
 		fdata->link = NULL;
 
-		fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+		fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
 		fdata->path = _g_path_remove_level (fdata->full_path);
 	}
 	else if (arj_comm->line_no == 2) { /* Read file size and date. */
diff --git a/src/fr-command-cfile.c b/src/fr-command-cfile.c
index 15cd91c..5dcce81 100644
--- a/src/fr-command-cfile.c
+++ b/src/fr-command-cfile.c
@@ -70,7 +70,7 @@ get_uncompressed_name_from_archive (FrCommand  *comm,
 			str = g_string_new ("");
 			while (g_input_stream_read (stream, buffer, 1, NULL, NULL) > 0) {
 				if (buffer[0] == '\0') {
-					filename = g_strdup (_g_path_get_file_name (str->str));
+					filename = g_strdup (_g_path_get_basename (str->str));
 #ifdef DEBUG
 					g_message ("filename is: %s", filename);
 #endif
@@ -95,6 +95,7 @@ list__process_line (char     *line,
 	FrCommand  *comm = FR_COMMAND (data);
 	FileData   *fdata;
 	char      **fields;
+	GFile      *file;
 	char       *filename;
 
 	fdata = file_data_new ();
@@ -104,29 +105,31 @@ list__process_line (char     *line,
 		fdata->size = g_ascii_strtoull (fields[1], NULL, 10);
 	g_strfreev (fields);
 
+	file = g_file_new_for_path (comm->filename);
+
 	if (fdata->size == 0)
-		fdata->size = _g_uri_get_file_size (comm->filename);
+		fdata->size = _g_file_get_file_size (file);
 
 	filename = get_uncompressed_name_from_archive (comm, comm->filename);
 	if (filename == NULL)
 		filename = _g_path_remove_extension (comm->filename);
 
-	fdata->full_path = g_strconcat ("/",
-					_g_path_get_file_name (filename),
-					NULL);
+	fdata->full_path = g_strconcat ("/", _g_path_get_basename (filename), NULL);
 	g_free (filename);
 
 	fdata->original_path = fdata->full_path + 1;
 	fdata->link = NULL;
-	fdata->modified = _g_path_get_file_mtime (comm->filename);
+	fdata->modified = _g_file_get_file_mtime (file);
 
-	fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+	fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
 	fdata->path = _g_path_remove_level (fdata->full_path);
 
 	if (*fdata->name == 0)
 		file_data_free (fdata);
 	else
 		fr_archive_add_file (FR_ARCHIVE (comm), fdata);
+
+	g_object_unref (file);
 }
 
 
@@ -153,21 +156,23 @@ fr_command_cfile_list (FrCommand *comm)
 
 		FileData *fdata;
 		char     *filename;
+		GFile    *file;
 
 		fdata = file_data_new ();
 
 		filename = _g_path_remove_extension (comm->filename);
 		fdata->full_path = g_strconcat ("/",
-						_g_path_get_file_name (filename),
+						_g_path_get_basename (filename),
 						NULL);
 		g_free (filename);
 
+		file = g_file_new_for_path (comm->filename);
+
 		fdata->original_path = fdata->full_path + 1;
 		fdata->link = NULL;
-		fdata->size = _g_path_get_file_size (comm->filename);
-		fdata->modified = _g_path_get_file_mtime (comm->filename);
-
-		fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+		fdata->size = _g_file_get_file_size (file);
+		fdata->modified = _g_file_get_file_mtime (file);
+		fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
 		fdata->path = _g_path_remove_level (fdata->full_path);
 
 		if (*fdata->name == 0)
@@ -175,6 +180,8 @@ fr_command_cfile_list (FrCommand *comm)
 		else
 			fr_archive_add_file (FR_ARCHIVE (comm), fdata);
 
+		g_object_unref (file);
+
 		return FALSE;
 	}
 
@@ -336,7 +343,7 @@ fr_command_cfile_extract (FrCommand  *comm,
 	temp_dir = _g_path_get_temp_work_dir (NULL);
 	temp_file = g_strconcat (temp_dir,
 				 "/",
-				 _g_path_get_file_name (comm->filename),
+				 _g_path_get_basename (comm->filename),
 				 NULL);
 
 	fr_process_begin_command (comm->process, "cp");
@@ -418,7 +425,7 @@ fr_command_cfile_extract (FrCommand  *comm,
 
 	compr_file = get_uncompressed_name_from_archive (comm, comm->filename);
 	if (compr_file == NULL)
-		compr_file = _g_path_remove_extension (_g_path_get_file_name (comm->filename));
+		compr_file = _g_path_remove_extension (_g_path_get_basename (comm->filename));
 	dest_file = g_strconcat (dest_dir,
 				 "/",
 				 compr_file,
diff --git a/src/fr-command-cpio.c b/src/fr-command-cpio.c
index 266968a..dcdf1b7 100644
--- a/src/fr-command-cpio.c
+++ b/src/fr-command-cpio.c
@@ -151,7 +151,7 @@ list__process_line (char     *line,
 	if (fdata->dir)
 		fdata->name = _g_path_get_dir_name (fdata->full_path);
 	else
-		fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+		fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
 	fdata->path = _g_path_remove_level (fdata->full_path);
 
 	if (*fdata->name == 0)
diff --git a/src/fr-command-dpkg.c b/src/fr-command-dpkg.c
index 7325a71..3c64f88 100644
--- a/src/fr-command-dpkg.c
+++ b/src/fr-command-dpkg.c
@@ -140,7 +140,7 @@ process_data_line (char     *line,
         if (fdata->dir)
                 fdata->name = _g_path_get_dir_name (fdata->full_path);
         else
-                fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+                fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
         fdata->path = _g_path_remove_level (fdata->full_path);
 
         if (*fdata->name == 0)
diff --git a/src/fr-command-iso.c b/src/fr-command-iso.c
index 9a19863..1132652 100644
--- a/src/fr-command-iso.c
+++ b/src/fr-command-iso.c
@@ -111,7 +111,7 @@ list__process_line (char     *line,
 		else
 			fdata->full_path = g_strstrip (g_strconcat (comm_iso->cur_path, name_field, NULL));
 		fdata->original_path = fdata->full_path;
-		fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+		fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
 		fdata->path = _g_path_remove_level (fdata->full_path);
 
 		fr_archive_add_file (FR_ARCHIVE (comm), fdata);
@@ -162,8 +162,9 @@ fr_command_iso_extract (FrCommand  *comm,
 		const char *filename;
 		char       *file_dir;
 		char       *temp_dest_dir = NULL;
+		GFile      *directory;
 
-		filename = _g_path_get_file_name (path);
+		filename = _g_path_get_basename (path);
 		file_dir = _g_path_remove_level (path);
 		if ((file_dir != NULL) && (strcmp (file_dir, "/") != 0))
 			temp_dest_dir = g_build_filename (dest_dir, file_dir, NULL);
@@ -174,7 +175,8 @@ fr_command_iso_extract (FrCommand  *comm,
 		if (temp_dest_dir == NULL)
 			continue;
 
-		_g_path_make_directory_tree (temp_dest_dir, 0700, NULL);
+		directory = g_file_new_for_path (temp_dest_dir);
+		_g_file_make_directory_tree (directory, 0700, NULL);
 
 		fr_process_begin_command (comm->process, "sh");
 		fr_process_set_working_dir (comm->process, temp_dest_dir);
@@ -186,6 +188,7 @@ fr_command_iso_extract (FrCommand  *comm,
 		fr_process_add_arg (comm->process, filename);
 		fr_process_end_command (comm->process);
 
+		g_object_unref (directory);
 		g_free (temp_dest_dir);
 	}
 }
diff --git a/src/fr-command-jar.c b/src/fr-command-jar.c
index a72bb56..4b999ab 100644
--- a/src/fr-command-jar.c
+++ b/src/fr-command-jar.c
@@ -57,7 +57,7 @@ fr_command_jar_add (FrCommand     *comm,
 
 	for (scan = file_list; scan; scan = scan->next) {
 		char *filename = scan->data;
-		char *path = _g_uri_build (base_dir, filename, NULL);
+		char *path = g_build_filename (base_dir, filename, NULL);
 		char *package = NULL;
 
 		if (_g_filename_has_extension (filename, ".java"))
@@ -71,9 +71,9 @@ fr_command_jar_add (FrCommand     *comm,
 			JarData *newdata = g_new0 (JarData, 1);
 
 			newdata->package_minus_one_level = _g_path_remove_level (package);
-			newdata->link_name = g_strdup (_g_path_get_file_name (package));
+			newdata->link_name = g_strdup (_g_path_get_basename (package));
 			newdata->rel_path = _g_path_remove_level (filename);
-			newdata->filename = g_strdup (_g_path_get_file_name (filename));
+			newdata->filename = g_strdup (_g_path_get_basename (filename));
 			jardata_list = g_list_append (jardata_list, newdata);
 		}
 
@@ -85,17 +85,20 @@ fr_command_jar_add (FrCommand     *comm,
 	for (scan = jardata_list; scan ; scan = scan->next) {
 		JarData *jdata = scan->data;
 		char    *pack_path;
+		GFile   *directory;
 		char    *old_link;
 		char    *link_name;
 		int      retval;
 
-		pack_path = _g_uri_build (tmp_dir, jdata->package_minus_one_level, NULL);
-		if (! _g_path_make_directory_tree (pack_path, 0755, NULL)) {
+		pack_path = g_build_filename (tmp_dir, jdata->package_minus_one_level, NULL);
+		directory = g_file_new_for_path (pack_path);
+		if (! _g_file_make_directory_tree (directory, 0755, NULL)) {
+			g_object_unref (directory);
 			g_free (pack_path);
 			continue;
 		}
 
-		old_link = _g_uri_build (base_dir, jdata->rel_path, NULL);
+		old_link = g_build_filename (base_dir, jdata->rel_path, NULL);
 		link_name = g_build_filename (pack_path, jdata->link_name, NULL);
 
 		retval = symlink (old_link, link_name);
@@ -108,6 +111,7 @@ fr_command_jar_add (FrCommand     *comm,
 
 		g_free (link_name);
 		g_free (old_link);
+		g_object_unref (directory);
 		g_free (pack_path);
 	}
 
diff --git a/src/fr-command-lha.c b/src/fr-command-lha.c
index 32301ed..da5c577 100644
--- a/src/fr-command-lha.c
+++ b/src/fr-command-lha.c
@@ -190,7 +190,7 @@ process_line (char     *line,
 	if (fdata->dir)
 		fdata->name = _g_path_get_dir_name (fdata->full_path);
 	else
-		fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+		fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
 
 	fdata->path = _g_path_remove_level (fdata->full_path);
 
diff --git a/src/fr-command-lrzip.c b/src/fr-command-lrzip.c
index 2e542e4..de73fd9 100644
--- a/src/fr-command-lrzip.c
+++ b/src/fr-command-lrzip.c
@@ -51,7 +51,7 @@ list__process_line (char     *line,
 
 	fdata->encrypted = FALSE;
 
-	char *new_fname = g_strdup (_g_path_get_file_name (comm->filename));
+	char *new_fname = g_strdup (_g_path_get_basename (comm->filename));
 	if (g_str_has_suffix (new_fname, ".lrz"))
 		new_fname[strlen (new_fname) - 4] = '\0';
 
diff --git a/src/fr-command-rar.c b/src/fr-command-rar.c
index e098427..a0731c7 100644
--- a/src/fr-command-rar.c
+++ b/src/fr-command-rar.c
@@ -153,7 +153,7 @@ process_line (char     *line,
 					fdata->dir = TRUE;
 				}
 				else
-					fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+					fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
 
 				fr_archive_add_file (FR_ARCHIVE (comm), fdata);
 				rar_comm->fdata = NULL;
@@ -280,7 +280,7 @@ parse_progress_line (FrCommand  *comm,
 			if ((len > 5) && (strncmp (filename + len - 5, "  OK ", 5) == 0))
 				filename[len - 5] = 0;
 
-			msg = g_strdup_printf (message_format, _g_path_get_file_name (filename), NULL);
+			msg = g_strdup_printf (message_format, _g_path_get_basename (filename), NULL);
 			fr_archive_message (archive, msg);
 
 			g_free (msg);
diff --git a/src/fr-command-rpm.c b/src/fr-command-rpm.c
index 88b42c7..5593799 100644
--- a/src/fr-command-rpm.c
+++ b/src/fr-command-rpm.c
@@ -159,7 +159,7 @@ list__process_line (char     *line,
 	if (fdata->dir)
 		fdata->name = _g_path_get_dir_name (fdata->full_path);
 	else
-		fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+		fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
 	fdata->path = _g_path_remove_level (fdata->full_path);
 
 	if (*fdata->name == 0)
diff --git a/src/fr-command-tar.c b/src/fr-command-tar.c
index 471f5d8..f630fb6 100644
--- a/src/fr-command-tar.c
+++ b/src/fr-command-tar.c
@@ -175,7 +175,7 @@ process_line (char     *line,
 	if (fdata->dir)
 		fdata->name = _g_path_get_dir_name (fdata->full_path);
 	else
-		fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+		fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
 	fdata->path = _g_path_remove_level (fdata->full_path);
 
 	if (*fdata->name == 0)
@@ -290,7 +290,7 @@ process_line__generic (char     *line,
 		fr_archive_progress (archive, fr_archive_progress_inc_completed_files (archive, 1));
 	}
 	else {
-		char *msg = g_strdup_printf (message_format, _g_path_get_file_name (line), NULL);
+		char *msg = g_strdup_printf (message_format, _g_path_get_basename (line), NULL);
 		fr_archive_message (archive, msg);
 		g_free (msg);
 	}
@@ -830,7 +830,7 @@ get_temp_name (FrCommandTar *c_tar,
 
 	template = g_strconcat (dirname, "/.fr-XXXXXX", NULL);
 	result = mkdtemp (template);
-	temp_name = g_build_filename (result, _g_path_get_file_name (filepath), NULL);
+	temp_name = g_build_filename (result, _g_path_get_basename (filepath), NULL);
 	g_free (template);
 
 	return temp_name;
diff --git a/src/fr-command-unarchiver.c b/src/fr-command-unarchiver.c
index c88685e..b1c7425 100644
--- a/src/fr-command-unarchiver.c
+++ b/src/fr-command-unarchiver.c
@@ -109,7 +109,7 @@ list_command_completed (gpointer data)
 				if (fdata->dir)
 					fdata->name = _g_path_get_dir_name (fdata->full_path);
 				else
-					fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+					fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
 				fdata->path = _g_path_remove_level (fdata->full_path);
 
 				fr_archive_add_file (FR_ARCHIVE (unar_comm), fdata);
diff --git a/src/fr-command-unstuff.c b/src/fr-command-unstuff.c
index b89465c..e1c644f 100644
--- a/src/fr-command-unstuff.c
+++ b/src/fr-command-unstuff.c
@@ -159,7 +159,7 @@ process_line (char     *line,
 	fdata->full_path = filename;
 	fdata->original_path = filename;
 	fdata->link = NULL;
-	fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+	fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
 	fdata->path = _g_path_remove_level (fdata->full_path);
 
 	fdata->size = 0;
diff --git a/src/fr-command-zip.c b/src/fr-command-zip.c
index 8d5707f..617818d 100644
--- a/src/fr-command-zip.c
+++ b/src/fr-command-zip.c
@@ -144,7 +144,7 @@ list__process_line (char     *line,
 	if (fdata->dir)
 		fdata->name = _g_path_get_dir_name (fdata->full_path);
 	else
-		fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+		fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
 	fdata->path = _g_path_remove_level (fdata->full_path);
 
 	if (*fdata->name == 0)
diff --git a/src/fr-command-zoo.c b/src/fr-command-zoo.c
index 13245e0..a5b6826 100644
--- a/src/fr-command-zoo.c
+++ b/src/fr-command-zoo.c
@@ -201,7 +201,7 @@ process_zoo_line (char     *line,
 		fdata->original_path = fdata->full_path + 1;
 	}
 
-	fdata->name = g_strdup (_g_path_get_file_name (fdata->full_path));
+	fdata->name = g_strdup (_g_path_get_basename (fdata->full_path));
 	fdata->path = _g_path_remove_level (fdata->full_path);
 
 	if (*fdata->name == 0)
diff --git a/src/fr-command.c b/src/fr-command.c
index a739d4d..3d5d3cc 100644
--- a/src/fr-command.c
+++ b/src/fr-command.c
@@ -53,11 +53,11 @@ typedef struct {
 	char               *uri;
 	FrAction            action;
 	GList              *file_list;
-	char               *base_uri;
+	GFile              *base_dir;
 	char               *dest_dir;
 	gboolean            update;
 	gboolean            recursive;
-	char               *tmp_dir;
+	GFile              *tmp_dir;
 	guint               source_id;
 	char               *password;
 	gboolean            encrypt_header;
@@ -76,8 +76,8 @@ xfer_data_free (XferData *data)
 
 	g_free (data->uri);
 	g_free (data->password);
-	_g_string_list_free (data->file_list);
-	g_free (data->base_uri);
+	_g_object_list_unref (data->file_list);
+	_g_object_unref (data->base_dir);
 	g_free (data->dest_dir);
 	g_free (data->tmp_dir);
 	_g_object_unref (data->cancellable);
@@ -103,8 +103,8 @@ enum {
 struct _FrCommandPrivate {
 	GFile     *local_copy;
 	gboolean   is_remote;
-	char      *temp_dir;
-	char      *temp_extraction_dir;
+	GFile     *temp_dir;
+	GFile     *temp_extraction_dir;
 	gboolean   remote_extraction;
 };
 
@@ -114,17 +114,16 @@ _fr_command_remove_temp_work_dir (FrCommand *self)
 {
 	if (self->priv->temp_dir == NULL)
 		return;
-	_g_path_remove_directory (self->priv->temp_dir);
-	g_free (self->priv->temp_dir);
-	self->priv->temp_dir = NULL;
+	_g_file_remove_directory (self->priv->temp_dir, NULL, NULL);
+	_g_clear_object (&self->priv->temp_dir);
 }
 
 
-static const char *
+static GFile *
 _fr_command_get_temp_work_dir (FrCommand *self)
 {
 	_fr_command_remove_temp_work_dir (self);
-	self->priv->temp_dir = _g_path_get_temp_work_dir (NULL);
+	self->priv->temp_dir = _g_file_get_temp_work_dir (NULL);
 	return self->priv->temp_dir;
 }
 
@@ -194,68 +193,64 @@ static void
 move_here (FrArchive    *archive,
 	   GCancellable *cancellable)
 {
-	const char *extraction_destination;
-	char       *content_uri;
-	char       *parent;
-	char       *parent_parent;
-	char       *new_content_uri;
-	GFile      *source, *destination, *parent_file;
-	GError     *error = NULL;
+	GFile  *extraction_destination;
+	GFile  *directory_content;
+	GFile  *parent;
+	GFile  *parent_parent;
+	char   *content_name;
+	GFile  *new_directory_content;
+	GError *error = NULL;
 
 	extraction_destination = fr_archive_get_last_extraction_destination (archive);
-	content_uri = _g_uri_get_dir_content_if_unique (extraction_destination);
-	if (content_uri == NULL)
+	directory_content = _g_file_get_dir_content_if_unique (extraction_destination);
+	if (directory_content == NULL)
 		return;
 
-	parent = _g_path_remove_level (content_uri);
-
-	if (_g_uri_cmp (parent, extraction_destination) == 0) {
-		char *new_uri;
+	parent = g_file_get_parent (directory_content);
 
-		new_uri = _g_uri_create_alternative_for_uri (extraction_destination);
+	if (g_file_equal (parent, extraction_destination)) {
+		GFile *new_destination;
 
-		source = g_file_new_for_uri (extraction_destination);
-		destination = g_file_new_for_uri (new_uri);
-		if (! g_file_move (source, destination, 0, NULL, NULL, NULL, &error)) {
-			g_warning ("could not rename %s to %s: %s", extraction_destination, new_uri, error->message);
+		new_destination = _g_file_create_alternative_for_file (extraction_destination);
+		if (! g_file_move (extraction_destination, new_destination, 0, cancellable, NULL, NULL, &error)) {
+			g_warning ("%s", error->message);
 			g_clear_error (&error);
 		}
-		g_object_unref (source);
-		g_object_unref (destination);
 
-		fr_archive_set_last_extraction_destination (archive, new_uri);
+		fr_archive_set_last_extraction_destination (archive, new_destination);
 
-		g_free (parent);
+		g_object_unref (directory_content);
+		directory_content = _g_file_get_dir_content_if_unique (new_destination);
+		g_object_unref (new_destination);
 
-		content_uri = _g_uri_get_dir_content_if_unique (new_uri);
-		if (content_uri == NULL)
+		if (directory_content == NULL)
 			return;
 
-		parent = _g_path_remove_level (content_uri);
+		g_object_unref (parent);
+		parent = g_file_get_parent (directory_content);
 	}
 
-	parent_parent = _g_path_remove_level (parent);
-	new_content_uri = _g_uri_create_alternative (parent_parent, _g_path_get_file_name (content_uri));
+	parent_parent = g_file_get_parent (parent);
+	content_name = g_file_get_basename (directory_content);
+	new_directory_content = _g_file_create_alternative (parent_parent, content_name);
+	g_free (content_name);
 
-	source = g_file_new_for_uri (content_uri);
-	destination = g_file_new_for_uri (new_content_uri);
-	if (! g_file_move (source, destination, 0, NULL, NULL, NULL, &error)) {
-		g_warning ("could not rename %s to %s: %s", content_uri, new_content_uri, error->message);
+	if (! g_file_move (directory_content, new_directory_content, 0, cancellable, NULL, NULL, &error)) {
+		g_warning ("%s", error->message);
 		g_clear_error (&error);
 	}
 
-	parent_file = g_file_new_for_uri (parent);
-	if (! g_file_delete (parent_file, cancellable, &error)) {
-		g_warning ("could not remove directory %s: %s", parent, error->message);
+	if (! g_file_delete (parent, cancellable, &error)) {
+		g_warning ("%s", error->message);
 		g_clear_error (&error);
 	}
-	g_object_unref (parent_file);
 
-	fr_archive_set_last_extraction_destination (archive, new_content_uri);
+	fr_archive_set_last_extraction_destination (archive, new_directory_content);
 
-	g_free (parent_parent);
-	g_free (parent);
-	g_free (content_uri);
+	g_object_unref (new_directory_content);
+	g_object_unref (parent_parent);
+	g_object_unref (parent);
+	g_object_unref (directory_content);
 }
 
 
@@ -269,9 +264,8 @@ copy_extracted_files_done (GError   *error,
 	if (error != NULL)
 		g_simple_async_result_set_from_error (xfer_data->result, error);
 
-	_g_path_remove_directory (self->priv->temp_extraction_dir);
-	g_free (self->priv->temp_extraction_dir);
-	self->priv->temp_extraction_dir = NULL;
+	_g_file_remove_directory (self->priv->temp_extraction_dir, NULL, NULL);
+	_g_clear_object (&self->priv->temp_extraction_dir);
 
 	if ((error == NULL) && (xfer_data->archive->extract_here))
 		move_here (xfer_data->archive, xfer_data->cancellable);
@@ -331,19 +325,25 @@ static void
 fr_command_add (FrCommand  *self,
 		const char *from_file,
 		GList      *file_list,
-		const char *base_dir,
+		GFile      *base_dir,
 		gboolean    update,
 		gboolean    recursive)
 {
+	char *base_dir_path;
+
 	fr_process_set_out_line_func (self->process, NULL, NULL);
 	fr_process_set_err_line_func (self->process, NULL, NULL);
 
+	base_dir_path = g_file_get_path (base_dir);
+
 	FR_COMMAND_GET_CLASS (G_OBJECT (self))->add (self,
 						     from_file,
 						     file_list,
-						     base_dir,
+						     base_dir_path,
 						     update,
 						     recursive);
+
+	g_free (base_dir_path);
 }
 
 
@@ -363,21 +363,28 @@ static void
 fr_command_extract (FrCommand  *self,
 		    const char *from_file,
 		    GList      *file_list,
-		    const char *dest_dir,
+		    GFile      *destination,
 		    gboolean    overwrite,
 		    gboolean    skip_older,
 		    gboolean    junk_paths)
 {
+	char *destination_path;
+
 	fr_process_set_out_line_func (self->process, NULL, NULL);
 	fr_process_set_err_line_func (self->process, NULL, NULL);
 
+	destination_path = g_file_get_path (destination);
+	g_return_if_fail (destination_path != NULL);
+
 	FR_COMMAND_GET_CLASS (G_OBJECT (self))->extract (self,
 							 from_file,
 							 file_list,
-							 dest_dir,
+							 destination_path,
 							 overwrite,
 							 skip_older,
 							 junk_paths);
+
+	g_free (destination_path);
 }
 
 
@@ -595,7 +602,7 @@ fr_command_finalize (GObject *object)
 
 	_g_object_unref (self->process);
 	_fr_command_remove_temp_work_dir (self);
-	g_free (self->priv->temp_extraction_dir);
+	_g_clear_object (&self->priv->temp_extraction_dir);
 
 	if (G_OBJECT_CLASS (fr_command_parent_class)->finalize)
 		G_OBJECT_CLASS (fr_command_parent_class)->finalize (object);
@@ -763,47 +770,43 @@ fr_command_list (FrArchive           *archive,
 /* -- add -- */
 
 
-static char *
-create_tmp_base_dir (const char *base_dir,
-		     const char *dest_path)
-{
-	char *dest_dir;
-	char *temp_dir;
-	char *tmp;
-	char *parent_dir;
-	char *dir;
-
-	if ((dest_path == NULL)
-	    || (*dest_path == '\0')
-	    || (strcmp (dest_path, "/") == 0))
-	{
-		return g_strdup (base_dir);
-	}
+static GFile *
+create_tmp_base_dir (GFile      *base_dir,
+		     const char *destination)
+{
+	GFile  *temp_dir;
+	char   *destination_parent;
+	GFile  *parent_dir;
+	GFile  *dir;
+	char   *path;
+	GError *error = NULL;
 
-	dest_dir = g_strdup (dest_path);
-	if (dest_dir[strlen (dest_dir) - 1] == G_DIR_SEPARATOR)
-		dest_dir[strlen (dest_dir) - 1] = 0;
+	if ((destination == NULL) || (*destination == '\0')|| (strcmp (destination, "/") == 0))
+		return g_object_ref (base_dir);
 
-	debug (DEBUG_INFO, "base_dir: %s\n", base_dir);
-	debug (DEBUG_INFO, "dest_dir: %s\n", dest_dir);
+	debug (DEBUG_INFO, "base_dir: %s\n", g_file_get_path (base_dir));
+	debug (DEBUG_INFO, "dest_dir: %s\n", destination);
 
-	temp_dir = _g_path_get_temp_work_dir (NULL);
-	tmp = _g_path_remove_level (dest_dir);
-	parent_dir =  g_build_filename (temp_dir, tmp, NULL);
-	g_free (tmp);
+	temp_dir = _g_file_get_temp_work_dir (NULL);
+	destination_parent = _g_path_remove_level (destination);
+	parent_dir =  _g_file_append_path (temp_dir, destination_parent, NULL);
+
+	debug (DEBUG_INFO, "mkdir %s\n", g_file_get_path (parent_dir));
+	_g_file_make_directory_tree (parent_dir, 0700, NULL);
 
-	debug (DEBUG_INFO, "mkdir %s\n", parent_dir);
-	_g_path_make_directory_tree (parent_dir, 0700, NULL);
-	g_free (parent_dir);
+	dir = _g_file_append_path (temp_dir, destination, NULL);
 
-	dir = g_build_filename (temp_dir, "/", dest_dir, NULL);
-	debug (DEBUG_INFO, "symlink %s --> %s\n", dir, base_dir);
-	if (! symlink (base_dir, dir)) {
-		/* void */
+	path = g_file_get_path (base_dir);
+	debug (DEBUG_INFO, "symlink %s --> %s\n", g_file_get_path (dir), path);
+	if (! g_file_make_symbolic_link (dir, path, NULL, &error)) {
+		g_warning ("%s", error->message);
+		g_clear_error (&error);
 	}
 
-	g_free (dir);
-	g_free (dest_dir);
+	g_free (path);
+	g_object_unref (dir);
+	g_object_unref (parent_dir);
+	g_free (destination_parent);
 
 	return temp_dir;
 }
@@ -832,36 +835,31 @@ static void delete_from_archive (FrCommand *self,
 static GList *
 newer_files_only (FrArchive  *archive,
 		  GList      *file_list,
-		  const char *base_dir)
+		  GFile      *base_dir)
 {
 	GList *newer_files = NULL;
 	GList *scan;
 
 	for (scan = file_list; scan; scan = scan->next) {
 		char     *filename = scan->data;
-		char     *fullpath;
-		char     *uri;
+		GFile    *file;
 		FileData *fdata;
 
 		fdata = find_file_in_archive (archive, filename);
 
 		if (fdata == NULL) {
-			newer_files = g_list_prepend (newer_files, g_strdup (scan->data));
+			newer_files = g_list_prepend (newer_files, g_strdup (filename));
 			continue;
 		}
 
-		fullpath = g_strconcat (base_dir, "/", filename, NULL);
-		uri = g_filename_to_uri (fullpath, NULL, NULL);
-
-		if (fdata->modified >= _g_uri_get_file_mtime (uri)) {
-			g_free (fullpath);
-			g_free (uri);
+		file = _g_file_append_path (base_dir, filename, NULL);
+		if (fdata->modified >= _g_file_get_file_mtime (file)) {
+			g_object_unref (file);
 			continue;
 		}
-		g_free (fullpath);
-		g_free (uri);
+		g_object_unref (file);
 
-		newer_files = g_list_prepend (newer_files, g_strdup (scan->data));
+		newer_files = g_list_prepend (newer_files, g_strdup (filename));
 	}
 
 	return newer_files;
@@ -870,19 +868,17 @@ newer_files_only (FrArchive  *archive,
 
 static gboolean
 save_list_to_temp_file (GList   *file_list,
-		        char   **list_dir,
+		        char   **list_dirname,
 		        char   **list_filename,
 		        GError **error)
 {
 	gboolean           error_occurred = FALSE;
+	GFile             *list_dir;
 	GFile             *list_file;
 	GFileOutputStream *ostream;
 
-	if (error != NULL)
-		*error = NULL;
-	*list_dir = _g_path_get_temp_work_dir (NULL);
-	*list_filename = g_build_filename (*list_dir, "file-list", NULL);
-	list_file = g_file_new_for_path (*list_filename);
+	list_dir = _g_file_get_temp_work_dir (NULL);
+	list_file = g_file_get_child (list_dir, "file-list");
 	ostream = g_file_create (list_file, G_FILE_CREATE_PRIVATE, NULL, error);
 
 	if (ostream != NULL) {
@@ -911,13 +907,16 @@ save_list_to_temp_file (GList   *file_list,
 		error_occurred = TRUE;
 
 	if (error_occurred) {
-		_g_path_remove_directory (*list_dir);
-		g_free (*list_dir);
-		g_free (*list_filename);
-		*list_dir = NULL;
+		_g_file_remove_directory (list_dir, NULL, NULL);
+		*list_dirname = NULL;
 		*list_filename = NULL;
 	}
+	else {
+		*list_dirname = g_file_get_path (list_dir);
+		*list_filename = g_file_get_path (list_file);
+	}
 
+	g_object_unref (list_dir);
 	g_object_unref (list_file);
 
 	return ! error_occurred;
@@ -962,7 +961,7 @@ split_in_chunks (GList *file_list)
 static gboolean
 _fr_command_add (FrCommand      *self,
 		 GList          *file_list,
-		 const char     *base_dir,
+		 GFile          *base_dir,
 		 const char     *dest_dir,
 		 gboolean        update,
 		 gboolean        recursive,
@@ -977,7 +976,7 @@ _fr_command_add (FrCommand      *self,
 	GList     *new_file_list = NULL;
 	gboolean   base_dir_created = FALSE;
 	GList     *scan;
-	char      *tmp_base_dir = NULL;
+	GFile     *tmp_base_dir = NULL;
 	char      *tmp_archive_dir = NULL;
 	char      *archive_filename = NULL;
 	char      *tmp_archive_filename = NULL;
@@ -1015,7 +1014,7 @@ _fr_command_add (FrCommand      *self,
 		}
 	}
 	else {
-		tmp_base_dir = g_strdup (base_dir);
+		tmp_base_dir = g_object_ref (base_dir);
 		new_file_list = _g_string_list_dup (file_list);
 	}
 
@@ -1034,8 +1033,8 @@ _fr_command_add (FrCommand      *self,
 		debug (DEBUG_INFO, "nothing to update.\n");
 
 		if (base_dir_created)
-			_g_path_remove_directory (tmp_base_dir);
-		g_free (tmp_base_dir);
+			_g_file_remove_directory (tmp_base_dir, NULL, NULL);
+		g_object_unref (tmp_base_dir);
 
 		return FALSE;
 	}
@@ -1059,7 +1058,7 @@ _fr_command_add (FrCommand      *self,
 		tmp_archive_dir = _g_path_get_temp_work_dir (archive_dir);
 		archive_filename = g_file_get_path (self->priv->local_copy);
 		tmp_archive_filename = g_build_filename (tmp_archive_dir,
-							 _g_path_get_file_name (archive_filename),
+							 _g_path_get_basename (archive_filename),
 							 NULL);
 		tmp_file = g_file_new_for_path (tmp_archive_filename);
 		g_object_set (self, "filename", tmp_file, NULL);
@@ -1193,7 +1192,7 @@ _fr_command_add (FrCommand      *self,
 			fr_process_set_working_dir (self->process, g_get_tmp_dir ());
 			fr_process_set_sticky (self->process, TRUE);
 			fr_process_add_arg (self->process, "-rf");
-			fr_process_add_arg (self->process, tmp_base_dir);
+			fr_process_add_arg_file (self->process, tmp_base_dir);
 			fr_process_end_command (self->process);
 		}
 	}
@@ -1201,7 +1200,7 @@ _fr_command_add (FrCommand      *self,
 	g_free (tmp_archive_filename);
 	g_free (archive_filename);
 	g_free (tmp_archive_dir);
-	g_free (tmp_base_dir);
+	g_object_unref (tmp_base_dir);
 
 	return ! error_occurred;
 }
@@ -1251,10 +1250,30 @@ process_ready_after_changing_archive (GObject      *source_object,
 }
 
 
+static GList *
+get_relative_path_list (GList *file_list,
+		        GFile *base_dir)
+{
+	GList    *relative_file_list;
+	GList    *scan;
+
+	relative_file_list = NULL;
+	for (scan = file_list; scan; scan = scan->next) {
+		char *relative_path;
+
+		relative_path = g_file_get_relative_path (base_dir, G_FILE (scan->data));
+		if (relative_path != NULL)
+			relative_file_list = g_list_prepend (relative_file_list, relative_path);
+	}
+
+	return g_list_reverse (relative_file_list);
+}
+
+
 static void
 _fr_command_add_local_files (FrCommand           *self,
 			     GList               *file_list,
-			     const char          *base_dir,
+			     GFile               *base_dir,
 			     const char          *dest_dir,
 			     gboolean             update,
 			     gboolean             recursive,
@@ -1265,13 +1284,16 @@ _fr_command_add_local_files (FrCommand           *self,
 			     GCancellable        *cancellable,
 			     GSimpleAsyncResult  *command_result)
 {
+	GList    *relative_file_list;
 	XferData *xfer_data;
 	GError   *error = NULL;
 
+	relative_file_list = get_relative_path_list (file_list, base_dir);
+
 	g_object_set (self, "filename", self->priv->local_copy, NULL);
 	fr_process_clear (self->process);
 	if (! _fr_command_add (self,
-			       file_list,
+			       relative_file_list,
 			       base_dir,
 			       dest_dir,
 			       update,
@@ -1283,6 +1305,7 @@ _fr_command_add_local_files (FrCommand           *self,
 			       cancellable,
 			       &error))
 	{
+		_g_string_list_free (relative_file_list);
 		if (error != NULL) {
 			g_simple_async_result_set_from_error (command_result, error);
 			g_error_free (error);
@@ -1291,6 +1314,8 @@ _fr_command_add_local_files (FrCommand           *self,
 		return;
 	}
 
+	_g_string_list_free (relative_file_list);
+
 	xfer_data = g_new0 (XferData, 1);
 	xfer_data->archive = _g_object_ref (self);
 	xfer_data->cancellable = _g_object_ref (cancellable);
@@ -1350,7 +1375,7 @@ copy_remote_files_progress (goffset   current_file,
 static void
 copy_remote_files (FrCommand           *self,
 		   GList               *file_list,
-		   const char          *base_uri,
+		   GFile               *base_dir,
 		   const char          *dest_dir,
 		   gboolean             update,
 		   gboolean             recursive,
@@ -1358,7 +1383,7 @@ copy_remote_files (FrCommand           *self,
 		   gboolean             encrypt_header,
 		   FrCompression        compression,
 		   guint                volume_size,
-		   const char          *tmp_dir,
+		   GFile               *tmp_dir,
 		   GCancellable        *cancellable,
 		   GSimpleAsyncResult  *result)
 {
@@ -1370,25 +1395,28 @@ copy_remote_files (FrCommand           *self,
 
 	sources = NULL;
 	destinations = NULL;
-	created_folders = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
+	created_folders = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, (GDestroyNotify) g_object_unref, NULL);
 	for (scan = file_list; scan; scan = scan->next) {
-		char *partial_filename = scan->data;
-		char *local_uri;
-		char *local_folder_uri;
-		char *remote_uri;
-
-		local_uri = g_strconcat ("file://", tmp_dir, "/", partial_filename, NULL);
-		local_folder_uri = _g_path_remove_level (local_uri);
-		if (g_hash_table_lookup (created_folders, local_folder_uri) == NULL) {
+		GFile *file = scan->data;
+		char  *relative_path;
+		GFile *local_file;
+		GFile *local_folder;
+
+		relative_path = g_file_get_relative_path (base_dir, file);
+		local_file = _g_file_append_path (tmp_dir, relative_path, NULL);
+		local_folder = g_file_get_parent (local_file);
+		if (g_hash_table_lookup (created_folders, local_folder) == NULL) {
 			GError *error = NULL;
-			if (! _g_uri_ensure_dir_exists (local_folder_uri, 0755, &error)) {
+
+			if (! _g_file_make_directory_tree (local_folder, 0755, &error)) {
 				g_simple_async_result_set_from_error (result, error);
 				g_simple_async_result_complete_in_idle (result);
 
-				g_clear_error (&error);
 				g_object_unref (result);
-				g_free (local_folder_uri);
-				g_free (local_uri);
+				g_clear_error (&error);
+				g_object_unref (local_folder);
+				g_object_unref (local_file);
+				g_free (relative_path);
 				_g_file_list_free (sources);
 				_g_file_list_free (destinations);
 				g_hash_table_destroy (created_folders);
@@ -1396,24 +1424,22 @@ copy_remote_files (FrCommand           *self,
 				return;
 			}
 
-			g_hash_table_insert (created_folders, local_folder_uri, GINT_TO_POINTER (1));
+			g_hash_table_insert (created_folders, g_object_ref (local_folder), GINT_TO_POINTER (1));
 		}
-		else
-			g_free (local_folder_uri);
 
-		remote_uri = g_strconcat (base_uri, "/", partial_filename, NULL);
-		sources = g_list_append (sources, g_file_new_for_uri (remote_uri));
-		g_free (remote_uri);
+		sources = g_list_append (sources, g_object_ref (file));
+		destinations = g_list_append (destinations, g_object_ref (local_file));
 
-		destinations = g_list_append (destinations, g_file_new_for_uri (local_uri));
-		g_free (local_uri);
+		g_object_unref (local_folder);
+		g_object_unref (local_file);
+		g_free (relative_path);
 	}
 	g_hash_table_destroy (created_folders);
 
 	xfer_data = g_new0 (XferData, 1);
 	xfer_data->archive = g_object_ref (self);
-	xfer_data->file_list = _g_string_list_dup (file_list);
-	xfer_data->base_uri = g_strdup (base_uri);
+	xfer_data->file_list = _g_object_list_ref (file_list);
+	xfer_data->base_dir = g_object_ref (base_dir);
 	xfer_data->dest_dir = g_strdup (dest_dir);
 	xfer_data->update = update;
 	xfer_data->recursive = recursive;
@@ -1422,7 +1448,7 @@ copy_remote_files (FrCommand           *self,
 	xfer_data->encrypt_header = encrypt_header;
 	xfer_data->compression = compression;
 	xfer_data->volume_size = volume_size;
-	xfer_data->tmp_dir = g_strdup (tmp_dir);
+	xfer_data->tmp_dir = g_object_ref (tmp_dir);
 	xfer_data->cancellable = _g_object_ref (cancellable);
 	xfer_data->result = result;
 
@@ -1446,7 +1472,7 @@ copy_remote_files (FrCommand           *self,
 static void
 fr_command_add_files (FrArchive           *base,
 		      GList               *file_list,
-		      const char          *base_dir,
+		      GFile               *base_dir,
 		      const char          *dest_dir,
 		      gboolean             update,
 		      gboolean             recursive,
@@ -1466,13 +1492,10 @@ fr_command_add_files (FrArchive           *base,
 					    user_data,
 					    fr_archive_add_files);
 
-	if (_g_uri_is_local (base_dir)) {
-		char *local_dir;
-
-		local_dir = g_filename_from_uri (base_dir, NULL, NULL);
+	if (_g_file_is_local (base_dir))
 		_fr_command_add_local_files (self,
 					     file_list,
-					     local_dir,
+					     base_dir,
 					     dest_dir,
 					     update,
 					     recursive,
@@ -1482,9 +1505,6 @@ fr_command_add_files (FrArchive           *base,
 					     volume_size,
 					     cancellable,
 					     result);
-
-		g_free (local_dir);
-	}
 	else
 		copy_remote_files (self,
 				   file_list,
@@ -1666,7 +1686,7 @@ _fr_command_remove (FrCommand     *self,
 		archive_dir = g_file_get_path (local_copy_parent);
 		tmp_archive_dir = _g_path_get_temp_work_dir (archive_dir);
 		archive_filename = g_file_get_path (self->priv->local_copy);
-		tmp_archive_filename = g_build_filename (tmp_archive_dir, _g_path_get_file_name (archive_filename), NULL);
+		tmp_archive_filename = g_build_filename (tmp_archive_dir, _g_path_get_basename (archive_filename), NULL);
 		tmp_file = g_file_new_for_path (tmp_archive_filename);
 		g_object_set (self, "filename", tmp_file, NULL);
 
@@ -1825,16 +1845,20 @@ move_files_to_dir (FrCommand *self,
 
 
 static void
-move_files_in_chunks (FrCommand *self,
-		      GList            *file_list,
-		      const char       *temp_dir,
-		      const char       *dest_dir,
-		      gboolean          overwrite)
+move_files_in_chunks (FrCommand  *self,
+		      GList      *file_list,
+		      GFile      *temp_dir,
+		      GFile      *destination,
+		      gboolean    overwrite)
 {
 	GList *scan;
+	char  *temp_dir_path;
 	int    temp_dir_l;
+	char  *dest_dir;
 
-	temp_dir_l = strlen (temp_dir);
+	temp_dir_path = g_file_get_path (temp_dir);
+	temp_dir_l = strlen (temp_dir_path);
+	dest_dir = g_file_get_path (destination);
 
 	for (scan = file_list; scan != NULL; ) {
 		GList *prev = scan->prev;
@@ -1853,16 +1877,19 @@ move_files_in_chunks (FrCommand *self,
 		}
 
 		prev->next = NULL;
-		move_files_to_dir (self, chunk_list, temp_dir, dest_dir, overwrite);
+		move_files_to_dir (self, chunk_list, temp_dir_path, dest_dir, overwrite);
 		prev->next = scan;
 	}
+
+	g_free (dest_dir);
+	g_free (temp_dir_path);
 }
 
 
 static void
 extract_from_archive (FrCommand  *self,
 		      GList      *file_list,
-		      const char *dest_dir,
+		      GFile      *destination,
 		      gboolean    overwrite,
 		      gboolean    skip_older,
 		      gboolean    junk_paths,
@@ -1876,7 +1903,7 @@ extract_from_archive (FrCommand  *self,
 		fr_command_extract (self,
 				    NULL,
 				    file_list,
-				    dest_dir,
+				    destination,
 				    overwrite,
 				    skip_older,
 				    junk_paths);
@@ -1893,7 +1920,7 @@ extract_from_archive (FrCommand  *self,
 			fr_command_extract (self,
 					    list_filename,
 					    file_list,
-					    dest_dir,
+					    destination,
 					    overwrite,
 					    skip_older,
 					    junk_paths);
@@ -1901,7 +1928,7 @@ extract_from_archive (FrCommand  *self,
 			/* remove the temp dir */
 
 			fr_process_begin_command (self->process, "rm");
-			fr_process_set_working_dir (self->process, g_get_tmp_dir());
+			fr_process_set_working_dir (self->process, g_get_tmp_dir ());
 			fr_process_set_sticky (self->process, TRUE);
 			fr_process_add_arg (self->process, "-rf");
 			fr_process_add_arg (self->process, list_dir);
@@ -1932,7 +1959,7 @@ extract_from_archive (FrCommand  *self,
 			fr_command_extract (self,
 					    NULL,
 					    chunk_list,
-					    dest_dir,
+					    destination,
 					    overwrite,
 					    skip_older,
 					    junk_paths);
@@ -1956,7 +1983,7 @@ compute_base_path (const char *base_dir,
 
 	if (junk_paths) {
 		if (can_junk_paths)
-			new_path = g_strdup (_g_path_get_file_name (path));
+			new_path = g_strdup (_g_path_get_basename (path));
 		else
 			new_path = g_strdup (path);
 
@@ -2083,7 +2110,7 @@ remove_files_contained_in_this_dir (GList *file_list,
 static void
 _fr_command_extract (FrCommand  *self,
 		     GList      *file_list,
-		     const char *destination,
+		     GFile      *destination,
 		     const char *base_dir,
 		     gboolean    skip_older,
 		     gboolean    overwrite,
@@ -2186,8 +2213,8 @@ _fr_command_extract (FrCommand  *self,
 	for (scan = file_list; scan; scan = scan->next) {
 		FileData   *fdata;
 		char       *archive_list_filename = scan->data;
-		char        dest_filename[4096];
 		const char *filename;
+		GFile      *destination_file;
 
 		fdata = find_file_in_archive (archive, archive_list_filename);
 
@@ -2204,30 +2231,32 @@ _fr_command_extract (FrCommand  *self,
 		if (! junk_paths)
 			filename = archive_list_filename;
 		else
-			filename = _g_path_get_file_name (archive_list_filename);
+			filename = _g_path_get_basename (archive_list_filename);
 
-		if ((destination[strlen (destination) - 1] == '/')
-		    || (filename[0] == '/'))
-			sprintf (dest_filename, "%s%s", destination, filename);
-		else
-			sprintf (dest_filename, "%s/%s", destination, filename);
+		destination_file = _g_file_append_path (destination, filename, NULL);
 
-		/*debug (DEBUG_INFO, "-> %s\n", dest_filename);*/
+		/*debug (DEBUG_INFO, "-> %s\n", g_file_get_uri (destination_file));*/
 
 		/**/
 
 		if (! archive->propExtractCanSkipOlder
 		    && skip_older
-		    && g_file_test (dest_filename, G_FILE_TEST_EXISTS)
-		    && (fdata->modified < _g_path_get_file_mtime (dest_filename)))
+		    && g_file_query_exists (destination_file, NULL)
+		    && (fdata->modified < _g_file_get_file_mtime (destination_file)))
+		{
 			continue;
+		}
 
 		if (! archive->propExtractCanAvoidOverwrite
 		    && ! overwrite
-		    && g_file_test (dest_filename, G_FILE_TEST_EXISTS))
+		    && g_file_query_exists (destination_file, NULL))
+		{
 			continue;
+		}
 
 		filtered = g_list_prepend (filtered, fdata->original_path);
+
+		g_object_unref (destination_file);
 	}
 
 	if (filtered == NULL) {
@@ -2240,9 +2269,9 @@ _fr_command_extract (FrCommand  *self,
 	}
 
 	if (move_to_dest_dir) {
-		char *temp_dir;
+		GFile *temp_dir;
 
-		temp_dir = _g_path_get_temp_work_dir (destination);
+		temp_dir = _g_file_get_temp_work_dir (destination);
 		extract_from_archive (self,
 				      filtered,
 				      temp_dir,
@@ -2267,10 +2296,10 @@ _fr_command_extract (FrCommand  *self,
 
 		fr_process_begin_command (self->process, "rm");
 		fr_process_add_arg (self->process, "-rf");
-		fr_process_add_arg (self->process, temp_dir);
+		fr_process_add_arg_file (self->process, temp_dir);
 		fr_process_end_command (self->process);
 
-		g_free (temp_dir);
+		g_object_unref (temp_dir);
 	}
 	else
 		extract_from_archive (self,
@@ -2320,13 +2349,12 @@ process_ready_for_extract_to_local_cb (GObject      *source_object,
 		g_print ("action_performed: ERROR!\n");
 
 		if ((self->priv->remote_extraction) && (self->priv->temp_extraction_dir != NULL)) {
-			_g_path_remove_directory (self->priv->temp_extraction_dir);
-			g_free (self->priv->temp_extraction_dir);
-			self->priv->temp_extraction_dir = NULL;
+			_g_file_remove_directory (self->priv->temp_extraction_dir, NULL, NULL);
+			_g_clear_object (&self->priv->temp_extraction_dir);
 		}
 
 		if (xfer_data->archive->extract_here)
-			_g_uri_remove_directory (fr_archive_get_last_extraction_destination (xfer_data->archive));
+			_g_file_remove_directory (fr_archive_get_last_extraction_destination (xfer_data->archive), NULL, NULL);
 	}
 
 	xfer_data->archive->extract_here = FALSE;
@@ -2340,7 +2368,7 @@ process_ready_for_extract_to_local_cb (GObject      *source_object,
 static void
 _fr_command_extract_to_local (FrCommand           *self,
 			      GList               *file_list,
-			      const char          *destination,
+			      GFile               *destination,
 			      const char          *base_dir,
 			      gboolean             skip_older,
 			      gboolean             overwrite,
@@ -2379,7 +2407,7 @@ _fr_command_extract_to_local (FrCommand           *self,
 static void
 fr_command_extract_files (FrArchive           *base,
 			  GList               *file_list,
-			  const char          *destination,
+			  GFile               *destination,
 			  const char          *base_dir,
 			  gboolean             skip_older,
 			  gboolean             overwrite,
@@ -2391,12 +2419,11 @@ fr_command_extract_files (FrArchive           *base,
 {
 	FrCommand *self = FR_COMMAND (base);
 
-	g_free (self->priv->temp_extraction_dir);
-	self->priv->temp_extraction_dir = NULL;
+	_g_clear_object (&self->priv->temp_extraction_dir);
 
-	self->priv->remote_extraction = ! _g_uri_is_local (destination);
+	self->priv->remote_extraction = ! _g_file_is_local (destination);
 	if (self->priv->remote_extraction) {
-		self->priv->temp_extraction_dir = _g_path_get_temp_work_dir (NULL);
+		self->priv->temp_extraction_dir = _g_file_get_temp_work_dir (NULL);
 		_fr_command_extract_to_local (self,
 					     file_list,
 					     self->priv->temp_extraction_dir,
@@ -2409,13 +2436,10 @@ fr_command_extract_files (FrArchive           *base,
 					     callback,
 					     user_data);
 	}
-	else {
-		char *local_destination;
-
-		local_destination = g_filename_from_uri (destination, NULL, NULL);
+	else
 		_fr_command_extract_to_local (self,
 					     file_list,
-					     local_destination,
+					     destination,
 					     base_dir,
 					     skip_older,
 					     overwrite,
@@ -2424,8 +2448,6 @@ fr_command_extract_files (FrArchive           *base,
 					     cancellable,
 					     callback,
 					     user_data);
-		g_free (local_destination);
-	}
 }
 
 
@@ -2502,7 +2524,7 @@ fr_command_rename (FrArchive           *archive,
 		   gpointer             user_data)
 {
 	FrCommand *self = FR_COMMAND (archive);
-	char      *tmp_dir;
+	GFile     *tmp_dir;
 	gboolean   added_dir;
 	char      *new_dirname;
 	GList     *new_file_list;
@@ -2515,7 +2537,7 @@ fr_command_rename (FrArchive           *archive,
 		      "filename", self->priv->local_copy,
 		      NULL);
 
-	tmp_dir = _g_path_get_temp_work_dir (NULL);
+	tmp_dir = _g_file_get_temp_work_dir (NULL);
 
 	fr_process_clear (self->process);
 	_fr_command_extract (self,
@@ -2553,48 +2575,50 @@ fr_command_rename (FrArchive           *archive,
 	new_dirname = g_build_filename (current_dir + 1, new_name, "/", NULL);
 	new_file_list = NULL;
 	if (is_dir) {
-		char *old_path;
-		char *new_path;
+		GFile *old_file;
+		GFile *new_file;
 
-		old_path = g_build_filename (tmp_dir, current_dir, old_name, NULL);
-		new_path = g_build_filename (tmp_dir, current_dir, new_name, NULL);
+		old_file = _g_file_append_path (tmp_dir, current_dir, old_name, NULL);
+		new_file = _g_file_append_path (tmp_dir, current_dir, new_name, NULL);
 
 		fr_process_begin_command (self->process, "mv");
 		fr_process_add_arg (self->process, "-f");
-		fr_process_add_arg (self->process, old_path);
-		fr_process_add_arg (self->process, new_path);
+		fr_process_add_arg_file (self->process, old_file);
+		fr_process_add_arg_file (self->process, new_file);
 		fr_process_end_command (self->process);
 
-		g_free (old_path);
-		g_free (new_path);
+		g_object_unref (old_file);
+		g_object_unref (new_file);
 	}
 
 	for (scan = file_list; scan; scan = scan->next) {
 		const char *current_dir_relative = current_dir + 1;
 		const char *filename = (char*) scan->data;
-		char       *old_path = NULL, *common = NULL, *new_path = NULL;
+		GFile      *old_file = NULL;
+		GFile      *new_file = NULL;
+		char       *common = NULL;
 		char       *new_filename;
 
-		old_path = g_build_filename (tmp_dir, filename, NULL);
+		old_file = _g_file_append_path (tmp_dir, filename, NULL);
 
 		if (strlen (filename) > (strlen (current_dir) + strlen (old_name)))
 			common = g_strdup (filename + strlen (current_dir) + strlen (old_name));
-		new_path = g_build_filename (tmp_dir, current_dir, new_name, common, NULL);
+		new_file = _g_file_append_path (tmp_dir, current_dir, new_name, common, NULL);
 
 		if (! is_dir) {
 			fr_process_begin_command (self->process, "mv");
 			fr_process_add_arg (self->process, "-f");
-			fr_process_add_arg (self->process, old_path);
-			fr_process_add_arg (self->process, new_path);
+			fr_process_add_arg_file (self->process, old_file);
+			fr_process_add_arg_file (self->process, new_file);
 			fr_process_end_command (self->process);
 		}
 
 		new_filename = g_build_filename (current_dir_relative, new_name, common, NULL);
 		new_file_list = g_list_prepend (new_file_list, new_filename);
 
-		g_free (old_path);
 		g_free (common);
-		g_free (new_path);
+		g_object_unref (new_file);
+		g_object_unref (old_file);
 	}
 	new_file_list = g_list_reverse (new_file_list);
 
@@ -2625,11 +2649,11 @@ fr_command_rename (FrArchive           *archive,
 		g_simple_async_result_set_from_error (result, error);
 		g_simple_async_result_complete_in_idle (result);
 
-		g_unlink (tmp_dir);
+		g_file_delete (tmp_dir, NULL, NULL);
 
 		g_object_unref (result);
 		g_error_free (error);
-		g_free (tmp_dir);
+		g_object_unref (tmp_dir);
 
 		return;
 	}
@@ -2643,7 +2667,7 @@ fr_command_rename (FrArchive           *archive,
 	fr_process_set_working_dir (self->process, g_get_tmp_dir ());
 	fr_process_set_sticky (self->process, TRUE);
 	fr_process_add_arg (self->process, "-rf");
-	fr_process_add_arg (self->process, tmp_dir);
+	fr_process_add_arg_file (self->process, tmp_dir);
 	fr_process_end_command (self->process);
 
 	xfer_data = g_new0 (XferData, 1);
@@ -2659,7 +2683,7 @@ fr_command_rename (FrArchive           *archive,
 			    process_ready_after_changing_archive,
 			    xfer_data);
 
-	g_free (tmp_dir);
+	g_object_unref (tmp_dir);
 }
 
 
@@ -2668,7 +2692,7 @@ fr_command_rename (FrArchive           *archive,
 
 static void
 fr_command_paste_clipboard (FrArchive           *archive,
-		    	    char                *archive_uri,
+		    	    GFile               *archive_file,
 		    	    char                *password,
 		    	    gboolean             encrypt_header,
 		    	    FrCompression        compression,
@@ -2676,7 +2700,7 @@ fr_command_paste_clipboard (FrArchive           *archive,
 		    	    FrClipboardOp        op,
 		    	    char                *base_dir,
 		    	    GList               *files,
-		    	    char                *tmp_dir,
+		    	    GFile               *tmp_dir,
 		    	    char                *current_dir,
 		    	    GCancellable        *cancellable,
 		    	    GAsyncReadyCallback  callback,
@@ -2701,7 +2725,7 @@ fr_command_paste_clipboard (FrArchive           *archive,
 		    && (old_name[strlen (old_name) - 1] != '/'))
 		{
 			fr_process_begin_command (command->process, "mv");
-			fr_process_set_working_dir (command->process, tmp_dir);
+			fr_process_set_working_dir_file (command->process, tmp_dir);
 			fr_process_add_arg (command->process, "-f");
 			if (old_name[0] == '/')
 				old_name = old_name + 1;
@@ -2752,7 +2776,7 @@ fr_command_paste_clipboard (FrArchive           *archive,
 	fr_process_set_working_dir (command->process, g_get_tmp_dir ());
 	fr_process_set_sticky (command->process, TRUE);
 	fr_process_add_arg (command->process, "-rf");
-	fr_process_add_arg (command->process, tmp_dir);
+	fr_process_add_arg_file (command->process, tmp_dir);
 	fr_process_end_command (command->process);
 
 	/**/
@@ -2778,7 +2802,6 @@ fr_command_paste_clipboard (FrArchive           *archive,
 static void
 fr_command_add_dropped_files (FrArchive           *archive,
 		   	      GList               *file_list,
-		   	      const char          *base_dir,
 		   	      const char          *dest_dir,
 		   	      const char          *password,
 		   	      gboolean             encrypt_header,
@@ -2792,6 +2815,8 @@ fr_command_add_dropped_files (FrArchive           *archive,
 	GList     *scan;
 	XferData  *xfer_data;
 
+	/* FIXME: doesn't work with remote files */
+
 	fr_archive_set_stoppable (FR_ARCHIVE (command), TRUE);
 	command->creating_archive = ! g_file_query_exists (command->priv->local_copy, cancellable);
 	g_object_set (command,
@@ -2805,20 +2830,21 @@ fr_command_add_dropped_files (FrArchive           *archive,
 	fr_process_clear (command->process);
 	fr_command_uncompress (command);
 	for (scan = file_list; scan; scan = scan->next) {
-		char  *fullpath = scan->data;
-		char  *basedir;
+		GFile *file = G_FILE (scan->data);
+		GFile *parent;
 		GList *singleton;
 
-		basedir = _g_path_remove_level (fullpath);
-		singleton = g_list_prepend (NULL, (char*)_g_path_get_file_name (fullpath));
+		parent = g_file_get_parent (file);
+		singleton = g_list_prepend (NULL, g_file_get_basename (file));
 		fr_command_add (command,
 				NULL,
 				singleton,
-				basedir,
+				parent,
 				FALSE,
 				FALSE);
-		g_list_free (singleton);
-		g_free (basedir);
+
+		_g_string_list_free (singleton);
+		g_object_ref (parent);
 	}
 	fr_command_recompress (command);
 
@@ -2864,14 +2890,14 @@ fr_command_update_open_files (FrArchive           *archive,
 	     scan_file && scan_dir;
 	     scan_file = scan_file->next, scan_dir = scan_dir->next)
 	{
-		char  *filepath = scan_file->data;
-		char  *dirpath = scan_dir->data;
-		GList *local_file_list;
+		GFile *file = G_FILE (scan_file->data);
+		GFile *folder = G_FILE (scan_dir->data);
+		GList *singleton;
 
-		local_file_list = g_list_append (NULL, filepath);
+		singleton = g_list_append (NULL, g_file_get_relative_path (folder, file));
 		_fr_command_add (self,
-				 local_file_list,
-				 dirpath,
+				 singleton,
+			 	 folder,
 				 "/",
 				 FALSE,
 				 FALSE,
@@ -2882,7 +2908,7 @@ fr_command_update_open_files (FrArchive           *archive,
 				 cancellable,
 				 NULL);
 
-		g_list_free (local_file_list);
+		_g_string_list_free (singleton);
 	}
 
 	/**/
diff --git a/src/fr-init.c b/src/fr-init.c
index 1f2024c..7d7b1f4 100644
--- a/src/fr-init.c
+++ b/src/fr-init.c
@@ -638,27 +638,13 @@ command_done (CommandData *cdata)
 	if (cdata == NULL)
 		return;
 
-	if ((cdata->temp_dir != NULL) && _g_path_query_is_dir (cdata->temp_dir)) {
-		char *argv[4];
-
-		argv[0] = "rm";
-		argv[1] = "-rf";
-		argv[2] = cdata->temp_dir;
-		argv[3] = NULL;
-		g_spawn_sync (g_get_tmp_dir (), argv, NULL,
-			      G_SPAWN_SEARCH_PATH,
-			      NULL, NULL,
-			      NULL, NULL, NULL,
-			      NULL);
-	}
+	_g_file_remove_directory (cdata->temp_dir, NULL, NULL);
 
 	g_free (cdata->command);
-	if (cdata->app != NULL)
-		g_object_unref (cdata->app);
-	_g_string_list_free (cdata->file_list);
-	g_free (cdata->temp_dir);
-	if (cdata->process != NULL)
-		g_object_unref (cdata->process);
+	_g_object_unref (cdata->app);
+	_g_object_list_unref (cdata->file_list);
+	_g_object_unref (cdata->temp_dir);
+	_g_object_unref (cdata->process);
 
 	CommandList = g_list_remove (CommandList, cdata);
 	g_free (cdata);
diff --git a/src/fr-init.h b/src/fr-init.h
index e987dd0..0287d92 100644
--- a/src/fr-init.h
+++ b/src/fr-init.h
@@ -40,7 +40,7 @@ typedef struct {
 	char      *command;
 	GAppInfo  *app;
 	GList     *file_list;
-	char      *temp_dir;
+	GFile     *temp_dir;
 } CommandData;
 
 extern GList                 *CommandList;
diff --git a/src/fr-new-archive-dialog.c b/src/fr-new-archive-dialog.c
index e04008e..8ab3bd6 100644
--- a/src/fr-new-archive-dialog.c
+++ b/src/fr-new-archive-dialog.c
@@ -210,7 +210,7 @@ filter_notify_cb (GObject    *gobject,
 		char       *new_basename_uft8;
 
 		new_ext = mime_type_desc[self->priv->supported_types[n_format]].default_ext;
-		basename = _g_path_get_file_name (uri);
+		basename = _g_path_get_basename (uri);
 		if (g_str_has_suffix (basename, ext))
 			basename_noext = g_strndup (basename, strlen (basename) - strlen (ext));
 		else
@@ -422,11 +422,11 @@ _fr_new_archive_dialog_get_archive_type (FrNewArchiveDialog *self)
 }
 
 
-char *
-fr_new_archive_dialog_get_uri (FrNewArchiveDialog  *self,
-			       const char         **mime_type)
+GFile *
+fr_new_archive_dialog_get_file (FrNewArchiveDialog  *self,
+			        const char         **mime_type)
 {
-	char       *uri = NULL;
+	char       *uri;
 	int         n_format;
 	const char *file_mime_type;
 	GFile      *file, *dir;
@@ -527,7 +527,7 @@ fr_new_archive_dialog_get_uri (FrNewArchiveDialog  *self,
 		char     *secondary_message;
 		gboolean  overwrite;
 
-		filename = _g_uri_display_basename (uri);
+		filename = _g_file_get_display_basename (file);
 		message = g_strdup_printf (_("A file named \"%s\" already exists.  Do you want to replace it?"), filename);
 		secondary_message = g_strdup_printf (_("The file already exists in \"%s\".  Replacing it will overwrite its contents."), g_file_info_get_display_name (dir_info));
 		dialog = _gtk_message_dialog_new (GTK_WINDOW (self),
@@ -570,10 +570,10 @@ fr_new_archive_dialog_get_uri (FrNewArchiveDialog  *self,
 		}
 	}
 
-	g_object_unref (file);
 	g_object_unref (dir_info);
+	g_free (uri);
 
-	return uri;
+	return file;
 }
 
 
diff --git a/src/fr-new-archive-dialog.h b/src/fr-new-archive-dialog.h
index d19b35d..940a9a0 100644
--- a/src/fr-new-archive-dialog.h
+++ b/src/fr-new-archive-dialog.h
@@ -53,7 +53,7 @@ GType           fr_new_archive_dialog_get_type            (void);
 GtkWidget *     fr_new_archive_dialog_new                 (GtkWindow           *parent,
 							   FrNewArchiveAction   action,
 							   const char          *default_name);
-char *          fr_new_archive_dialog_get_uri             (FrNewArchiveDialog  *dialog,
+GFile *         fr_new_archive_dialog_get_file            (FrNewArchiveDialog  *dialog,
 							   const char         **mime_type);
 const char *    fr_new_archive_dialog_get_password        (FrNewArchiveDialog  *dialog);
 gboolean        fr_new_archive_dialog_get_encrypt_header  (FrNewArchiveDialog  *dialog);
diff --git a/src/fr-process.c b/src/fr-process.c
index 95210e2..f66e533 100644
--- a/src/fr-process.c
+++ b/src/fr-process.c
@@ -422,6 +422,18 @@ fr_process_set_working_dir (FrProcess  *process,
 
 
 void
+fr_process_set_working_dir_file (FrProcess *process,
+				 GFile     *folder)
+{
+	char *path;
+
+	path = g_file_get_path (folder);
+	fr_process_set_working_dir (process, path);
+
+	g_free (path);
+}
+
+void
 fr_process_set_sticky (FrProcess *process,
 		       gboolean   sticky)
 {
@@ -503,6 +515,19 @@ fr_process_add_arg_printf (FrProcess    *fr_proc,
 
 
 void
+fr_process_add_arg_file (FrProcess *process,
+			 GFile     *file)
+{
+	char *path;
+
+	path = g_file_get_path (file);
+	fr_process_add_arg (process, path);
+
+	g_free (path);
+}
+
+
+void
 fr_process_set_arg_at (FrProcess  *process,
 		       int         n_comm,
 		       int         n_arg,
diff --git a/src/fr-process.h b/src/fr-process.h
index 309f86b..8d403cc 100644
--- a/src/fr-process.h
+++ b/src/fr-process.h
@@ -23,7 +23,7 @@
 #define FR_PROCESS_H
 
 #include <glib.h>
-#include <gtk/gtk.h>
+#include <gio/gio.h>
 #include <sys/types.h>
 #include "fr-error.h"
 #include "typedefs.h"
@@ -86,6 +86,8 @@ void        fr_process_add_arg_concat       (FrProcess            *fr_proc,
 void        fr_process_add_arg_printf       (FrProcess            *fr_proc,
 					     const char           *format,
 					     ...) G_GNUC_PRINTF (2, 3);
+void        fr_process_add_arg_file         (FrProcess            *process,
+					     GFile                *file);
 void        fr_process_set_arg_at           (FrProcess            *fr_proc,
 					     int                   n_comm,
 					     int                   n_arg,
@@ -102,6 +104,8 @@ void        fr_process_set_continue_func    (FrProcess            *fr_proc,
 void        fr_process_end_command          (FrProcess            *fr_proc);
 void        fr_process_set_working_dir      (FrProcess            *fr_proc,
 					     const char           *arg);
+void        fr_process_set_working_dir_file (FrProcess            *fr_proc,
+					     GFile                *folder);
 void        fr_process_set_sticky           (FrProcess            *fr_proc,
 					     gboolean              sticky);
 void        fr_process_set_ignore_error     (FrProcess            *fr_proc,
diff --git a/src/fr-window.c b/src/fr-window.c
index f84ad93..6bee0c7 100644
--- a/src/fr-window.c
+++ b/src/fr-window.c
@@ -67,7 +67,7 @@
 #define PROGRESS_DIALOG_DEFAULT_WIDTH 500
 #define PROGRESS_TIMEOUT_MSECS 1000
 #define PROGRESS_BAR_HEIGHT 10
-#undef  LOG_PROGRESS
+#define LOG_PROGRESS 1
 
 #define HIDE_PROGRESS_TIMEOUT_MSECS 500
 #define DEFAULT_NAME_COLUMN_WIDTH 250
@@ -123,18 +123,18 @@ typedef struct {
 
 typedef struct {
 	guint      converting : 1;
-	char      *temp_dir;
+	GFile     *temp_dir;
 	FrArchive *new_archive;
 	char      *password;
 	gboolean   encrypt_header;
 	guint      volume_size;
-	char      *new_file;
+	GFile     *new_file;
 } FrConvertData;
 
 
 typedef struct {
 	GList       *file_list;
-	char        *extract_to_dir;
+	GFile       *destination;
 	char        *base_dir;
 	gboolean     skip_older;
 	FrOverwrite  overwrite;
@@ -168,12 +168,12 @@ typedef enum {
 
 typedef struct {
 	int            refs;
-	char          *archive_uri;
-	char          *archive_password;
+	GFile         *file;
+	char          *password;
 	FrClipboardOp  op;
 	char          *base_dir;
 	GList         *files;
-	char          *tmp_dir;
+	GFile         *tmp_dir;
 	char          *current_dir;
 } FrClipboardData;
 
@@ -206,10 +206,10 @@ fr_clipboard_data_unref (FrClipboardData *clipboard_data)
 	if (--clipboard_data->refs > 0)
 		return;
 
-	g_free (clipboard_data->archive_uri);
-	g_free (clipboard_data->archive_password);
+	_g_object_unref (clipboard_data->file);
+	g_free (clipboard_data->password);
 	g_free (clipboard_data->base_dir);
-	g_free (clipboard_data->tmp_dir);
+	_g_object_unref (clipboard_data->tmp_dir);
 	g_free (clipboard_data->current_dir);
 	g_list_foreach (clipboard_data->files, (GFunc) g_free, NULL);
 	g_list_free (clipboard_data->files);
@@ -221,10 +221,10 @@ static void
 fr_clipboard_data_set_password (FrClipboardData *clipboard_data,
 				const char      *password)
 {
-	if (clipboard_data->archive_password != password)
-		g_free (clipboard_data->archive_password);
+	if (clipboard_data->password != password)
+		g_free (clipboard_data->password);
 	if (password != NULL)
-		clipboard_data->archive_password = g_strdup (password);
+		clipboard_data->password = g_strdup (password);
 }
 
 
@@ -285,12 +285,12 @@ struct _FrWindowPrivate {
 					      * archive.*/
 	gboolean         reload_archive;
 
-	char *           archive_uri;
-	char *           open_default_dir;    /* default directory to be used
+	GFile *          archive_file;
+	GFile *          open_default_dir;    /* default directory to be used
 					       * in the Open dialog. */
-	char *           add_default_dir;     /* default directory to be used
+	GFile *          add_default_dir;     /* default directory to be used
 					       * in the Add dialog. */
-	char *           extract_default_dir; /* default directory to be used
+	GFile *          extract_default_dir; /* default directory to be used
 					       * in the Extract dialog. */
 	gboolean         freeze_default_dir;
 	gboolean         asked_for_password;
@@ -348,7 +348,7 @@ struct _FrWindowPrivate {
 
 	/* dragged files data */
 
-	char             *drag_destination_folder;
+	GFile            *drag_destination_folder;
 	char             *drag_base_dir;
 	GError           *drag_error;
 	GList            *drag_file_list;        /* the list of files we are
@@ -370,8 +370,8 @@ struct _FrWindowPrivate {
 	gboolean          progress_pulse;
 	guint             progress_timeout;  /* Timeout to display the progress dialog. */
 	guint             hide_progress_timeout;  /* Timeout to hide the progress dialog. */
-	char             *pd_last_archive;
-	char             *working_archive;
+	GFile            *pd_last_archive;
+	GFile            *working_archive;
 	double            pd_last_fraction;
 	char             *pd_last_message;
 	gboolean          use_progress_dialog;
@@ -519,7 +519,7 @@ _fr_window_convert_data_free (FrWindow   *window,
 			     gboolean    all)
 {
 	if (all) {
-		g_free (window->priv->convert_data.new_file);
+		_g_object_unref (window->priv->convert_data.new_file);
 		window->priv->convert_data.new_file = NULL;
 	}
 
@@ -570,10 +570,10 @@ fr_window_free_private_data (FrWindow *window)
 
 	fr_window_history_clear (window);
 
-	g_free (window->priv->open_default_dir);
-	g_free (window->priv->add_default_dir);
-	g_free (window->priv->extract_default_dir);
-	g_free (window->priv->archive_uri);
+	_g_object_unref (window->priv->open_default_dir);
+	_g_object_unref (window->priv->add_default_dir);
+	_g_object_unref (window->priv->extract_default_dir);
+	_g_object_unref (window->priv->archive_file);
 
 	g_free (window->priv->password);
 	g_free (window->priv->password_for_paste);
@@ -621,7 +621,7 @@ fr_window_free_private_data (FrWindow *window)
 	fr_window_free_batch_data (window);
 	fr_window_reset_current_batch_action (window);
 
-	g_free (window->priv->pd_last_archive);
+	_g_object_unref (window->priv->pd_last_archive);
 	g_free (window->priv->pd_last_message);
 	g_free (window->priv->extract_here_dir);
 
@@ -1997,11 +1997,9 @@ fr_window_update_dir_tree (FrWindow *window)
 	icon = get_mime_type_icon (MIME_TYPE_ARCHIVE);
 	{
 		GtkTreeIter  node;
-		char        *uri;
 		char        *name;
 
-		uri = g_file_get_uri (fr_archive_get_file (window->archive));
-		name = _g_uri_display_basename (uri);
+		name = _g_file_get_display_basename (fr_archive_get_file (window->archive));
 
 		gtk_tree_store_append (window->priv->tree_store, &node, NULL);
 		gtk_tree_store_set (window->priv->tree_store, &node,
@@ -2013,7 +2011,6 @@ fr_window_update_dir_tree (FrWindow *window)
 		g_hash_table_replace (dir_cache, "/", gtk_tree_model_get_path (GTK_TREE_MODEL (window->priv->tree_store), &node));
 
 		g_free (name);
-		g_free (uri);
 	}
 	g_object_unref (icon);
 
@@ -2038,7 +2035,7 @@ fr_window_update_dir_tree (FrWindow *window)
 		gtk_tree_store_append (window->priv->tree_store, &node, &parent);
 		gtk_tree_store_set (window->priv->tree_store, &node,
 				    TREE_COLUMN_ICON, icon,
-				    TREE_COLUMN_NAME, _g_path_get_file_name (dir),
+				    TREE_COLUMN_NAME, _g_path_get_basename (dir),
 				    TREE_COLUMN_PATH, dir,
 				    TREE_COLUMN_WEIGHT, PANGO_WEIGHT_NORMAL,
 				    -1);
@@ -2158,7 +2155,7 @@ fr_window_update_title (FrWindow *window)
 		char *title;
 		char *name;
 
-		name = _g_uri_display_basename (fr_window_get_archive_uri (window));
+		name = _g_file_get_display_basename (fr_window_get_archive_file (window));
 		title = g_strdup_printf ("%s %s",
 					 name,
 					 window->archive->read_only ? _("[read only]") : "");
@@ -2261,27 +2258,29 @@ progress_dialog_delete_event (GtkWidget *caller,
 
 
 static void
-open_folder (GtkWindow  *parent,
-	     const char *folder)
+open_folder (GtkWindow *parent_window,
+	     GFile     *folder)
 {
 	GError *error = NULL;
+	char   *uri;
 
 	if (folder == NULL)
 		return;
 
-	if (! gtk_show_uri (parent != NULL ? gtk_window_get_screen (parent) : NULL,
-			    folder,
+	uri = g_file_get_uri (folder);
+	if (! gtk_show_uri (parent_window != NULL ? gtk_window_get_screen (parent_window) : NULL,
+			    uri,
 			    GDK_CURRENT_TIME, &error))
 	{
 		GtkWidget *d;
 		char      *utf8_name;
 		char      *message;
 
-		utf8_name = g_filename_display_name (folder);
+		utf8_name = _g_file_get_display_basename (folder);
 		message = g_strdup_printf (_("Could not display the folder \"%s\""), utf8_name);
 		g_free (utf8_name);
 
-		d = _gtk_error_dialog_new (parent,
+		d = _gtk_error_dialog_new (parent_window,
 					   GTK_DIALOG_MODAL,
 					   NULL,
 					   message,
@@ -2293,6 +2292,8 @@ open_folder (GtkWindow  *parent,
 		g_free (message);
 		g_clear_error (&error);
 	}
+
+	g_free (uri);
 }
 
 
@@ -2348,13 +2349,13 @@ progress_dialog_response (GtkDialog *dialog,
 
 
 static char*
-get_action_description (FrAction    action,
-			const char *uri)
+get_action_description (FrAction  action,
+			GFile    *file)
 {
 	char *basename;
 	char *message;
 
-	basename = (uri != NULL) ? _g_uri_display_basename (uri) : NULL;
+	basename = _g_file_get_display_basename (file);
 
 	message = NULL;
 	switch (action) {
@@ -2442,8 +2443,8 @@ progress_dialog_set_action_description (FrWindow   *window,
 static void
 progress_dialog_update_action_description (FrWindow *window)
 {
-	const char *current_archive;
-	char       *description;
+	GFile *current_archive;
+	char  *description;
 
 
 	if (window->priv->progress_dialog == NULL)
@@ -2454,12 +2455,11 @@ progress_dialog_update_action_description (FrWindow *window)
 	else if (window->priv->working_archive != NULL)
 		current_archive = window->priv->working_archive;
 	else
-		current_archive = window->priv->archive_uri;
+		current_archive = window->priv->archive_file;
 
-	g_free (window->priv->pd_last_archive);
-	window->priv->pd_last_archive = NULL;
+	_g_clear_object (&window->priv->pd_last_archive);
 	if (current_archive != NULL)
-		window->priv->pd_last_archive = g_strdup (current_archive);
+		window->priv->pd_last_archive = g_object_ref (current_archive);
 
 	description = get_action_description (window->priv->action, window->priv->pd_last_archive);
 	progress_dialog_set_action_description (window, description);
@@ -2470,13 +2470,12 @@ progress_dialog_update_action_description (FrWindow *window)
 
 static gboolean
 fr_window_working_archive_cb (FrArchive  *archive,
-			      const char *archive_filename,
+			      const char *archive_uri,
 			      FrWindow   *window)
 {
-	g_free (window->priv->working_archive);
-	window->priv->working_archive = NULL;
-	if (archive_filename != NULL)
-		window->priv->working_archive = g_strdup (archive_filename);
+	_g_clear_object (&window->priv->working_archive);
+	if (archive_uri != NULL)
+		window->priv->working_archive = g_file_new_for_uri (archive_uri);
 	progress_dialog_update_action_description (window);
 
 	return TRUE;
@@ -2547,14 +2546,11 @@ fr_archive_start_cb (FrArchive *archive,
 		     FrAction   action,
 		     FrWindow  *window)
 {
-	char *uri;
 	char *description;
 
-	uri = g_file_get_uri (fr_archive_get_file (archive));
-	description = get_action_description (action, uri);
+	description = get_action_description (action, fr_archive_get_file (archive));
 	fr_archive_message_cb (archive, description, window);
 
-	g_free (uri);
 	g_free (description);
 }
 
@@ -2607,10 +2603,9 @@ create_the_progress_dialog (FrWindow *window)
 	window->priv->pd_message = _gtk_builder_get_widget (builder, "message_label");
 	window->priv->pd_progress_box = _gtk_builder_get_widget (builder, "progress_box");
 
-	g_free (window->priv->pd_last_archive);
-	window->priv->pd_last_archive = NULL;
-	if (window->priv->archive_uri != NULL)
-		window->priv->pd_last_archive = g_strdup (window->priv->archive_uri);
+	_g_clear_object (&window->priv->pd_last_archive);
+	window->priv->pd_last_archive = _g_object_ref (window->priv->archive_file);
+
 	progress_dialog_update_action_description (window);
 
 	/* signals */
@@ -2701,7 +2696,7 @@ fr_archive_progress_cb (FrArchive *archive,
 			gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (window->priv->pd_progress_bar), fraction);
 		gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (window->priv->progress_bar), fraction);
 
-		if ((archive != NULL) && (fr_archive_progress_get_total_files (archive) > 1)) {
+		if ((archive != NULL) && (fr_archive_progress_get_total_files (archive) > 0)) {
 			char *message = NULL;
 			int   remaining_files;
 
@@ -2800,7 +2795,7 @@ open_progress_dialog_with_open_archive (FrWindow *window)
 	fr_archive_progress_cb (NULL, 1.0, window);
 	fr_archive_message_cb (NULL, NULL, window);
 
-	basename = _g_uri_display_basename (window->priv->convert_data.new_file);
+	basename = _g_file_get_display_basename (window->priv->convert_data.new_file);
 	/* Translators: %s is a filename */
 	description = g_strdup_printf (_("\"%s\" created successfully"), basename);
 	progress_dialog_set_action_description (window, description);
@@ -2825,11 +2820,15 @@ fr_window_push_message (FrWindow   *window,
 
 static void
 fr_window_add_to_recent_list (FrWindow *window,
-			      char     *uri)
+			      GFile    *file)
 {
-	if (_g_path_is_temp_dir (uri))
+	char *uri;
+
+	if (_g_file_is_temp_dir (file))
 		return;
 
+	uri = g_file_get_uri (file);
+
 	if (window->archive->mime_type != NULL) {
 		GtkRecentData *recent_data;
 
@@ -2843,15 +2842,24 @@ fr_window_add_to_recent_list (FrWindow *window,
 	}
 	else
 		gtk_recent_manager_add_item (gtk_recent_manager_get_default (), uri);
+
+	g_free (uri);
 }
 
 
 static void
 fr_window_remove_from_recent_list (FrWindow *window,
-				   char     *filename)
+				   GFile    *file)
 {
-	if (filename != NULL)
-		gtk_recent_manager_remove_item (gtk_recent_manager_get_default (), filename, NULL);
+	char *uri;
+
+	if (file == NULL)
+		return;
+
+	uri = g_file_get_uri (file);
+	gtk_recent_manager_remove_item (gtk_recent_manager_get_default (), uri, NULL);
+
+	g_free (uri);
 }
 
 
@@ -3002,7 +3010,7 @@ _handle_archive_operation_error (FrWindow  *window,
 
 		case FR_ACTION_LOADING_ARCHIVE:
 			dialog_parent = window->priv->load_error_parent_window;
-			utf8_name = _g_uri_display_basename (window->priv->archive_uri);
+			utf8_name = _g_file_get_display_basename (window->priv->archive_file);
 			msg = g_strdup_printf (_("Could not open \"%s\""), utf8_name);
 			g_free (utf8_name);
 			break;
@@ -3083,8 +3091,8 @@ _archive_operation_completed (FrWindow *window,
 	gboolean  continue_batch = FALSE;
 	gboolean  opens_dialog;
 	gboolean  operation_canceled;
-	char     *archive_dir;
-	gboolean  temp_dir;
+	GFile    *archive_dir;
+	gboolean  is_temp_dir;
 
 #ifdef DEBUG
 	debug (DEBUG_INFO, "%s [DONE] (FR::Window)\n", action_names[action]);
@@ -3113,22 +3121,22 @@ _archive_operation_completed (FrWindow *window,
 	case FR_ACTION_LOADING_ARCHIVE:
 		close_progress_dialog (window, FALSE);
 		if (error != NULL) {
-			fr_window_remove_from_recent_list (window, window->priv->archive_uri);
+			fr_window_remove_from_recent_list (window, window->priv->archive_file);
 			fr_window_archive_close (window);
 		}
 		break;
 
 	case FR_ACTION_LISTING_CONTENT:
-		/* update the uri because multi-volume archives can have
+		/* update the file because multi-volume archives can have
 		 * a different name after loading. */
-		g_free (window->priv->archive_uri);
-		window->priv->archive_uri = g_file_get_uri (fr_archive_get_file (window->archive));
+		_g_object_unref (window->priv->archive_file);
+		window->priv->archive_file = _g_object_ref (fr_archive_get_file (window->archive));
 
 		window->priv->reload_archive = FALSE;
 
 		close_progress_dialog (window, FALSE);
 		if (error != NULL) {
-			fr_window_remove_from_recent_list (window, window->priv->archive_uri);
+			fr_window_remove_from_recent_list (window, window->priv->archive_file);
 			fr_window_archive_close (window);
 			fr_window_set_password (window, NULL);
 			break;
@@ -3136,15 +3144,15 @@ _archive_operation_completed (FrWindow *window,
 
 		/* error == NULL */
 
-		archive_dir = _g_path_remove_level (window->priv->archive_uri);
-		temp_dir = _g_path_is_temp_dir (archive_dir);
+		archive_dir = g_file_get_parent (window->priv->archive_file);
+		is_temp_dir = _g_file_is_temp_dir (archive_dir);
 		if (! window->priv->archive_present) {
 			window->priv->archive_present = TRUE;
 
 			fr_window_history_clear (window);
 			fr_window_history_add (window, "/");
 
-			if (! temp_dir) {
+			if (! is_temp_dir) {
 				fr_window_set_open_default_dir (window, archive_dir);
 				fr_window_set_add_default_dir (window, archive_dir);
 				if (! window->priv->freeze_default_dir)
@@ -3153,10 +3161,10 @@ _archive_operation_completed (FrWindow *window,
 
 			window->priv->archive_new = FALSE;
 		}
-		g_free (archive_dir);
+		g_object_unref (archive_dir);
 
-		if (! temp_dir)
-			fr_window_add_to_recent_list (window, window->priv->archive_uri);
+		if (! is_temp_dir)
+			fr_window_add_to_recent_list (window, window->priv->archive_file);
 
 		fr_window_update_title (window);
 		fr_window_go_to_location (window, fr_window_get_current_location (window), TRUE);
@@ -3173,20 +3181,20 @@ _archive_operation_completed (FrWindow *window,
 	case FR_ACTION_ADDING_FILES:
 		close_progress_dialog (window, FALSE);
 
-		/* update the uri because multi-volume archives can have
+		/* update the file because multi-volume archives can have
 		 * a different name after creation. */
-		g_free (window->priv->archive_uri);
-		window->priv->archive_uri = g_file_get_uri (fr_archive_get_file (window->archive));
+		_g_object_unref (window->priv->archive_file);
+		window->priv->archive_file = _g_object_ref (fr_archive_get_file (window->archive));
 
 		if (window->priv->notify) {
-			g_free (window->priv->convert_data.new_file);
-			window->priv->convert_data.new_file = g_strdup (window->priv->archive_uri);
+			_g_object_unref (window->priv->convert_data.new_file);
+			window->priv->convert_data.new_file = g_object_ref (window->priv->archive_file);
 		}
 
 		if (error == NULL) {
 			if (window->priv->archive_new)
 				window->priv->archive_new = FALSE;
-			fr_window_add_to_recent_list (window, window->priv->archive_uri);
+			fr_window_add_to_recent_list (window, window->priv->archive_file);
 		}
 
 		if (! window->priv->batch_mode && ! operation_canceled)
@@ -3244,8 +3252,8 @@ static void
 _archive_operation_started (FrWindow *window,
 			    FrAction  action)
 {
-	char *archive_uri;
-	char *message;
+	GFile *archive;
+	char  *message;
 
 	window->priv->action = action;
 	_fr_window_start_activity_mode (window);
@@ -3254,10 +3262,10 @@ _archive_operation_started (FrWindow *window,
 	debug (DEBUG_INFO, "%s [START] (FR::Window)\n", action_names[action]);
 #endif
 
-	archive_uri = window->priv->pd_last_archive;
-	if (archive_uri == NULL)
-		archive_uri =  window->priv->archive_uri;
-	message = get_action_description (action, archive_uri);
+	archive = window->priv->pd_last_archive;
+	if (archive == NULL)
+		archive =  window->priv->archive_file;
+	message = get_action_description (action, archive);
 	fr_window_push_message (window, message);
 	g_free (message);
 
@@ -3476,8 +3484,6 @@ fr_window_get_file_list_pattern (FrWindow    *window,
 		FileData *fd = g_ptr_array_index (window->archive->files, i);
 		char     *utf8_name;
 
-		/* FIXME: only files in the current location ? */
-
 		if (fd == NULL)
 			continue;
 
@@ -3914,7 +3920,7 @@ file_leave_notify_callback (GtkWidget *widget,
 
 
 static GList *
-get_uri_list_from_selection_data (char *uri_list)
+get_file_list_from_selection_data (char *uri_list)
 {
 	GList  *list = NULL;
 	char  **uris;
@@ -3925,7 +3931,7 @@ get_uri_list_from_selection_data (char *uri_list)
 
 	uris = g_uri_list_extract_uris (uri_list);
 	for (i = 0; uris[i] != NULL; i++)
-		list = g_list_prepend (list, g_strdup (uris[i]));
+		list = g_list_prepend (list, g_file_new_for_uri (uris[i]));
 	g_strfreev (uris);
 
 	return g_list_reverse (list);
@@ -3968,11 +3974,11 @@ get_clipboard_data_from_selection_data (FrWindow   *window,
 
 	uris = g_strsplit (data, "\r\n", -1);
 
-	clipboard_data->archive_uri = g_strdup (uris[0]);
+	clipboard_data->file = g_file_new_for_uri (uris[0]);
 	if (window->priv->password_for_paste != NULL)
-		clipboard_data->archive_password = g_strdup (window->priv->password_for_paste);
+		clipboard_data->password = g_strdup (window->priv->password_for_paste);
 	else if (strcmp (uris[1], "") != 0)
-		clipboard_data->archive_password = g_strdup (uris[1]);
+		clipboard_data->password = g_strdup (uris[1]);
 	clipboard_data->op = (strcmp (uris[2], "copy") == 0) ? FR_CLIPBOARD_OP_COPY : FR_CLIPBOARD_OP_CUT;
 	clipboard_data->base_dir = g_strdup (uris[3]);
 	for (i = 4; uris[i] != NULL; i++)
@@ -3988,13 +3994,13 @@ get_clipboard_data_from_selection_data (FrWindow   *window,
 
 gboolean
 fr_window_create_archive_and_continue (FrWindow   *window,
-			  	       const char *uri,
+			  	       GFile      *file,
 			  	       const char *mime_type,
 			  	       GtkWindow  *error_dialog_parent)
 {
 	gboolean result = FALSE;
 
-	if (fr_window_archive_new (FR_WINDOW (window), uri, mime_type)) {
+	if (fr_window_archive_new (FR_WINDOW (window), file, mime_type)) {
 		if (! fr_window_is_batch_mode (FR_WINDOW (window)))
 			gtk_window_present (GTK_WINDOW (window));
 		_archive_operation_completed (window, FR_ACTION_CREATING_NEW_ARCHIVE, NULL);
@@ -4023,7 +4029,7 @@ new_archive_dialog_response_cb (GtkDialog *dialog,
 				gpointer   user_data)
 {
 	FrWindow   *window = user_data;
-	char       *uri;
+	GFile      *file;
 	const char *mime_type;
 	GtkWidget  *archive_window;
 	gboolean    new_window;
@@ -4037,8 +4043,8 @@ new_archive_dialog_response_cb (GtkDialog *dialog,
 		return;
 	}
 
-	uri = fr_new_archive_dialog_get_uri (FR_NEW_ARCHIVE_DIALOG (dialog), &mime_type);
-	if (uri == NULL)
+	file = fr_new_archive_dialog_get_file (FR_NEW_ARCHIVE_DIALOG (dialog), &mime_type);
+	if (file == NULL)
 		return;
 
 	new_window = fr_window_archive_is_present (window) && ! fr_window_is_batch_mode (window);
@@ -4056,7 +4062,7 @@ new_archive_dialog_response_cb (GtkDialog *dialog,
 	fr_window_set_volume_size (FR_WINDOW (archive_window), volume_size);
 
 	if (fr_window_create_archive_and_continue (FR_WINDOW (archive_window),
-						   uri,
+						   file,
 						   mime_type,
 						   GTK_WINDOW (dialog)))
 	{
@@ -4065,7 +4071,7 @@ new_archive_dialog_response_cb (GtkDialog *dialog,
 	else if (new_window)
 		gtk_widget_destroy (archive_window);
 
-	g_free (uri);
+	g_object_unref (file);
 }
 
 
@@ -4115,7 +4121,7 @@ fr_window_drag_data_received  (GtkWidget          *widget,
 		return;
 	}
 
-	list = get_uri_list_from_selection_data ((char*) gtk_selection_data_get_data (data));
+	list = get_file_list_from_selection_data ((char*) gtk_selection_data_get_data (data));
 	if (list == NULL) {
 		GtkWidget *d;
 
@@ -4132,7 +4138,7 @@ fr_window_drag_data_received  (GtkWidget          *widget,
 
 	one_file = (list->next == NULL);
 	if (one_file)
-		is_an_archive = _g_uri_is_archive (list->data);
+		is_an_archive = _g_file_is_archive (G_FILE (list->data));
 	else
 		is_an_archive = FALSE;
 
@@ -4163,14 +4169,14 @@ fr_window_drag_data_received  (GtkWidget          *widget,
 			if (r == 0)  /* Add */
 				fr_window_archive_add_dropped_items (window, list);
 			else if (r == 1)  /* Open */
-				fr_window_archive_open (window, list->data, GTK_WINDOW (window));
+				fr_window_archive_open (window, G_FILE (list->data), GTK_WINDOW (window));
  		}
  		else
 			fr_window_archive_add_dropped_items (window, list);
 	}
 	else {
 		if (one_file && is_an_archive)
-			fr_window_archive_open (window, list->data, GTK_WINDOW (window));
+			fr_window_archive_open (window, G_FILE (list->data), GTK_WINDOW (window));
 		else {
 			GtkWidget *d;
 			int        r;
@@ -4189,59 +4195,46 @@ fr_window_drag_data_received  (GtkWidget          *widget,
 			gtk_widget_destroy (GTK_WIDGET (d));
 
 			if (r == GTK_RESPONSE_YES) {
-				char       *first_item;
-				char       *folder;
-				char       *local_path = NULL;
-				char       *utf8_path = NULL;
-				const char *archive_name;
-				GtkWidget  *dialog;
+				GFile     *first_file;
+				GFile     *folder;
+				char      *archive_name;
+				GtkWidget *dialog;
 
 				fr_window_free_batch_data (window);
 				fr_window_append_batch_action (window,
 							       FR_BATCH_ACTION_ADD,
-							       _g_string_list_dup (list),
-							       (GFreeFunc) _g_string_list_free);
+							       _g_object_list_ref (list),
+							       (GFreeFunc) _g_object_list_unref);
 
-				first_item = (char*) list->data;
-				folder = _g_path_remove_level (first_item);
+				first_file = G_FILE (list->data);
+				folder = g_file_get_parent (first_file);
 				if (folder != NULL)
 					fr_window_set_open_default_dir (window, folder);
 
-				if ((list->next != NULL) && (folder != NULL)) {
-					archive_name = _g_path_get_file_name (folder);
-				}
-				else {
-					if (_g_uri_is_local (first_item)) {
-						local_path = g_filename_from_uri (first_item, NULL, NULL);
-						if (local_path)
-							utf8_path = g_filename_to_utf8 (local_path, -1, NULL, NULL, NULL);
-						if (!utf8_path)
-							utf8_path= g_strdup (first_item);
-						g_free (local_path);
-					}
-					else {
-						utf8_path = g_strdup (first_item);
-					}
-					archive_name = _g_path_get_file_name (utf8_path);
-				}
+				if ((list->next != NULL) && (folder != NULL))
+					archive_name = g_file_get_basename (folder);
+				else
+					archive_name = g_file_get_basename (first_file);
 
 				dialog = fr_new_archive_dialog_new (GTK_WINDOW (window),
 								    FR_NEW_ARCHIVE_ACTION_SAVE_AS,
 								    archive_name);
-				gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), fr_window_get_open_default_dir (window));
+				gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog),
+									  fr_window_get_open_default_dir (window),
+									  NULL);
 				g_signal_connect (G_OBJECT (dialog),
 						  "response",
 						  G_CALLBACK (new_archive_dialog_response_cb),
 						  window);
 				gtk_window_present (GTK_WINDOW (dialog));
 
-				g_free (utf8_path);
-				g_free (folder);
+				g_free (archive_name);
+				_g_object_unref (folder);
 			}
 		}
 	}
 
-	_g_string_list_free (list);
+	_g_object_list_unref (list);
 
 	debug (DEBUG_INFO, "::DragDataReceived <--\n");
 }
@@ -4367,15 +4360,14 @@ get_selection_data_from_clipboard_data (FrWindow        *window,
 		      			FrClipboardData *data)
 {
 	GString *list;
-	char    *local_filename;
+	char    *uri;
 	GList   *scan;
 
 	list = g_string_new (NULL);
 
-	/* FIXME: check if this works correctly */
-	local_filename = g_file_get_uri (fr_archive_get_file (window->archive));
-	g_string_append (list, local_filename);
-	g_free (local_filename);
+	uri = g_file_get_uri (fr_archive_get_file (window->archive));
+	g_string_append (list, uri);
+	g_free (uri);
 
 	g_string_append (list, "\r\n");
 	if (window->priv->password != NULL)
@@ -4404,8 +4396,9 @@ fr_window_folder_tree_drag_data_get (GtkWidget        *widget,
 {
 	FrWindow *window = user_data;
 	GList    *file_list;
-	char     *destination;
-	char     *destination_folder;
+	char     *uri;
+	GFile    *destination;
+	GFile    *destination_folder;
 
 	debug (DEBUG_INFO, "::DragDataGet -->\n");
 
@@ -4437,35 +4430,38 @@ fr_window_folder_tree_drag_data_get (GtkWidget        *widget,
 	if (! nautilus_xds_dnd_is_valid_xds_context (context))
 		return FALSE;
 
-	destination = get_xds_atom_value (context);
-	g_return_val_if_fail (destination != NULL, FALSE);
+	uri  = get_xds_atom_value (context);
+	g_return_val_if_fail (uri != NULL, FALSE);
 
-	destination_folder = _g_path_remove_level (destination);
-	g_free (destination);
+	destination = g_file_new_for_uri (uri);
+	destination_folder = g_file_get_parent (destination);
+
+	g_object_unref (destination);
 
 	/* check whether the extraction can be performed in the destination
 	 * folder */
 
 	g_clear_error (&window->priv->drag_error);
 
-	if (! _g_uri_check_permissions (destination_folder, R_OK | W_OK)) {
-		char *destination_folder_display_name;
+	if (! _g_file_check_permissions (destination_folder, R_OK | W_OK)) {
+		char *display_name;
 
-		destination_folder_display_name = g_filename_display_name (destination_folder);
-		window->priv->drag_error = g_error_new (FR_ERROR, 0, _("You don't have the right permissions to extract archives in the folder \"%s\""), destination_folder_display_name);
-		g_free (destination_folder_display_name);
+		display_name = _g_file_get_display_basename (destination_folder);
+		window->priv->drag_error = g_error_new (FR_ERROR, 0, _("You don't have the right permissions to extract archives in the folder \"%s\""), display_name);
+
+		g_free (display_name);
 	}
 
 	if (window->priv->drag_error == NULL) {
 		g_free (window->priv->drag_destination_folder);
 		g_free (window->priv->drag_base_dir);
 		_g_string_list_free (window->priv->drag_file_list);
-		window->priv->drag_destination_folder = g_strdup (destination_folder);
+		window->priv->drag_destination_folder = g_object_ref (destination_folder);
 		window->priv->drag_base_dir = fr_window_get_selected_folder_in_tree_view (window);
 		window->priv->drag_file_list = file_list;
 	}
 
-	g_free (destination_folder);
+	g_object_unref (destination_folder);
 
 	/* sends back the response */
 
@@ -4483,8 +4479,9 @@ fr_window_file_list_drag_data_get (FrWindow         *window,
 				   GtkSelectionData *selection_data,
 				   GList            *path_list)
 {
-	char *destination;
-	char *destination_folder;
+	char  *uri;
+	GFile *destination;
+	GFile *destination_folder;
 
 	debug (DEBUG_INFO, "::DragDataGet -->\n");
 
@@ -4517,35 +4514,38 @@ fr_window_file_list_drag_data_get (FrWindow         *window,
 	if (! nautilus_xds_dnd_is_valid_xds_context (context))
 		return FALSE;
 
-	destination = get_xds_atom_value (context);
-	g_return_val_if_fail (destination != NULL, FALSE);
+	uri = get_xds_atom_value (context);
+	g_return_val_if_fail (uri != NULL, FALSE);
 
-	destination_folder = _g_path_remove_level (destination);
-	g_free (destination);
+	destination = g_file_new_for_uri (uri);
+	destination_folder = g_file_get_parent (destination);
+
+	g_object_unref (destination);
 
 	/* check whether the extraction can be performed in the destination
 	 * folder */
 
 	g_clear_error (&window->priv->drag_error);
 
-	if (! _g_uri_check_permissions (destination_folder, R_OK | W_OK)) {
-		char *destination_folder_display_name;
+	if (! _g_file_check_permissions (destination_folder, R_OK | W_OK)) {
+		char *display_name;
 
-		destination_folder_display_name = g_filename_display_name (destination_folder);
-		window->priv->drag_error = g_error_new (FR_ERROR, 0, _("You don't have the right permissions to extract archives in the folder \"%s\""), destination_folder_display_name);
-		g_free (destination_folder_display_name);
+		display_name = _g_file_get_display_basename (destination_folder);
+		window->priv->drag_error = g_error_new (FR_ERROR, 0, _("You don't have the right permissions to extract archives in the folder \"%s\""), display_name);
+
+		g_free (display_name);
 	}
 
 	if (window->priv->drag_error == NULL) {
 		g_free (window->priv->drag_destination_folder);
 		g_free (window->priv->drag_base_dir);
 		_g_string_list_free (window->priv->drag_file_list);
-		window->priv->drag_destination_folder = g_strdup (destination_folder);
+		window->priv->drag_destination_folder = g_object_ref (destination_folder);
 		window->priv->drag_base_dir = g_strdup (fr_window_get_current_location (window));
 		window->priv->drag_file_list = fr_window_get_file_list_from_path_list (window, path_list, NULL);
 	}
 
-	g_free (destination_folder);
+	g_object_unref (destination_folder);
 
 	/* sends back the response */
 
@@ -5313,13 +5313,18 @@ static void
 recent_chooser_item_activated_cb (GtkRecentChooser *chooser,
 				  FrWindow         *window)
 {
-	char *uri;
+	char  *uri;
+	GFile *file;
 
 	uri = gtk_recent_chooser_get_current_uri (chooser);
-	if (uri != NULL) {
-		fr_window_archive_open (window, uri, GTK_WINDOW (window));
-		g_free (uri);
-	}
+	if (uri == NULL)
+		return;
+
+	file = g_file_new_for_uri (uri);
+	fr_window_archive_open (window, file, GTK_WINDOW (window));
+
+	g_object_unref (file);
+	g_free (uri);
 }
 
 
@@ -5562,9 +5567,9 @@ fr_window_construct (FrWindow *window)
 
 	window->priv->action = FR_ACTION_NONE;
 
-	window->priv->open_default_dir = g_strdup (_g_uri_get_home ());
-	window->priv->add_default_dir = g_strdup (_g_uri_get_home ());
-	window->priv->extract_default_dir = g_strdup (_g_uri_get_home ());
+	window->priv->open_default_dir = g_object_ref (_g_file_get_home ());
+	window->priv->add_default_dir = g_object_ref (_g_file_get_home ());
+	window->priv->extract_default_dir = g_object_ref (_g_file_get_home ());
 
 	window->priv->give_focus_to_the_list = FALSE;
 
@@ -5576,7 +5581,7 @@ fr_window_construct (FrWindow *window)
 	window->priv->archive_present = FALSE;
 	window->priv->archive_new = FALSE;
 	window->priv->reload_archive = FALSE;
-	window->priv->archive_uri = NULL;
+	window->priv->archive_file = NULL;
 
 	window->priv->drag_destination_folder = NULL;
 	window->priv->drag_base_dir = NULL;
@@ -6101,39 +6106,34 @@ _fr_window_set_archive (FrWindow  *window,
 
 
 static void
-_fr_window_set_archive_uri (FrWindow   *window,
-			   const char *uri)
+_fr_window_set_archive_file (FrWindow *window,
+			     GFile    *file)
 {
-	if (window->priv->archive_uri != NULL)
-		g_free (window->priv->archive_uri);
-	window->priv->archive_uri = g_strdup (uri);
+	_g_object_unref (window->priv->archive_file);
+	window->priv->archive_file = _g_object_ref (file);
 }
 
 
 gboolean
 fr_window_archive_new (FrWindow   *window,
-		       const char *uri,
+		       GFile      *file,
 		       const char *mime_type)
 {
-	GFile     *file;
 	FrArchive *archive;
 
 	g_return_val_if_fail (window != NULL, FALSE);
 
-	file = g_file_new_for_uri (uri);
 	archive = fr_archive_create (file, mime_type);
 	if (archive != NULL) {
 		fr_window_archive_close (window);
 		_fr_window_set_archive (window, archive);
-		_fr_window_set_archive_uri (window, uri);
+		_fr_window_set_archive_file (window, file);
 		window->priv->archive_present = TRUE;
 		window->priv->archive_new = TRUE;
 
 		g_object_unref (archive);
 	}
 
-	g_object_unref (file);
-
 	return archive != NULL;
 }
 
@@ -6195,11 +6195,12 @@ archive_open_ready_cb (GObject      *source_object,
 
 FrWindow *
 fr_window_archive_open (FrWindow   *current_window,
-			const char *uri,
+			GFile      *file,
 			GtkWindow  *parent)
 {
 	FrWindow *window = current_window;
-	GFile    *file;
+
+	g_return_val_if_fail (file != NULL, FALSE);
 
 	if (current_window->priv->archive_present)
 		window = (FrWindow *) fr_window_new ();
@@ -6207,7 +6208,7 @@ fr_window_archive_open (FrWindow   *current_window,
 	g_return_val_if_fail (window != NULL, FALSE);
 
 	fr_window_archive_close (window);
-	_fr_window_set_archive_uri (window, uri);
+	_fr_window_set_archive_file (window, file);
 	window->priv->give_focus_to_the_list = TRUE;
 	window->priv->load_error_parent_window = parent;
 
@@ -6216,17 +6217,14 @@ fr_window_archive_open (FrWindow   *current_window,
 	/* this is used to reload the archive after asking a password */
 	fr_window_set_current_batch_action (window,
 					    FR_BATCH_ACTION_LOAD,
-					    g_strdup (window->priv->archive_uri),
-					    (GFreeFunc) g_free);
+					    g_object_ref (file),
+					    (GFreeFunc) g_object_unref);
 
-	file = g_file_new_for_uri (window->priv->archive_uri);
 	fr_archive_open (file,
 			 window->priv->cancellable,
 			 archive_open_ready_cb,
 			 window);
 
-	g_object_unref (file);
-
 	return window;
 }
 
@@ -6260,22 +6258,22 @@ fr_window_archive_close (FrWindow *window)
 }
 
 
-const char *
-fr_window_get_archive_uri (FrWindow *window)
+GFile *
+fr_window_get_archive_file (FrWindow *window)
 {
 	g_return_val_if_fail (window != NULL, NULL);
 
-	return window->priv->archive_uri;
+	return window->priv->archive_file;
 }
 
 
-const char *
-fr_window_get_paste_archive_uri (FrWindow *window)
+GFile *
+fr_window_get_archive_file_for_paste (FrWindow *window)
 {
 	g_return_val_if_fail (window != NULL, NULL);
 
 	if (window->priv->clipboard_data != NULL)
-		return window->priv->clipboard_data->archive_uri;
+		return window->priv->clipboard_data->file;
 	else
 		return NULL;
 }
@@ -6365,7 +6363,7 @@ _fr_window_notify_creation_complete (FrWindow *window)
 	NotifyData         *notify_data;
 
 	title = get_action_description (window->priv->action, window->priv->pd_last_archive);
-	basename = _g_uri_display_basename (window->priv->convert_data.new_file);
+	basename = _g_file_get_display_basename (window->priv->convert_data.new_file);
 	/* Translators: %s is a filename */
 	message = g_strdup_printf (_("\"%s\" created successfully"), basename);
 	notification = notify_notification_new (window->priv->batch_title, message, "file-roller");
@@ -6453,45 +6451,18 @@ archive_add_files_ready_cb (GObject      *source_object,
 
 
 void
-fr_window_archive_add_files (FrWindow *window,
-			     GList    *file_list, /* GFile list */
-			     gboolean  update)
+fr_window_archive_add_files (FrWindow   *window,
+			     GList      *file_list, /* GFile list */
+			     GFile      *base_dir,
+			     gboolean    update)
 {
-	GFile *base;
-	char  *base_dir;
-	int    base_len;
-	GList *files = NULL;
-	GList *scan;
-	char  *base_uri;
-
-	base = g_file_get_parent ((GFile *) file_list->data);
-	base_dir = g_file_get_path (base);
-	base_len = 0;
-	if (strcmp (base_dir, "/") != 0)
-		base_len = strlen (base_dir);
-
-	for (scan = file_list; scan; scan = scan->next) {
-		GFile *file = scan->data;
-		char  *path;
-		char  *rel_path;
-
-		path = g_file_get_path (file);
-		rel_path = g_strdup (path + base_len + 1);
-		files = g_list_prepend (files, rel_path);
-
-		g_free (path);
-	}
-
-	base_uri = g_file_get_uri (base);
-
 	_archive_operation_started (window, FR_ACTION_ADDING_FILES);
 
 	fr_archive_add_files (window->archive,
-			      files,
-			      base_uri,
+			      file_list,
+			      base_dir,
 			      fr_window_get_current_location (window),
 			      update,
-			      FALSE,
 			      window->priv->password,
 			      window->priv->encrypt_header,
 			      window->priv->compression,
@@ -6499,101 +6470,47 @@ fr_window_archive_add_files (FrWindow *window,
 			      window->priv->cancellable,
 			      archive_add_files_ready_cb,
 			      window);
-
-	g_free (base_uri);
-	_g_string_list_free (files);
-	g_free (base_dir);
-	g_object_unref (base);
-}
-
-
-void
-fr_window_archive_add_with_wildcard (FrWindow      *window,
-				     const char    *include_files,
-				     const char    *exclude_files,
-				     const char    *exclude_folders,
-				     const char    *base_dir,
-				     const char    *dest_dir,
-				     gboolean       update,
-				     gboolean       follow_links)
-{
-	_archive_operation_started (window, FR_ACTION_ADDING_FILES);
-
-	fr_archive_add_with_wildcard (window->archive,
-				      include_files,
-				      exclude_files,
-				      exclude_folders,
-				      base_dir,
-				      (dest_dir == NULL)? fr_window_get_current_location (window): dest_dir,
-				      update,
-				      follow_links,
-				      window->priv->password,
-				      window->priv->encrypt_header,
-				      window->priv->compression,
-				      window->priv->volume_size,
-				      window->priv->cancellable,
-				      archive_add_files_ready_cb,
-				      window);
 }
 
 
 void
-fr_window_archive_add_directory (FrWindow      *window,
-				 const char    *directory,
-				 const char    *base_dir,
-				 const char    *dest_dir,
-				 gboolean       update)
+fr_window_archive_add_with_filter (FrWindow      *window,
+				   GFile         *base_dir,
+				   const char    *include_files,
+				   const char    *exclude_files,
+				   const char    *exclude_folders,
+				   const char    *dest_dir,
+				   gboolean       update,
+				   gboolean       follow_links)
 {
 	_archive_operation_started (window, FR_ACTION_ADDING_FILES);
 
-	fr_archive_add_directory (window->archive,
-				  directory,
-				  base_dir,
-				  (dest_dir == NULL)? fr_window_get_current_location (window): dest_dir,
-				  update,
-				  window->priv->password,
-				  window->priv->encrypt_header,
-				  window->priv->compression,
-				  window->priv->volume_size,
-				  window->priv->cancellable,
-				  archive_add_files_ready_cb,
-				  window);
-}
-
-
-void
-fr_window_archive_add_items (FrWindow      *window,
-			     GList         *item_list,
-			     const char    *base_dir,
-			     const char    *dest_dir,
-			     gboolean       update)
-{
-	_archive_operation_started (window, FR_ACTION_ADDING_FILES);
-
-	fr_archive_add_items (window->archive,
-			      item_list,
-			      base_dir,
-			      (dest_dir == NULL)? fr_window_get_current_location (window): dest_dir,
-			      update,
-			      window->priv->password,
-			      window->priv->encrypt_header,
-			      window->priv->compression,
-			      window->priv->volume_size,
-			      window->priv->cancellable,
-			      archive_add_files_ready_cb,
-			      window);
+	fr_archive_add_files_with_filter (window->archive,
+					  base_dir,
+					  include_files,
+					  exclude_files,
+					  exclude_folders,
+					  (dest_dir == NULL)? fr_window_get_current_location (window): dest_dir,
+					  update,
+					  follow_links,
+					  window->priv->password,
+					  window->priv->encrypt_header,
+					  window->priv->compression,
+					  window->priv->volume_size,
+					  window->priv->cancellable,
+					  archive_add_files_ready_cb,
+					  window);
 }
 
 
 void
 fr_window_archive_add_dropped_items (FrWindow *window,
-				     GList    *item_list)
+				     GList    *file_list)
 {
 	_archive_operation_started (window, FR_ACTION_ADDING_FILES);
 
 	fr_archive_add_dropped_items (window->archive,
-				      item_list,
-				      fr_window_get_current_location (window),
+				      file_list,
 				      fr_window_get_current_location (window),
 				      window->priv->password,
 				      window->priv->encrypt_header,
@@ -6640,7 +6557,7 @@ fr_window_archive_remove (FrWindow *window,
 
 static ExtractData*
 extract_data_new (GList       *file_list,
-		  const char  *extract_to_dir,
+		  GFile       *destination,
 		  const char  *base_dir,
 		  gboolean     skip_older,
 		  FrOverwrite  overwrite,
@@ -6652,8 +6569,7 @@ extract_data_new (GList       *file_list,
 
 	edata = g_new0 (ExtractData, 1);
 	edata->file_list = _g_string_list_dup (file_list);
-	if (extract_to_dir != NULL)
-		edata->extract_to_dir = g_strdup (extract_to_dir);
+	edata->destination = _g_object_ref (destination);
 	edata->skip_older = skip_older;
 	edata->overwrite = overwrite;
 	edata->junk_paths = junk_paths;
@@ -6666,8 +6582,8 @@ extract_data_new (GList       *file_list,
 }
 
 
-static ExtractData*
-extract_to_data_new (const char *extract_to_dir)
+static ExtractData *
+extract_to_data_new (GFile *extract_to_dir)
 {
 	return extract_data_new (NULL,
 				 extract_to_dir,
@@ -6686,7 +6602,7 @@ extract_data_free (ExtractData *edata)
 	g_return_if_fail (edata != NULL);
 
 	_g_string_list_free (edata->file_list);
-	g_free (edata->extract_to_dir);
+	_g_object_unref (edata->destination);
 	g_free (edata->base_dir);
 
 	g_free (edata);
@@ -6745,7 +6661,7 @@ _fr_window_archive_extract_from_edata (FrWindow    *window,
 
 	fr_archive_extract (window->archive,
 			    edata->file_list,
-			    edata->extract_to_dir,
+			    edata->destination,
 			    edata->base_dir,
 			    edata->skip_older,
 			    edata->overwrite == FR_OVERWRITE_YES,
@@ -6815,27 +6731,20 @@ _fr_window_ask_overwrite_dialog (OverwriteData *odata)
 
 	while ((odata->edata->overwrite == FR_OVERWRITE_ASK) && (odata->current_file != NULL)) {
 		const char *base_name;
-		char       *e_base_name;
-		char       *dest_uri;
-		GFile      *file;
+		GFile      *destination;
 		GFileInfo  *info;
 		GFileType   file_type;
 
-		base_name = _g_path_get_basename ((char *) odata->current_file->data, odata->edata->base_dir, odata->edata->junk_paths);
-		e_base_name = g_uri_escape_string (base_name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, TRUE);
-		dest_uri = g_strdup_printf ("%s/%s", odata->edata->extract_to_dir, e_base_name);
-		file = g_file_new_for_uri (dest_uri);
-		info = g_file_query_info (file,
+		base_name = _g_path_get_relative_basename ((char *) odata->current_file->data, odata->edata->base_dir, odata->edata->junk_paths);
+		destination = g_file_get_child (odata->edata->destination, base_name);
+		info = g_file_query_info (destination,
 					  G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
 					  G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
 					  NULL,
 					  NULL);
 
-		g_free (dest_uri);
-		g_free (e_base_name);
-
 		if (info == NULL) {
-			g_object_unref (file);
+			g_object_unref (destination);
 			odata->current_file = odata->current_file->next;
 			continue;
 		}
@@ -6849,7 +6758,7 @@ _fr_window_ask_overwrite_dialog (OverwriteData *odata)
 			GtkWidget *d;
 
 			msg = g_strdup_printf (_("Replace file \"%s\"?"), g_file_info_get_display_name (info));
-			parent = g_file_get_parent (file);
+			parent = g_file_get_parent (destination);
 			parent_name = g_file_get_parse_name (parent);
 			details = g_strdup_printf (_("Another file with the same name already exists in \"%s\"."), parent_name);
 			d = _gtk_message_dialog_new (GTK_WINDOW (odata->window),
@@ -6872,7 +6781,7 @@ _fr_window_ask_overwrite_dialog (OverwriteData *odata)
 			g_free (parent_name);
 			g_object_unref (parent);
 			g_object_unref (info);
-			g_object_unref (file);
+			g_object_unref (destination);
 
 			return;
 		}
@@ -6880,7 +6789,7 @@ _fr_window_ask_overwrite_dialog (OverwriteData *odata)
 			odata->current_file = odata->current_file->next;
 
 		g_object_unref (info);
-		g_object_unref (file);
+		g_object_unref (destination);
 	}
 
 	if (do_not_extract) {
@@ -6944,7 +6853,7 @@ archive_is_encrypted (FrWindow *window,
 void
 fr_window_archive_extract (FrWindow    *window,
 			   GList       *file_list,
-			   const char  *extract_to_dir,
+			   GFile       *destination,
 			   const char  *base_dir,
 			   gboolean     skip_older,
 			   FrOverwrite  overwrite,
@@ -6956,7 +6865,7 @@ fr_window_archive_extract (FrWindow    *window,
 	GError      *error = NULL;
 
 	edata = extract_data_new (file_list,
-				  extract_to_dir,
+				  destination,
 				  base_dir,
 				  skip_older,
 				  overwrite,
@@ -6974,7 +6883,7 @@ fr_window_archive_extract (FrWindow    *window,
 		return;
 	}
 
-	if (! _g_uri_query_is_dir (edata->extract_to_dir)) {
+	if (! _g_file_query_is_dir (edata->destination)) {
 
 		/* There is nothing to ask if the destination doesn't exist. */
 		if (edata->overwrite == FR_OVERWRITE_ASK)
@@ -6986,7 +6895,7 @@ fr_window_archive_extract (FrWindow    *window,
 			char      *folder_name;
 			char      *msg;
 
-			folder_name = g_filename_display_name (edata->extract_to_dir);
+			folder_name = _g_file_get_display_basename (edata->destination);
 			msg = g_strdup_printf (_("Destination folder \"%s\" does not exist.\n\nDo you want to create it?"), folder_name);
 			g_free (folder_name);
 
@@ -7009,7 +6918,7 @@ fr_window_archive_extract (FrWindow    *window,
 				do_not_extract = TRUE;
 		}
 
-		if (! do_not_extract && ! _g_uri_ensure_dir_exists (edata->extract_to_dir, 0755, &error)) {
+		if (! do_not_extract && ! _g_file_make_directory_tree (edata->destination, 0755, &error)) {
 			GtkWidget *d;
 			char      *details;
 
@@ -7396,7 +7305,7 @@ fr_window_action_new_archive (FrWindow *window)
 	dialog = fr_new_archive_dialog_new (GTK_WINDOW (window),
 					    FR_NEW_ARCHIVE_ACTION_NEW,
 					    NULL);
-	gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), fr_window_get_open_default_dir (window));
+	gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog), fr_window_get_open_default_dir (window), NULL);
 	g_signal_connect (G_OBJECT (dialog),
 			  "response",
 			  G_CALLBACK (new_archive_dialog_response_cb),
@@ -7409,7 +7318,7 @@ fr_window_action_new_archive (FrWindow *window)
 
 
 typedef struct {
-	char     *uri;
+	GFile    *file;
 	char     *mime_type;
 	char     *password;
 	gboolean  encrypt_header;
@@ -7418,7 +7327,7 @@ typedef struct {
 
 
 static SaveAsData *
-save_as_data_new (const char *uri,
+save_as_data_new (GFile      *file,
 		  const char *mime_type,
 		  const char *password,
 		  gboolean    encrypt_header,
@@ -7427,8 +7336,7 @@ save_as_data_new (const char *uri,
 	SaveAsData *sdata;
 
 	sdata = g_new0 (SaveAsData, 1);
-	if (uri != NULL)
-		sdata->uri = g_strdup (uri);
+	sdata->file = _g_object_ref (file);
 	if (mime_type != NULL)
 		sdata->mime_type = g_strdup (mime_type);
 	if (password != NULL)
@@ -7445,7 +7353,7 @@ save_as_data_free (SaveAsData *sdata)
 {
 	if (sdata == NULL)
 		return;
-	g_free (sdata->uri);
+	_g_object_unref (sdata->file);
 	g_free (sdata->mime_type);
 	g_free (sdata->password);
 	g_free (sdata);
@@ -7475,7 +7383,7 @@ archive_add_ready_for_conversion_cb (GObject      *source_object,
 						 NULL,
 						 NULL);
 
-	_g_path_remove_directory (window->priv->convert_data.temp_dir);
+	_g_file_remove_directory (window->priv->convert_data.temp_dir, NULL, NULL);
 	_fr_window_convert_data_free (window, FALSE);
 
 	if (error == NULL)
@@ -7503,7 +7411,7 @@ _save_as_operation_completed_with_error (FrWindow *window,
 		return;
 	}
 
-	_g_path_remove_directory (window->priv->convert_data.temp_dir);
+	_g_file_remove_directory (window->priv->convert_data.temp_dir, NULL, NULL);
 	_fr_window_convert_data_free (window, TRUE);
 
 	_fr_window_stop_activity_mode (window);
@@ -7519,63 +7427,54 @@ archive_extraction_ready_for_convertion_cb (GObject      *source_object,
 {
 	FrWindow *window = user_data;
 	GError   *error = NULL;
-	char     *source_dir;
 
 	if (! fr_archive_operation_finish (FR_ARCHIVE (source_object), result, &error)) {
 		_save_as_operation_completed_with_error (window, FR_ACTION_EXTRACTING_FILES, error);
 		return;
 	}
 
-	source_dir = g_filename_to_uri (window->priv->convert_data.temp_dir, NULL, NULL);
-	fr_archive_add_with_wildcard (window->priv->convert_data.new_archive,
-				      "*",
-				      NULL,
-				      NULL,
-				      source_dir,
-				      NULL,
-				      FALSE,
-				      TRUE,
-				      window->priv->convert_data.password,
-				      window->priv->convert_data.encrypt_header,
-				      window->priv->compression,
-				      window->priv->convert_data.volume_size,
-				      window->priv->cancellable,
-				      archive_add_ready_for_conversion_cb,
-				      window);
-
-	g_free (source_dir);
+	fr_archive_add_files_with_filter (window->priv->convert_data.new_archive,
+					  window->priv->convert_data.temp_dir,
+					  "*",
+					  NULL,
+					  NULL,
+					  NULL,
+					  FALSE,
+					  TRUE,
+					  window->priv->convert_data.password,
+					  window->priv->convert_data.encrypt_header,
+					  window->priv->compression,
+					  window->priv->convert_data.volume_size,
+					  window->priv->cancellable,
+					  archive_add_ready_for_conversion_cb,
+					  window);
 }
 
 
 static void
 fr_window_archive_save_as (FrWindow   *window,
-			   const char *uri,
+			   GFile      *file,
 			   const char *mime_type,
 			   const char *password,
 			   gboolean    encrypt_header,
 			   guint       volume_size)
 {
-	GFile *file;
-
 	g_return_if_fail (window != NULL);
-	g_return_if_fail (uri != NULL);
+	g_return_if_fail (file != NULL);
 	g_return_if_fail (window->archive != NULL);
 
 	_fr_window_convert_data_free (window, TRUE);
-	window->priv->convert_data.new_file = g_strdup (uri);
+	window->priv->convert_data.new_file = g_object_ref (file);
 
 	/* create the new archive */
 
-	file = g_file_new_for_uri (uri);
 	window->priv->convert_data.new_archive = fr_archive_create (file, mime_type);
-	g_object_unref (file);
-
 	if (window->priv->convert_data.new_archive == NULL) {
 		GtkWidget *d;
 		char      *utf8_name;
 		char      *message;
 
-		utf8_name = _g_uri_display_basename (uri);
+		utf8_name = _g_file_get_display_basename (file);
 		message = g_strdup_printf (_("Could not save the archive \"%s\""), utf8_name);
 		g_free (utf8_name);
 
@@ -7605,7 +7504,7 @@ fr_window_archive_save_as (FrWindow   *window,
 
 	fr_window_set_current_batch_action (window,
 					    FR_BATCH_ACTION_SAVE_AS,
-					    save_as_data_new (uri, mime_type, password, encrypt_header, volume_size),
+					    save_as_data_new (file, mime_type, password, encrypt_header, volume_size),
 					    (GFreeFunc) save_as_data_free);
 
 	g_signal_connect (G_OBJECT (window->priv->convert_data.new_archive),
@@ -7630,20 +7529,20 @@ fr_window_archive_save_as (FrWindow   *window,
 			  window);
 
 	window->priv->convert_data.converting = TRUE;
-	window->priv->convert_data.temp_dir = _g_path_get_temp_work_dir (NULL);
+	window->priv->convert_data.temp_dir = _g_file_get_temp_work_dir (NULL);
 
 	fr_archive_action_started (window->archive, FR_ACTION_EXTRACTING_FILES);
-	fr_archive_extract_to_local (window->archive,
-				     NULL,
-				     window->priv->convert_data.temp_dir,
-				     NULL,
-				     TRUE,
-				     TRUE,
-				     FALSE,
-				     window->priv->password,
-				     window->priv->cancellable,
-				     archive_extraction_ready_for_convertion_cb,
-				     window);
+	fr_archive_extract (window->archive,
+			    NULL,
+			    window->priv->convert_data.temp_dir,
+			    NULL,
+			    TRUE,
+			    TRUE,
+			    FALSE,
+			    window->priv->password,
+			    window->priv->cancellable,
+			    archive_extraction_ready_for_convertion_cb,
+			    window);
 }
 
 
@@ -7653,7 +7552,7 @@ save_as_archive_dialog_response_cb (GtkDialog *dialog,
 				    gpointer   user_data)
 {
 	FrWindow   *window = user_data;
-	char       *uri;
+	GFile      *file;
 	const char *mime_type;
 	const char *password;
 	gboolean    encrypt_header;
@@ -7669,8 +7568,8 @@ save_as_archive_dialog_response_cb (GtkDialog *dialog,
 	if (response != GTK_RESPONSE_OK)
 		return;
 
-	uri = fr_new_archive_dialog_get_uri (FR_NEW_ARCHIVE_DIALOG (dialog), &mime_type);
-	if (uri == NULL)
+	file = fr_new_archive_dialog_get_file (FR_NEW_ARCHIVE_DIALOG (dialog), &mime_type);
+	if (file == NULL)
 		return;
 
 	password = fr_new_archive_dialog_get_password (FR_NEW_ARCHIVE_DIALOG (dialog));
@@ -7681,10 +7580,10 @@ save_as_archive_dialog_response_cb (GtkDialog *dialog,
 	g_settings_set_int (settings, PREF_BATCH_ADD_VOLUME_SIZE, volume_size);
 	g_object_unref (settings);
 
-	fr_window_archive_save_as (window, uri, mime_type, password, encrypt_header, volume_size);
+	fr_window_archive_save_as (window, file, mime_type, password, encrypt_header, volume_size);
 
 	gtk_widget_destroy (GTK_WIDGET (dialog));
-	g_free (uri);
+	g_object_unref (file);
 }
 
 
@@ -7695,31 +7594,23 @@ fr_window_action_save_as (FrWindow *window)
 	GtkWidget *dialog;
 
 	archive_name = NULL;
-	if (window->priv->archive_uri != NULL) {
-		GFile      *file;
-		GFileInfo  *info;
-		GError     *err = NULL;
+	if (window->priv->archive_file != NULL) {
+		GFileInfo *info;
 
-		file = g_file_new_for_uri (window->priv->archive_uri);
-		info = g_file_query_info (file,
+		info = g_file_query_info (window->priv->archive_file,
 					  G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
-					  0, NULL, &err);
+					  0, NULL, NULL);
 
-		if (err != NULL) {
-			g_warning ("Failed to get display name for uri %s: %s", window->priv->archive_uri, err->message);
-			g_clear_error (&err);
-		}
-		else
+		if (info != NULL) {
 			archive_name = g_strdup (g_file_info_get_display_name (info));
-
-		g_object_unref (info);
-		g_object_unref (file);
+			g_object_unref (info);
+		}
 	}
 
 	dialog = fr_new_archive_dialog_new (GTK_WINDOW (window),
 					    FR_NEW_ARCHIVE_ACTION_SAVE_AS,
 					    archive_name);
-	gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), fr_window_get_open_default_dir (window));
+	gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog), fr_window_get_open_default_dir (window), NULL);
 	g_signal_connect (G_OBJECT (dialog),
 			  "response",
 			  G_CALLBACK (save_as_archive_dialog_response_cb),
@@ -8056,7 +7947,7 @@ fr_window_rename_selection (FrWindow *window,
 		if (path_to_rename == NULL)
 			return;
 		parent_dir = _g_path_remove_level (path_to_rename);
-		old_name = g_strdup (_g_path_get_file_name (path_to_rename));
+		old_name = g_strdup (_g_path_get_basename (path_to_rename));
 		renaming_dir = TRUE;
 	}
 	else {
@@ -8354,8 +8245,8 @@ add_pasted_files (FrWindow        *window,
 	}
 
 	fr_archive_paste_clipboard (window->archive,
-				    data->archive_uri,
-				    data->archive_password,
+				    data->file,
+				    data->password,
 				    window->priv->encrypt_header,
 				    window->priv->compression,
 				    window->priv->volume_size,
@@ -8452,17 +8343,17 @@ paste_from_archive_open_cb (GObject      *source_object,
 			  G_CALLBACK (fr_window_working_archive_cb),
 			  window);
 
-	fr_archive_extract_to_local (window->priv->copy_from_archive,
-				     window->priv->clipboard_data->files,
-				     window->priv->clipboard_data->tmp_dir,
-				     NULL,
-				     FALSE,
-				     TRUE,
-				     FALSE,
-				     window->priv->clipboard_data->archive_password,
-				     window->priv->cancellable,
-				     paste_from_archive_extract_ready_cb,
-				     window);
+	fr_archive_extract (window->priv->copy_from_archive,
+			    window->priv->clipboard_data->files,
+			    window->priv->clipboard_data->tmp_dir,
+			    NULL,
+			    FALSE,
+			    TRUE,
+			    FALSE,
+			    window->priv->clipboard_data->password,
+			    window->priv->cancellable,
+			    paste_from_archive_extract_ready_cb,
+			    window);
 }
 
 
@@ -8473,7 +8364,6 @@ fr_window_paste_from_clipboard_data (FrWindow        *window,
 	const char *current_dir_relative;
 	GHashTable *created_dirs;
 	GList      *scan;
-	GFile      *file;
 
 	if (window->priv->password_for_paste != NULL)
 		fr_clipboard_data_set_password (data, window->priv->password_for_paste);
@@ -8490,22 +8380,23 @@ fr_window_paste_from_clipboard_data (FrWindow        *window,
 
 	current_dir_relative = data->current_dir + 1;
 
-	data->tmp_dir = _g_path_get_temp_work_dir (NULL);
+	data->tmp_dir = _g_file_get_temp_work_dir (NULL);
 	created_dirs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 	for (scan = data->files; scan; scan = scan->next) {
 		const char *old_name = (char*) scan->data;
-		char       *new_name = g_build_filename (current_dir_relative, old_name + strlen (data->base_dir) - 1, NULL);
-		char       *dir = _g_path_remove_level (new_name);
+		char       *new_name;
+		char       *dir;
 
+		new_name = g_build_filename (current_dir_relative, old_name + strlen (data->base_dir) - 1, NULL);
+		dir = _g_path_remove_level (new_name);
 		if ((dir != NULL) && (g_hash_table_lookup (created_dirs, dir) == NULL)) {
-			char *dir_path;
+			GFile *directory;
 
-			dir_path = g_build_filename (data->tmp_dir, dir, NULL);
-			debug (DEBUG_INFO, "mktree %s\n", dir_path);
-			_g_path_make_directory_tree (dir_path, 0700, NULL);
+			directory = _g_file_append_path (data->tmp_dir, dir, NULL);
+			debug (DEBUG_INFO, "mktree %s\n", g_file_get_uri (directory));
+			_g_file_make_directory_tree (directory, 0700, NULL);
 
-			g_free (dir_path);
-			g_hash_table_replace (created_dirs, g_strdup (dir), "1");
+			g_hash_table_replace (created_dirs, g_strdup (dir), GINT_TO_POINTER (1));
 		}
 
 		g_free (dir);
@@ -8517,13 +8408,10 @@ fr_window_paste_from_clipboard_data (FrWindow        *window,
 
 	_archive_operation_started (window, FR_ACTION_PASTING_FILES);
 
-	file = g_file_new_for_uri (data->archive_uri);
-	fr_archive_open (file,
+	fr_archive_open (data->file,
 			 window->priv->cancellable,
 			 paste_from_archive_open_cb,
 			 window);
-
-	g_object_unref (file);
 }
 
 
@@ -8578,7 +8466,7 @@ fr_window_paste_selection (FrWindow *window,
 	g_free (utf8_path);
 
 	if (destination[0] != '/')
-		current_dir = _g_uri_build (fr_window_get_current_location (window), destination, NULL);
+		current_dir = g_build_filename (fr_window_get_current_location (window), destination, NULL);
 	else
 		current_dir = g_strdup (destination);
 	g_free (destination);
@@ -8670,14 +8558,14 @@ open_files_data_new (FrWindow *window,
 	odata->file_list = _g_string_list_dup (file_list);
 	odata->ask_application = ask_application;
 	odata->cdata = g_new0 (CommandData, 1);
-	odata->cdata->temp_dir = _g_path_get_temp_work_dir (NULL);
+	odata->cdata->temp_dir = _g_file_get_temp_work_dir (NULL);
 	odata->cdata->file_list = NULL;
 	for (scan = file_list; scan; scan = scan->next) {
-		char *file = scan->data;
-		char *filename;
+		char  *filename = scan->data;
+		GFile *file;
 
-		filename = g_build_filename (odata->cdata->temp_dir, file, NULL);
-		odata->cdata->file_list = g_list_prepend (odata->cdata->file_list, filename);
+		file = _g_file_append_path (odata->cdata->temp_dir, filename, NULL);
+		odata->cdata->file_list = g_list_prepend (odata->cdata->file_list, file);
 	}
 
 	/* Add to CommandList so the cdata is released on exit. */
@@ -8741,8 +8629,8 @@ fr_window_update_files (FrWindow *window,
 	for (scan = open_file_list; scan; scan = scan->next) {
 		OpenFile *open_file = scan->data;
 
-		file_list = g_list_prepend (file_list, open_file->path);
-		dir_list = g_list_prepend (dir_list, open_file->temp_dir);
+		file_list = g_list_prepend (file_list, g_object_ref (open_file->extracted_file));
+		dir_list = g_list_prepend (dir_list, g_object_ref (open_file->temp_dir));
 	}
 
 	_archive_operation_started (window, FR_ACTION_UPDATING_FILES);
@@ -8758,6 +8646,9 @@ fr_window_update_files (FrWindow *window,
 				      update_files_ready_cb,
 				      window);
 
+	_g_object_list_unref (dir_list);
+	_g_object_list_unref (file_list);
+
 	return TRUE;
 }
 
@@ -8770,7 +8661,6 @@ open_file_modified_cb (GFileMonitor     *monitor,
 		       gpointer          user_data)
 {
 	FrWindow *window = user_data;
-	char     *monitor_uri;
 	OpenFile *file;
 	GList    *scan;
 
@@ -8780,16 +8670,14 @@ open_file_modified_cb (GFileMonitor     *monitor,
 		return;
 	}
 
-	monitor_uri = g_file_get_uri (monitor_file);
 	file = NULL;
 	for (scan = window->priv->open_files; scan; scan = scan->next) {
 		OpenFile *test = scan->data;
-		if (_g_uri_cmp (test->extracted_uri, monitor_uri) == 0) {
+		if (_g_file_cmp_uris (test->extracted_file, monitor_file) == 0) {
 			file = test;
 			break;
 		}
 	}
-	g_free (monitor_uri);
 
 	g_return_if_fail (file != NULL);
 
@@ -8803,16 +8691,12 @@ static void
 fr_window_monitor_open_file (FrWindow *window,
 			     OpenFile *file)
 {
-	GFile *f;
-
 	window->priv->open_files = g_list_prepend (window->priv->open_files, file);
-	f = g_file_new_for_uri (file->extracted_uri);
-	file->monitor = g_file_monitor_file (f, 0, NULL, NULL);
+	file->monitor = g_file_monitor_file (file->extracted_file, 0, NULL, NULL);
 	g_signal_connect (file->monitor,
 			  "changed",
 			  G_CALLBACK (open_file_modified_cb),
 			  window);
-	g_object_unref (f);
 }
 
 
@@ -8826,11 +8710,11 @@ monitor_extracted_files (OpenFilesData *odata)
 	     scan1 && scan2;
 	     scan1 = scan1->next, scan2 = scan2->next)
 	{
-		OpenFile   *ofile;
-		const char *file = scan1->data;
-		const char *extracted_path = scan2->data;
+		char     *original_path = (char *) scan1->data;
+		GFile    *extracted_file = G_FILE (scan2->data);
+		OpenFile *ofile;
 
-		ofile = open_file_new (file, extracted_path, odata->cdata->temp_dir);
+		ofile = open_file_new (original_path, extracted_file, odata->cdata->temp_dir);
 		if (ofile != NULL)
 			fr_window_monitor_open_file (window, ofile);
 	}
@@ -8841,7 +8725,7 @@ static gboolean
 fr_window_open_extracted_files (OpenFilesData *odata)
 {
 	GList               *file_list = odata->cdata->file_list;
-	const char          *first_file;
+	GFile               *first_file;
 	const char          *first_mime_type;
 	GAppInfo            *app;
 	GList               *files_to_open = NULL;
@@ -8851,7 +8735,7 @@ fr_window_open_extracted_files (OpenFilesData *odata)
 
 	g_return_val_if_fail (file_list != NULL, FALSE);
 
-	first_file = (char*) file_list->data;
+	first_file = G_FILE (file_list->data);
 	if (first_file == NULL)
 		return FALSE;
 
@@ -8863,7 +8747,7 @@ fr_window_open_extracted_files (OpenFilesData *odata)
 		return FALSE;
 	}
 
-	first_mime_type = _g_path_get_mime_type (first_file, FALSE);
+	first_mime_type = _g_file_get_mime_type (first_file, FALSE);
 	app = g_app_info_get_default_for_type (first_mime_type, FALSE);
 
 	if (app == NULL) {
@@ -8871,28 +8755,28 @@ fr_window_open_extracted_files (OpenFilesData *odata)
 		return FALSE;
 	}
 
-	files_to_open = g_list_append (files_to_open, g_filename_to_uri (first_file, NULL, NULL));
+	files_to_open = g_list_append (files_to_open, g_file_get_uri (first_file));
 
 	if (g_app_info_supports_files (app)) {
 		GList *scan;
 
 		for (scan = file_list->next; scan; scan = scan->next) {
-			const char *path = scan->data;
+			GFile      *file = G_FILE (scan->data);
 			const char *mime_type;
 
-			mime_type = _g_path_get_mime_type (path, FALSE);
+			mime_type = _g_file_get_mime_type (file, FALSE);
 			if (mime_type == NULL)
 				continue;
 
 			if (strcmp (mime_type, first_mime_type) == 0) {
-				files_to_open = g_list_append (files_to_open, g_filename_to_uri (path, NULL, NULL));
+				files_to_open = g_list_append (files_to_open, g_file_get_uri (file));
 			}
 			else {
 				GAppInfo *app2;
 
 				app2 = g_app_info_get_default_for_type (mime_type, FALSE);
 				if (g_app_info_equal (app, app2))
-					files_to_open = g_list_append (files_to_open, g_filename_to_uri (path, NULL, NULL));
+					files_to_open = g_list_append (files_to_open, g_file_get_uri (file));
 				g_object_unref (app2);
 			}
 		}
@@ -8954,83 +8838,81 @@ fr_window_open_files (FrWindow *window,
 
 	_archive_operation_started (odata->window, FR_ACTION_EXTRACTING_FILES);
 
-	fr_archive_extract_to_local (window->archive,
-				     odata->file_list,
-				     odata->cdata->temp_dir,
-				     NULL,
-				     FALSE,
-				     TRUE,
-				     FALSE,
-				     window->priv->password,
-				     window->priv->cancellable,
-				     open_files_extract_ready_cb,
-				     odata);
+	fr_archive_extract (window->archive,
+			    odata->file_list,
+			    odata->cdata->temp_dir,
+			    NULL,
+			    FALSE,
+			    TRUE,
+			    FALSE,
+			    window->priv->password,
+			    window->priv->cancellable,
+			    open_files_extract_ready_cb,
+			    odata);
 }
 
 
 /**/
 
 
-static char*
-get_default_dir (const char *dir)
+static GFile *
+_get_default_dir (GFile *directory)
 {
-	if (! _g_path_is_temp_dir (dir))
-		return g_strdup (dir);
+	if (! _g_file_is_temp_dir (directory))
+		return g_object_ref (directory);
 	else
 		return NULL;
 }
 
 
 void
-fr_window_set_open_default_dir (FrWindow   *window,
-				const char *default_dir)
+fr_window_set_open_default_dir (FrWindow *window,
+				GFile    *default_dir)
 {
 	g_return_if_fail (window != NULL);
 	g_return_if_fail (default_dir != NULL);
 
-	if (window->priv->open_default_dir != NULL)
-		g_free (window->priv->open_default_dir);
-	window->priv->open_default_dir = get_default_dir (default_dir);
+	_g_object_unref (window->priv->open_default_dir);
+	window->priv->open_default_dir = _get_default_dir (default_dir);
 }
 
 
-const char *
+GFile *
 fr_window_get_open_default_dir (FrWindow *window)
 {
 	if (window->priv->open_default_dir == NULL)
-		return _g_uri_get_home ();
+		return _g_file_get_home ();
 	else
 		return  window->priv->open_default_dir;
 }
 
 
 void
-fr_window_set_add_default_dir (FrWindow   *window,
-			       const char *default_dir)
+fr_window_set_add_default_dir (FrWindow *window,
+			       GFile    *default_dir)
 {
 	g_return_if_fail (window != NULL);
 	g_return_if_fail (default_dir != NULL);
 
-	if (window->priv->add_default_dir != NULL)
-		g_free (window->priv->add_default_dir);
-	window->priv->add_default_dir = get_default_dir (default_dir);
+	_g_object_unref (window->priv->add_default_dir);
+	window->priv->add_default_dir = _get_default_dir (default_dir);
 }
 
 
-const char *
+GFile *
 fr_window_get_add_default_dir (FrWindow *window)
 {
 	if (window->priv->add_default_dir == NULL)
-		return _g_uri_get_home ();
+		return _g_file_get_home ();
 	else
 		return  window->priv->add_default_dir;
 }
 
 
 void
-fr_window_set_extract_default_dir (FrWindow   *window,
-				   const char *default_dir,
-				   gboolean    freeze)
+fr_window_set_extract_default_dir (FrWindow *window,
+				   GFile    *default_dir,
+				   gboolean  freeze)
 {
 	g_return_if_fail (window != NULL);
 	g_return_if_fail (default_dir != NULL);
@@ -9042,26 +8924,25 @@ fr_window_set_extract_default_dir (FrWindow   *window,
 
 	window->priv->extract_interact_use_default_dir = freeze;
 
-	if (window->priv->extract_default_dir != NULL)
-		g_free (window->priv->extract_default_dir);
-	window->priv->extract_default_dir = get_default_dir (default_dir);
+	_g_object_unref (window->priv->extract_default_dir);
+	window->priv->extract_default_dir = _get_default_dir (default_dir);
 }
 
 
-const char *
+GFile *
 fr_window_get_extract_default_dir (FrWindow *window)
 {
 	if (window->priv->extract_default_dir == NULL)
-		return _g_uri_get_home ();
+		return _g_file_get_home ();
 	else
 		return  window->priv->extract_default_dir;
 }
 
 
 void
-fr_window_set_default_dir (FrWindow   *window,
-			   const char *default_dir,
-			   gboolean    freeze)
+fr_window_set_default_dir (FrWindow *window,
+			   GFile    *default_dir,
+			   gboolean  freeze)
 {
 	g_return_if_fail (window != NULL);
 	g_return_if_fail (default_dir != NULL);
@@ -9144,30 +9025,30 @@ fr_window_exec_batch_action (FrWindow      *window,
 	case FR_BATCH_ACTION_LOAD:
 		debug (DEBUG_INFO, "[BATCH] LOAD\n");
 
-		if (! _g_uri_query_exists ((char*) action->data)) {
+		if (! g_file_query_exists (G_FILE (action->data), NULL)) {
 			GError *error = NULL;
 
-			if (! fr_window_archive_new (window, (char*) action->data, NULL))
+			if (! fr_window_archive_new (window, G_FILE (action->data), NULL))
 				error = g_error_new_literal (FR_ERROR, FR_ERROR_GENERIC, _("Archive type not supported."));
 			_archive_operation_completed (window, FR_ACTION_CREATING_NEW_ARCHIVE, error);
 
 			_g_error_free (error);
 		}
 		else
-			fr_window_archive_open (window, (char*) action->data, GTK_WINDOW (window));
+			fr_window_archive_open (window, G_FILE (action->data), GTK_WINDOW (window));
 		break;
 
 	case FR_BATCH_ACTION_ADD:
 		debug (DEBUG_INFO, "[BATCH] ADD\n");
 
-		fr_window_archive_add_dropped_items (window, (GList*) action->data);
+		fr_window_archive_add_dropped_items (window, (GList *) action->data);
 		break;
 
 	case FR_BATCH_ACTION_OPEN:
 		debug (DEBUG_INFO, "[BATCH] OPEN\n");
 
 		fr_window_push_message (window, _("Add files to an archive"));
-		dlg_batch_add_files (window, (GList*) action->data);
+		dlg_batch_add_files (window, (GList *) action->data);
 		break;
 
 	case FR_BATCH_ACTION_EXTRACT:
@@ -9176,7 +9057,7 @@ fr_window_exec_batch_action (FrWindow      *window,
 		edata = action->data;
 		fr_window_archive_extract (window,
 					   edata->file_list,
-					   edata->extract_to_dir,
+					   edata->destination,
 					   edata->base_dir,
 					   edata->skip_older,
 					   edata->overwrite,
@@ -9247,7 +9128,7 @@ fr_window_exec_batch_action (FrWindow      *window,
 
 		sdata = action->data;
 		fr_window_archive_save_as (window,
-					   sdata->uri,
+					   sdata->file,
 					   sdata->mime_type,
 					   sdata->password,
 					   sdata->encrypt_header,
@@ -9465,16 +9346,16 @@ fr_window_get_batch_title (FrWindow *window)
 
 
 void
-fr_window_set_batch__extract_here (FrWindow   *window,
-				   const char *filename)
+fr_window_set_batch__extract_here (FrWindow *window,
+				   GFile    *archive)
 {
 	g_return_if_fail (window != NULL);
-	g_return_if_fail (filename != NULL);
+	g_return_if_fail (archive != NULL);
 
 	fr_window_append_batch_action (window,
 				       FR_BATCH_ACTION_LOAD,
-				       g_strdup (filename),
-				       (GFreeFunc) g_free);
+				       g_object_ref (archive),
+				       (GFreeFunc) g_object_unref);
 	fr_window_append_batch_action (window,
 				       FR_BATCH_ACTION_EXTRACT_HERE,
 				       extract_to_data_new (NULL),
@@ -9487,21 +9368,21 @@ fr_window_set_batch__extract_here (FrWindow   *window,
 
 
 void
-fr_window_set_batch__extract (FrWindow   *window,
-			      const char *filename,
-			      const char *dest_dir)
+fr_window_set_batch__extract (FrWindow  *window,
+			      GFile     *archive,
+			      GFile     *destination)
 {
 	g_return_if_fail (window != NULL);
-	g_return_if_fail (filename != NULL);
+	g_return_if_fail (archive != NULL);
 
 	fr_window_append_batch_action (window,
 				       FR_BATCH_ACTION_LOAD,
-				       g_strdup (filename),
-				       (GFreeFunc) g_free);
-	if (dest_dir != NULL)
+				       g_object_ref (archive),
+				       (GFreeFunc) g_object_unref);
+	if (destination != NULL)
 		fr_window_append_batch_action (window,
 					       FR_BATCH_ACTION_EXTRACT,
-					       extract_to_data_new (dest_dir),
+					       extract_to_data_new (destination),
 					       (GFreeFunc) extract_data_free);
 	else
 		fr_window_append_batch_action (window,
@@ -9516,26 +9397,26 @@ fr_window_set_batch__extract (FrWindow   *window,
 
 
 void
-fr_window_set_batch__add (FrWindow   *window,
-			  const char *archive,
-			  GList      *file_list)
+fr_window_set_batch__add (FrWindow *window,
+			  GFile    *archive,
+			  GList    *file_list)
 {
-	window->priv->batch_adding_one_file = (file_list->next == NULL) && (_g_uri_query_is_file (file_list->data));
+	window->priv->batch_adding_one_file = (file_list->next == NULL) && (_g_file_query_is_file (file_list->data));
 
 	if (archive != NULL)
 		fr_window_append_batch_action (window,
 					       FR_BATCH_ACTION_LOAD,
-					       g_strdup (archive),
-					       (GFreeFunc) g_free);
+					       g_object_ref (archive),
+					       (GFreeFunc) g_object_unref);
 	else
 		fr_window_append_batch_action (window,
 					       FR_BATCH_ACTION_OPEN,
-					       file_list,
-					       NULL);
+					       _g_object_list_ref (file_list),
+					       (GFreeFunc) _g_object_list_unref);
 	fr_window_append_batch_action (window,
 				       FR_BATCH_ACTION_ADD,
-				       file_list,
-				       NULL);
+				       _g_object_list_ref (file_list),
+				       (GFreeFunc) _g_object_list_unref);
 	fr_window_append_batch_action (window,
 				       FR_BATCH_ACTION_CLOSE,
 				       NULL,
diff --git a/src/fr-window.h b/src/fr-window.h
index b44fcaa..3be82ff 100644
--- a/src/fr-window.h
+++ b/src/fr-window.h
@@ -109,44 +109,35 @@ void            fr_window_close                        (FrWindow      *window);
 /* archive operations */
 
 gboolean        fr_window_archive_new                  (FrWindow      *window,
-						        const char    *uri,
+							GFile         *file,
 						        const char    *mime_type);
 FrWindow *      fr_window_archive_open                 (FrWindow      *window,
-						        const char    *uri,
+							GFile         *file,
 						        GtkWindow     *parent);
 void            fr_window_archive_close                (FrWindow      *window);
-const char *    fr_window_get_archive_uri              (FrWindow      *window);
-const char *    fr_window_get_paste_archive_uri        (FrWindow      *window);
+GFile *         fr_window_get_archive_file             (FrWindow      *window);
+GFile *         fr_window_get_archive_file_for_paste   (FrWindow      *window);
 gboolean        fr_window_archive_is_present           (FrWindow      *window);
 void            fr_window_archive_reload               (FrWindow      *window);
 void            fr_window_archive_add_files            (FrWindow      *window,
-						        GList         *file_list, /* GFile list */
-						        gboolean       update);
-void            fr_window_archive_add_with_wildcard    (FrWindow      *window,
+							GList         *file_list, /* GFile list */
+							GFile         *base_dir,
+							gboolean       update);
+void            fr_window_archive_add_with_filter      (FrWindow      *window,
+							GFile         *base_dir,
 						        const char    *include_files,
 						        const char    *exclude_files,
 						        const char    *exclude_folders,
-						        const char    *base_dir,
 						        const char    *dest_dir,
 						        gboolean       update,
 						        gboolean       follow_links);
-void            fr_window_archive_add_directory        (FrWindow      *window,
-						        const char    *directory,
-						        const char    *base_dir,
-						        const char    *dest_dir,
-						        gboolean       update);
-void            fr_window_archive_add_items            (FrWindow      *window,
-						        GList         *dir_list,
-						        const char    *base_dir,
-						        const char    *dest_dir,
-						        gboolean       update);
 void            fr_window_archive_add_dropped_items    (FrWindow      *window,
-						        GList         *item_list);
+						        GList         *file_list);
 void            fr_window_archive_remove               (FrWindow      *window,
 						        GList         *file_list);
 void            fr_window_archive_extract              (FrWindow      *window,
 						        GList         *file_list,
-						        const char    *extract_to_dir,
+						        GFile         *destination,
 						        const char    *base_dir,
 						        gboolean       skip_older,
 						        FrOverwrite    overwrite,
@@ -233,7 +224,7 @@ void            fr_window_stop                         (FrWindow    *window);
 
 void            fr_window_action_new_archive           (FrWindow   *window);
 gboolean        fr_window_create_archive_and_continue  (FrWindow   *window,
-							const char *uri,
+							GFile      *file,
 							const char *mime_type,
 							GtkWindow  *error_dialog_parent);
 void            fr_window_action_save_as               (FrWindow   *window);
@@ -252,18 +243,18 @@ gboolean        fr_window_update_files                 (FrWindow   *window,
 						        GList      *file_list);
 void            fr_window_update_history_list          (FrWindow   *window);
 void            fr_window_set_default_dir              (FrWindow   *window,
-						        const char *default_dir,
+							GFile      *default_dir,
 						        gboolean    freeze);
 void            fr_window_set_open_default_dir         (FrWindow   *window,
-						        const char *default_dir);
-const char *    fr_window_get_open_default_dir         (FrWindow   *window);
+							GFile      *default_dir);
+GFile *         fr_window_get_open_default_dir         (FrWindow   *window);
 void            fr_window_set_add_default_dir          (FrWindow   *window,
-						        const char *default_dir);
-const char *    fr_window_get_add_default_dir          (FrWindow   *window);
+							GFile      *default_dir);
+GFile *         fr_window_get_add_default_dir          (FrWindow   *window);
 void            fr_window_set_extract_default_dir      (FrWindow   *window,
-						        const char *default_dir,
+							GFile      *default_dir,
 						        gboolean    freeze);
-const char *    fr_window_get_extract_default_dir      (FrWindow   *window);
+GFile *         fr_window_get_extract_default_dir      (FrWindow   *window);
 void            fr_window_set_toolbar_visibility       (FrWindow   *window,
 						        gboolean    value);
 void            fr_window_set_statusbar_visibility     (FrWindow   *window,
@@ -299,12 +290,12 @@ void            fr_window_stop_batch_with_error        (FrWindow     *window,
 void            fr_window_resume_batch                 (FrWindow      *window);
 gboolean        fr_window_is_batch_mode                (FrWindow      *window);
 void            fr_window_set_batch__extract           (FrWindow      *window,
-						        const char    *filename,
-						        const char    *dest_dir);
+						        GFile         *archive,
+						        GFile         *destination);
 void            fr_window_set_batch__extract_here      (FrWindow      *window,
-						        const char    *filename);
+							GFile         *archive);
 void            fr_window_set_batch__add               (FrWindow      *window,
-						        const char    *archive,
+							GFile         *archive,
 						        GList         *file_list);
 void            fr_window_destroy_with_error_dialog    (FrWindow      *window);
 void            fr_window_set_notify                   (FrWindow      *window,
diff --git a/src/gio-utils.c b/src/gio-utils.c
index a07caa5..ccdd84e 100644
--- a/src/gio-utils.c
+++ b/src/gio-utils.c
@@ -22,101 +22,115 @@
 #include <string.h>
 #include <glib.h>
 #include <gio/gio.h>
-#include "glib-utils.h"
 #include "file-utils.h"
 #include "gio-utils.h"
-
+#include "glib-utils.h"
 
 #define N_FILES_PER_REQUEST 128
 
 
-/* -- filter -- */
+/* FileInfo */
 
 
-typedef enum {
-	FILTER_DEFAULT = 0,
-	FILTER_NODOTFILES = 1 << 1,
-	FILTER_IGNORECASE = 1 << 2,
-	FILTER_NOBACKUPFILES = 1 << 3
-} FilterOptions;
+static FileInfo*
+_g_info_data_new (GFile     *file,
+		  GFileInfo *info)
+{
+	FileInfo *data;
 
+	data = g_new0 (FileInfo, 1);
+	data->file = g_file_dup (file);
+	data->info = g_file_info_dup (info);
 
-typedef struct {
-	char           *pattern;
-	FilterOptions   options;
-	GRegex        **regexps;
-} Filter;
+	return data;
+}
 
 
-static Filter *
-filter_new (const char    *pattern,
-	    FilterOptions  options)
+static void
+_g_info_data_free (FileInfo *info_data)
 {
-	Filter             *filter;
-	GRegexCompileFlags  flags;
+	if (info_data == NULL)
+		return;
+	_g_object_unref (info_data->file);
+	_g_object_unref (info_data->info);
+	g_free (info_data);
+}
 
-	filter = g_new0 (Filter, 1);
 
+static void
+_g_info_data_list_unref (GList *list)
+{
+	g_list_foreach (list, (GFunc) _g_info_data_free, NULL);
+	g_list_free (list);
+}
+
+
+/* -- filter -- */
+
+
+struct _FileFilter {
+	int      ref_count;
+	char    *pattern;
+	GRegex **regexps;
+};
+
+
+FileFilter *
+file_filter_new (const char *pattern)
+{
+	FileFilter *filter;
+
+	filter = g_new0 (FileFilter, 1);
+	filter->ref_count = 1;
 	if ((pattern != NULL) && (strcmp (pattern, "*") != 0))
 		filter->pattern = g_strdup (pattern);
 
-	filter->options = options;
-	if (filter->options & FILTER_IGNORECASE)
-		flags = G_REGEX_CASELESS;
-	else
-		flags = 0;
-	filter->regexps = _g_regexp_split_from_patterns (pattern, flags);
+	filter->regexps = _g_regexp_split_from_patterns (pattern, G_REGEX_CASELESS);
 
 	return filter;
 }
 
 
-static void
-filter_destroy (Filter *filter)
+void
+file_filter_unref (FileFilter *filter)
 {
 	if (filter == NULL)
 		return;
+	if (--filter->ref_count > 0)
+		return;
 
 	g_free (filter->pattern);
-	if (filter->regexps != NULL)
-		_g_regexp_freev (filter->regexps);
+	_g_regexp_freev (filter->regexps);
 	g_free (filter);
 }
 
 
-static gboolean
-filter_matches (Filter     *filter,
-	        const char *name)
+gboolean
+file_filter_matches (FileFilter *filter,
+		     GFile      *file)
 {
-	const char *file_name;
-	char       *utf8_name;
-	gboolean    matched;
-
-	g_return_val_if_fail (name != NULL, FALSE);
+	char     *file_name;
+	char     *utf8_name;
+	gboolean  matched;
 
-	file_name = _g_path_get_file_name (name);
-
-	if ((filter->options & FILTER_NODOTFILES)
-	    && ((file_name[0] == '.') || (strstr (file_name, "/.") != NULL)))
-		return FALSE;
-
-	if ((filter->options & FILTER_NOBACKUPFILES)
-	    && (file_name[strlen (file_name) - 1] == '~'))
-		return FALSE;
+	g_return_val_if_fail (file != NULL, FALSE);
 
 	if (filter->pattern == NULL)
 		return TRUE;
 
+	file_name = g_file_get_basename (file);
 	utf8_name = g_filename_to_utf8 (file_name, -1, NULL, NULL, NULL);
 	matched = _g_regexp_matchv (filter->regexps, utf8_name, 0);
+
 	g_free (utf8_name);
+	g_free (file_name);
 
 	return matched;
 }
 
 
-static gboolean
-filter_empty (Filter *filter)
+gboolean
+file_filter_empty (FileFilter *filter)
 {
 	return ((filter->pattern == NULL) || (strcmp (filter->pattern, "*") == 0));
 }
@@ -125,6 +139,15 @@ filter_empty (Filter *filter)
 /* -- g_directory_foreach_child -- */
 
 
+static void
+_g_info_data_freev (FileInfo **data)
+{
+	if (*data != NULL)
+		_g_info_data_free (*data);
+	*data = NULL;
+}
+
+
 typedef struct {
 	GFile                *base_directory;
 	gboolean              recursive;
@@ -136,13 +159,16 @@ typedef struct {
 
 	/* private */
 
-	GFile                *current;
+	FileInfo            *current;
 	GHashTable           *already_visited;
 	GList                *to_visit;
+	char                 *attributes;
 	GCancellable         *cancellable;
 	GFileEnumerator      *enumerator;
 	GError               *error;
 	guint                 source_id;
+	GList                *children;
+	GList                *current_child;
 } ForEachChildData;
 
 
@@ -152,14 +178,16 @@ for_each_child_data_free (ForEachChildData *fec)
 	if (fec == NULL)
 		return;
 
-	if (fec->base_directory != NULL)
-		g_object_unref (fec->base_directory);
-	if (fec->current != NULL)
-		g_object_unref (fec->current);
-	if (fec->already_visited)
+	g_object_unref (fec->base_directory);
+	if (fec->already_visited != NULL)
 		g_hash_table_destroy (fec->already_visited);
-	if (fec->to_visit != NULL)
+	_g_info_data_freev (&(fec->current));
+	g_free (fec->attributes);
+	if (fec->to_visit != NULL) {
+		g_list_foreach (fec->to_visit, (GFunc) _g_info_data_free, NULL);
 		g_list_free (fec->to_visit);
+	}
+	_g_object_unref (fec->cancellable);
 	g_free (fec);
 }
 
@@ -170,10 +198,7 @@ for_each_child_done_cb (gpointer user_data)
 	ForEachChildData *fec = user_data;
 
 	g_source_remove (fec->source_id);
-	if (fec->current != NULL) {
-		g_object_unref (fec->current);
-		fec->current = NULL;
-	}
+	_g_info_data_freev (&(fec->current));
 	if (fec->done_func)
 		fec->done_func (fec->error, fec->user_data);
 	for_each_child_data_free (fec);
@@ -192,60 +217,38 @@ for_each_child_done (ForEachChildData *fec)
 static void for_each_child_start_current (ForEachChildData *fec);
 
 
-static gboolean
-for_each_child_start_cb (gpointer user_data)
-{
-	ForEachChildData *fec = user_data;
-
-	g_source_remove (fec->source_id);
-	for_each_child_start_current (fec);
-
-	return FALSE;
-}
-
-
 static void
 for_each_child_start (ForEachChildData *fec)
 {
-	fec->source_id = g_idle_add (for_each_child_start_cb, fec);
-}
-
-
-static void
-for_each_child_set_current_uri (ForEachChildData *fec,
-				const char       *directory)
-{
-	if (fec->current != NULL)
-		g_object_unref (fec->current);
-	fec->current = g_file_new_for_uri (directory);
+	for_each_child_start_current (fec);
 }
 
 
 static void
 for_each_child_set_current (ForEachChildData *fec,
-			    GFile            *directory)
+			    FileInfo        *data)
 {
-	if (fec->current != NULL)
-		g_object_unref (fec->current);
-	fec->current = g_file_dup (directory);
+	_g_info_data_freev (&(fec->current));
+	fec->current = data;
 }
 
+
 static void
 for_each_child_start_next_sub_directory (ForEachChildData *fec)
 {
-	char *sub_directory = NULL;
+	FileInfo *child = NULL;
 
 	if (fec->to_visit != NULL) {
 		GList *tmp;
 
-		sub_directory = (char*) fec->to_visit->data;
+		child = (FileInfo *) fec->to_visit->data;
 		tmp = fec->to_visit;
 		fec->to_visit = g_list_remove_link (fec->to_visit, tmp);
 		g_list_free (tmp);
 	}
 
-	if (sub_directory != NULL) {
-		for_each_child_set_current_uri (fec, sub_directory);
+	if (child != NULL) {
+		for_each_child_set_current (fec, child);
 		for_each_child_start (fec);
 	}
 	else
@@ -255,7 +258,7 @@ for_each_child_start_next_sub_directory (ForEachChildData *fec)
 
 static void
 for_each_child_close_enumerator (GObject      *source_object,
-	              		 GAsyncResult *result,
+				 GAsyncResult *result,
 		      		 gpointer      user_data)
 {
 	ForEachChildData *fec = user_data;
@@ -278,19 +281,116 @@ for_each_child_close_enumerator (GObject      *source_object,
 }
 
 
+static void for_each_child_next_files_ready (GObject      *source_object,
+					     GAsyncResult *result,
+					     gpointer      user_data);
+
+
+static void
+for_each_child_read_next_files (ForEachChildData *fec)
+{
+	_g_object_list_unref (fec->children);
+	fec->children = NULL;
+	g_file_enumerator_next_files_async (fec->enumerator,
+					    N_FILES_PER_REQUEST,
+					    G_PRIORITY_DEFAULT,
+					    fec->cancellable,
+					    for_each_child_next_files_ready,
+					    fec);
+}
+
+
+static void for_each_child_read_current_child_metadata (ForEachChildData *fec);
+
+
+static void
+for_each_child_read_next_child_metadata (ForEachChildData *fec)
+{
+	fec->current_child = fec->current_child->next;
+	if (fec->current_child != NULL)
+		for_each_child_read_current_child_metadata (fec);
+	else
+		for_each_child_read_next_files (fec);
+}
+
+
+static void
+for_each_child_compute_child (ForEachChildData *fec,
+			      GFile            *file,
+			      GFileInfo        *info)
+{
+	if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
+		char *id;
+
+		/* avoid to visit a directory more than ones */
+
+		id = g_strdup (g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILE));
+		if (id == NULL)
+			id = g_file_get_uri (file);
+
+		if (g_hash_table_lookup (fec->already_visited, id) == NULL) {
+			g_hash_table_insert (fec->already_visited, g_strdup (id), GINT_TO_POINTER (1));
+			fec->to_visit = g_list_append (fec->to_visit, _g_info_data_new (file, info));
+		}
+
+		g_free (id);
+	}
+
+	fec->for_each_file_func (file, info, fec->user_data);
+}
+
+
+static void
+for_each_child_metadata_ready_func (GObject      *source_object,
+                		    GAsyncResult *result,
+                		    gpointer      user_data)
+{
+	ForEachChildData *fec = user_data;
+	GFile            *file;
+	GFileInfo        *info;
+	GError           *error = NULL;
+
+	file = G_FILE (source_object);
+	info = g_file_query_info_finish (file, result, &error);
+	if (info != NULL)
+		for_each_child_compute_child (fec, file, info);
+
+	for_each_child_read_next_child_metadata (fec);
+}
+
+
+static void
+for_each_child_read_current_child_metadata (ForEachChildData *fec)
+{
+	GFileInfo *child_info = fec->current_child->data;
+	GFile     *child_file;
+
+	child_file = g_file_get_child (fec->current->file, g_file_info_get_name (child_info));
+	g_file_query_info_async  (child_file,
+				  fec->attributes,
+				  G_FILE_QUERY_INFO_NONE,
+				  G_PRIORITY_DEFAULT,
+				  NULL, /* FIXME: cannot use fec->cancellable here */
+				  for_each_child_metadata_ready_func,
+				  fec);
+
+	g_object_unref (child_file);
+}
+
+
 static void
 for_each_child_next_files_ready (GObject      *source_object,
-			         GAsyncResult *result,
-			         gpointer      user_data)
+				 GAsyncResult *result,
+				 gpointer      user_data)
 {
 	ForEachChildData *fec = user_data;
-	GList            *children, *scan;
+	GList            *scan;
 
-	children = g_file_enumerator_next_files_finish (fec->enumerator,
-                                                        result,
-                                                        &(fec->error));
+	fec->children = g_file_enumerator_next_files_finish (fec->enumerator,
+							     result,
+							     &(fec->error));
 
-	if (children == NULL) {
+	if (fec->children == NULL) {
 		g_file_enumerator_close_async (fec->enumerator,
 					       G_PRIORITY_DEFAULT,
 					       fec->cancellable,
@@ -299,40 +399,20 @@ for_each_child_next_files_ready (GObject      *source_object,
 		return;
 	}
 
-	for (scan = children; scan; scan = scan->next) {
+	for (scan = fec->children; scan; scan = scan->next) {
 		GFileInfo *child_info = scan->data;
-		GFile     *f;
-		char      *uri;
+		GFile     *child_file;
 
-		f = g_file_get_child (fec->current, g_file_info_get_name (child_info));
-		uri = g_file_get_uri (f);
+		child_file = g_file_get_child (fec->current->file, g_file_info_get_name (child_info));
+		for_each_child_compute_child (fec, child_file, child_info);
 
-		if (g_file_info_get_file_type (child_info) == G_FILE_TYPE_DIRECTORY) {
-			/* avoid to visit a directory more than once */
-
-			if (g_hash_table_lookup (fec->already_visited, uri) == NULL) {
-				char *sub_directory;
-
-				sub_directory = g_strdup (uri);
-				g_hash_table_insert (fec->already_visited, sub_directory, GINT_TO_POINTER (1));
-				fec->to_visit = g_list_append (fec->to_visit, sub_directory);
-			}
-		}
-
-		fec->for_each_file_func (uri, child_info, fec->user_data);
-
-		g_free (uri);
-		g_object_unref (f);
+		g_object_unref (child_file);
 	}
 
-	g_file_enumerator_next_files_async (fec->enumerator,
-                                            N_FILES_PER_REQUEST,
-                                            G_PRIORITY_DEFAULT,
-                                            fec->cancellable,
-                                            for_each_child_next_files_ready,
-                                            fec);
+	for_each_child_read_next_files (fec);
 }
 
+
 static void
 for_each_child_ready (GObject      *source_object,
 		      GAsyncResult *result,
@@ -340,18 +420,18 @@ for_each_child_ready (GObject      *source_object,
 {
 	ForEachChildData *fec = user_data;
 
-	fec->enumerator = g_file_enumerate_children_finish (fec->current, result, &(fec->error));
+	fec->enumerator = g_file_enumerate_children_finish (G_FILE (source_object), result, &(fec->error));
 	if (fec->enumerator == NULL) {
 		for_each_child_done (fec);
 		return;
 	}
 
 	g_file_enumerator_next_files_async (fec->enumerator,
-                                            N_FILES_PER_REQUEST,
-                                            G_PRIORITY_DEFAULT,
-                                            fec->cancellable,
-                                            for_each_child_next_files_ready,
-                                            fec);
+					    N_FILES_PER_REQUEST,
+					    G_PRIORITY_DEFAULT,
+					    fec->cancellable,
+					    for_each_child_next_files_ready,
+					    fec);
 }
 
 
@@ -359,13 +439,9 @@ static void
 for_each_child_start_current (ForEachChildData *fec)
 {
 	if (fec->start_dir_func != NULL) {
-		char  *directory;
 		DirOp  op;
 
-		directory = g_file_get_uri (fec->current);
-		op = fec->start_dir_func (directory, &(fec->error), fec->user_data);
-		g_free (directory);
-
+		op = fec->start_dir_func (fec->current->file, fec->current->info, &(fec->error), fec->user_data);
 		switch (op) {
 		case DIR_OP_SKIP:
 			for_each_child_start_next_sub_directory (fec);
@@ -378,20 +454,45 @@ for_each_child_start_current (ForEachChildData *fec)
 		}
 	}
 
-	g_file_enumerate_children_async (fec->current,
-					 "standard::name,standard::type",
+	g_file_enumerate_children_async (fec->current->file,
+					 fec->attributes,
 					 fec->follow_links ? G_FILE_QUERY_INFO_NONE : G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
 					 G_PRIORITY_DEFAULT,
-                                         fec->cancellable,
+					 fec->cancellable,
 					 for_each_child_ready,
 					 fec);
 }
 
+
+static void
+directory_info_ready_cb (GObject      *source_object,
+			 GAsyncResult *result,
+			 gpointer      user_data)
+{
+	ForEachChildData *fec = user_data;
+	GFileInfo        *info;
+	FileInfo        *child;
+
+	info = g_file_query_info_finish (G_FILE (source_object), result, &(fec->error));
+	if (info == NULL) {
+		for_each_child_done (fec);
+		return;
+	}
+
+	child = _g_info_data_new (fec->base_directory, info);
+	g_object_unref (info);
+
+	for_each_child_set_current (fec, child);
+	for_each_child_start_current (fec);
+}
+
+
 /**
  * g_directory_foreach_child:
  * @directory: The directory to visit.
  * @recursive: Whether to traverse the @directory recursively.
  * @follow_links: Whether to dereference the symbolic links.
+ * @attributes: The GFileInfo attributes to read.
  * @cancellable: An optional @GCancellable object, used to cancel the process.
  * @start_dir_func: the function called for each sub-directory, or %NULL if
  *   not needed.
@@ -414,6 +515,7 @@ void
 g_directory_foreach_child (GFile                *directory,
 			   gboolean              recursive,
 			   gboolean              follow_links,
+			   const char           *attributes,
 			   GCancellable         *cancellable,
 			   StartDirCallback      start_dir_func,
 			   ForEachChildCallback  for_each_file_func,
@@ -426,10 +528,14 @@ g_directory_foreach_child (GFile                *directory,
 
 	fec = g_new0 (ForEachChildData, 1);
 
-	fec->base_directory = g_object_ref (directory);
+	fec->base_directory = g_file_dup (directory);
 	fec->recursive = recursive;
 	fec->follow_links = follow_links;
-	fec->cancellable = cancellable;
+	fec->attributes = g_strconcat ("standard::name,standard::type,id::file",
+				       (((attributes != NULL) && (strcmp (attributes, "") != 0)) ? "," : NULL),
+				       attributes,
+				       NULL);
+	fec->cancellable = _g_object_ref (cancellable);
 	fec->start_dir_func = start_dir_func;
 	fec->for_each_file_func = for_each_file_func;
 	fec->done_func = done_func;
@@ -439,410 +545,201 @@ g_directory_foreach_child (GFile                *directory,
 						      g_free,
 						      NULL);
 
-	for_each_child_set_current (fec, fec->base_directory);
-	for_each_child_start_current (fec);
+	g_file_query_info_async (fec->base_directory,
+				 fec->attributes,
+				 G_FILE_QUERY_INFO_NONE,
+				 G_PRIORITY_DEFAULT,
+				 fec->cancellable,
+				 directory_info_ready_cb,
+				 fec);
 }
 
 
-/* -- get_file_list_data -- */
+/* -- _g_file_list_query_info_async -- */
 
 
 typedef struct {
-	GList             *files;
-	GList             *dirs;
-	GFile             *directory;
-	GFile             *base_dir;
-	GCancellable      *cancellable;
-	ListReadyCallback  done_func;
-	gpointer           done_data;
-	GList             *to_visit;
-	GList             *current_dir;
-	Filter            *include_filter;
-	Filter            *exclude_filter;
-	Filter            *exclude_folders_filter;
-	guint              visit_timeout;
-} GetFileListData;
+	GList               *file_list;
+	FileListFlags        flags;
+	char                *attributes;
+	GCancellable        *cancellable;
+	FilterMatchCallback  directory_filter_func;
+	FilterMatchCallback  file_filter_func;
+	InfoReadyCallback    callback;
+	gpointer             user_data;
+	GList               *current;
+	GList               *files;
+} QueryData;
 
 
 static void
-get_file_list_data_free (GetFileListData *gfl)
+query_data_free (QueryData *query_data)
 {
-	if (gfl == NULL)
-		return;
-
-	filter_destroy (gfl->include_filter);
-	filter_destroy (gfl->exclude_filter);
-	filter_destroy (gfl->exclude_folders_filter);
-	_g_string_list_free (gfl->files);
-	_g_string_list_free (gfl->dirs);
-	_g_string_list_free (gfl->to_visit);
-	if (gfl->directory != NULL)
-		g_object_unref (gfl->directory);
-	if (gfl->base_dir != NULL)
-		g_object_unref (gfl->base_dir);
-	g_free (gfl);
+	_g_object_list_unref (query_data->file_list);
+	_g_info_data_list_unref (query_data->files);
+	_g_object_unref (query_data->cancellable);
+	g_free (query_data->attributes);
+	g_free (query_data);
 }
 
 
-/* -- g_directory_list_async -- */
+static void query_info__query_current (QueryData *query_data);
 
 
-static GList*
-get_relative_file_list (GList *rel_list,
-			GList *file_list,
-			GFile *base_dir)
+static void
+query_info__query_next (QueryData *query_data)
 {
-	GList *scan;
-
-	if (base_dir == NULL)
-		return NULL;
-
-	for (scan = file_list; scan; scan = scan->next) {
-		char  *full_path = scan->data;
-		GFile *f;
-		char  *relative_path;
-
-		f = g_file_new_for_commandline_arg (full_path);
-		relative_path = g_file_get_relative_path (base_dir, f);
-		if (relative_path != NULL)
-			rel_list = g_list_prepend (rel_list, relative_path);
-		g_object_unref (f);
-	}
-
-	return rel_list;
-}
-
-
-static GList*
-get_dir_list_from_file_list (GHashTable *h_dirs,
-			     const char *base_dir,
-			     GList      *files,
-			     gboolean    is_dir_list)
-{
-	GList *scan;
-	GList *dir_list = NULL;
-	int    base_dir_len;
-
-	if (base_dir == NULL)
-		base_dir = "";
-	base_dir_len = strlen (base_dir);
-
-	for (scan = files; scan; scan = scan->next) {
-		char *filename = scan->data;
-		char *dir_name;
-
-		if (strlen (filename) <= base_dir_len)
-			continue;
-
-		if (is_dir_list)
-			dir_name = g_strdup (filename + base_dir_len + 1);
-		else
-			dir_name = _g_path_remove_level (filename + base_dir_len + 1);
-
-		while ((dir_name != NULL) && (dir_name[0] != '\0') && (strcmp (dir_name, "/") != 0)) {
-			char *tmp;
-			char *dir;
-
-			/* avoid to insert duplicated folders */
-
-			dir = g_strconcat (base_dir, "/", dir_name, NULL);
-			if (g_hash_table_lookup (h_dirs, dir) == NULL) {
-				g_hash_table_insert (h_dirs, dir, GINT_TO_POINTER (1));
-				dir_list = g_list_prepend (dir_list, dir);
-			}
-			else
-				g_free (dir);
-
-			tmp = dir_name;
-			dir_name = _g_path_remove_level (tmp);
-			g_free (tmp);
-		}
-
-		g_free (dir_name);
-	}
-
-	return dir_list;
+	query_data->current = query_data->current->next;
+	query_info__query_current (query_data);
 }
 
 
 static void
-get_file_list_done (GError   *error,
-		    gpointer  user_data)
+query_data__done_cb (GError   *error,
+		     gpointer  user_data)
 {
-	GetFileListData *gfl = user_data;
-	GHashTable      *h_dirs;
-	GList           *scan;
-	char            *uri;
-
-	gfl->files = g_list_reverse (gfl->files);
-	gfl->dirs = g_list_reverse (gfl->dirs);
-
-	/* FIXME: delete the folders that contain only filtered out files
-	if (! filter_empty (gfl->include_filter) || (gfl->exclude_filter->pattern != NULL)) {
-		_g_string_list_free (gfl->dirs);
-		gfl->dirs = NULL;
-	}
-	*/
-
-	h_dirs = g_hash_table_new (g_str_hash, g_str_equal);
-
-	/* Always include the base directory, this way empty base
- 	 * directories are added to the archive as well.  */
-
-	if (gfl->base_dir != NULL) {
-		char *dir;
-
-		dir = g_file_get_uri (gfl->base_dir);
-		gfl->dirs = g_list_prepend (gfl->dirs, dir);
-		g_hash_table_insert (h_dirs, dir, GINT_TO_POINTER (1));
-	}
-
-	/* Add all the parent directories in gfl->files/gfl->dirs to the
-	 * gfl->dirs list, the hash table is used to avoid duplicated
-	 * entries. */
-
-	for (scan = gfl->dirs; scan; scan = scan->next)
-		g_hash_table_insert (h_dirs, (char*)scan->data, GINT_TO_POINTER (1));
-
-	uri = g_file_get_uri (gfl->base_dir);
-	gfl->dirs = g_list_concat (gfl->dirs, get_dir_list_from_file_list (h_dirs, uri, gfl->files, FALSE));
-
-	if (filter_empty (gfl->include_filter))
-		gfl->dirs = g_list_concat (gfl->dirs, get_dir_list_from_file_list (h_dirs, uri, gfl->dirs, TRUE));
-
-	g_free (uri);
-	/**/
+	QueryData *query_data = user_data;
 
-	if (error == NULL) {
-		GList *rel_files, *rel_dirs;
-
-		if (gfl->base_dir != NULL) {
-			rel_files = get_relative_file_list (NULL, gfl->files, gfl->base_dir);
-			rel_dirs = get_relative_file_list (NULL, gfl->dirs, gfl->base_dir);
-		}
-		else {
-			rel_files = gfl->files;
-			rel_dirs = gfl->dirs;
-			gfl->files = NULL;
-			gfl->dirs = NULL;
-		}
-
-		/* rel_files/rel_dirs must be deallocated in done_func */
-		gfl->done_func (rel_files, rel_dirs, NULL, gfl->done_data);
+	if (error != NULL) {
+		query_data->callback (NULL, error, query_data->user_data);
+		query_data_free (query_data);
+		return;
 	}
-	else
-		gfl->done_func (NULL, NULL, error, gfl->done_data);
 
-	g_hash_table_destroy (h_dirs);
-	get_file_list_data_free (gfl);
+	query_info__query_next (query_data);
 }
 
 
 static void
-get_file_list_for_each_file (const char *uri,
-			     GFileInfo  *info,
-			     gpointer    user_data)
+query_data__for_each_file_cb (GFile      *file,
+			      GFileInfo  *info,
+			      gpointer    user_data)
 {
-	GetFileListData *gfl = user_data;
+	QueryData *query_data = user_data;
 
-	switch (g_file_info_get_file_type (info)) {
-	case G_FILE_TYPE_REGULAR:
-		if (filter_matches (gfl->include_filter, uri))
-			if ((gfl->exclude_filter->pattern == NULL) || ! filter_matches (gfl->exclude_filter, uri))
-				gfl->files = g_list_prepend (gfl->files, g_strdup (uri));
-		break;
-	default:
-		break;
-	}
+	if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
+		return;
+	if ((query_data->flags & FILE_LIST_NO_BACKUP_FILES) && g_file_info_get_is_backup (info))
+		return;
+	if ((query_data->flags & FILE_LIST_NO_HIDDEN_FILES) && g_file_info_get_is_hidden (info))
+		return;
+	if ((query_data->file_filter_func != NULL) && query_data->file_filter_func (file, info, query_data->user_data))
+		return;
+
+	query_data->files = g_list_prepend (query_data->files, _g_info_data_new (file, info));
 }
 
 
 static DirOp
-get_file_list_start_dir (const char  *uri,
-			 GError     **error,
-			 gpointer     user_data)
+query_data__start_dir_cb (GFile       *file,
+		          GFileInfo   *info,
+		          GError     **error,
+		          gpointer     user_data)
 {
-	GetFileListData *gfl = user_data;
+	QueryData *query_data = user_data;
 
-	if ((gfl->exclude_folders_filter->pattern == NULL) || ! filter_matches (gfl->exclude_folders_filter, uri)) {
-		gfl->dirs = g_list_prepend (gfl->dirs, g_strdup (uri));
-		return DIR_OP_CONTINUE;
-	}
-	else
+	if ((query_data->flags & FILE_LIST_NO_BACKUP_FILES) && g_file_info_get_is_backup (info))
+		return DIR_OP_SKIP;
+	if ((query_data->flags & FILE_LIST_NO_HIDDEN_FILES) && g_file_info_get_is_hidden (info))
+		return DIR_OP_SKIP;
+	if ((query_data->directory_filter_func != NULL) && query_data->directory_filter_func (file, info, query_data->user_data))
 		return DIR_OP_SKIP;
-}
-
-
-void
-g_directory_list_async (const char        *directory,
-		        const char        *base_dir,
-		        gboolean           recursive,
-		        gboolean           follow_links,
-		        gboolean           no_backup_files,
-		        gboolean           no_dot_files,
-		        const char        *include_files,
-		        const char        *exclude_files,
-		        const char        *exclude_folders,
-		        gboolean           ignorecase,
-		        GCancellable      *cancellable,
-		        ListReadyCallback  done_func,
-		        gpointer           done_data)
-{
-	GetFileListData *gfl;
-	FilterOptions    filter_options;
-
-	gfl = g_new0 (GetFileListData, 1);
-	gfl->directory = g_file_new_for_commandline_arg (directory);
-	gfl->base_dir = g_file_new_for_commandline_arg (base_dir);
-	gfl->done_func = done_func;
-	gfl->done_data = done_data;
-
-	filter_options = FILTER_DEFAULT;
-	if (no_backup_files)
-		filter_options |= FILTER_NOBACKUPFILES;
-	if (no_dot_files)
-		filter_options |= FILTER_NODOTFILES;
-	if (ignorecase)
-		filter_options |= FILTER_IGNORECASE;
-	gfl->include_filter = filter_new (include_files, filter_options);
-	gfl->exclude_filter = filter_new (exclude_files, ignorecase ? FILTER_IGNORECASE : FILTER_DEFAULT);
-	gfl->exclude_folders_filter = filter_new (exclude_folders, ignorecase ? FILTER_IGNORECASE : FILTER_DEFAULT);
-
-	g_directory_foreach_child (gfl->directory,
-				   recursive,
-				   follow_links,
-				   cancellable,
-				   get_file_list_start_dir,
-				   get_file_list_for_each_file,
-				   get_file_list_done,
-				   gfl);
-}
-
-
-/* -- g_list_items_async -- */
-
-
-static void get_items_for_current_dir (GetFileListData *gfl);
-
-
-static gboolean
-get_items_for_next_dir_idle_cb (gpointer data)
-{
-	GetFileListData *gfl = data;
-
-	g_source_remove (gfl->visit_timeout);
-	gfl->visit_timeout = 0;
 
-	gfl->current_dir = g_list_next (gfl->current_dir);
-	get_items_for_current_dir (gfl);
+	query_data->files = g_list_prepend (query_data->files, _g_info_data_new (file, info));
 
-	return FALSE;
+	return DIR_OP_CONTINUE;
 }
 
 
 static void
-get_items_for_current_dir_done (GList    *files,
-			        GList    *dirs,
-			        GError   *error,
-			        gpointer  data)
+query_data_info_ready_cb (GObject      *source_object,
+                          GAsyncResult *result,
+                          gpointer      user_data)
 {
-	GetFileListData *gfl = data;
+	QueryData *query_data = user_data;
+	GError    *error = NULL;
+	GFileInfo *info;
 
-	if (error != NULL) {
-		if (gfl->done_func)
-			gfl->done_func (NULL, NULL, error, gfl->done_data);
-		_g_string_list_free (files);
-		_g_string_list_free (dirs);
-		get_file_list_data_free (gfl);
+	info = g_file_query_info_finish ((GFile *) source_object, result, &error);
+	if (info == NULL) {
+		query_data->callback (NULL, error, query_data->user_data);
+		query_data_free (query_data);
 		return;
 	}
 
-	gfl->files = g_list_concat (gfl->files, files);
-	gfl->dirs = g_list_concat (gfl->dirs, dirs);
+	if ((query_data->flags & FILE_LIST_RECURSIVE) && (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)) {
+		g_directory_foreach_child (G_FILE (query_data->current->data),
+					   TRUE,
+					   (query_data->flags & FILE_LIST_NO_FOLLOW_LINKS) == 0,
+					   query_data->attributes,
+					   query_data->cancellable,
+					   query_data__start_dir_cb,
+					   query_data__for_each_file_cb,
+					   query_data__done_cb,
+					   query_data);
+	}
+	else {
+		query_data->files = g_list_prepend (query_data->files, _g_info_data_new ((GFile *) query_data->current->data, info));
+		query_info__query_next (query_data);
+	}
 
-	gfl->visit_timeout = g_idle_add (get_items_for_next_dir_idle_cb, gfl);
+	g_object_unref (info);
 }
 
 
 static void
-get_items_for_current_dir (GetFileListData *gfl)
+query_info__query_current (QueryData *query_data)
 {
-	GFile *current_dir;
-	char  *directory_name;
-	GFile *directory_file;
-	char  *directory_uri;
-	char  *base_dir_uri;
-
-	if (gfl->current_dir == NULL) {
-		if (gfl->done_func) {
-			/* gfl->files/gfl->dirs must be deallocated in gfl->done_func */
-			gfl->done_func (gfl->files, gfl->dirs, NULL, gfl->done_data);
-			gfl->files = NULL;
-			gfl->dirs = NULL;
-		}
-		get_file_list_data_free (gfl);
+	GFileQueryInfoFlags flags;
+
+	if (query_data->current == NULL) {
+		query_data->files = g_list_reverse (query_data->files);
+		query_data->callback (query_data->files, NULL, query_data->user_data);
+		query_data_free (query_data);
 		return;
 	}
 
-	current_dir = g_file_new_for_uri ((char*) gfl->current_dir->data);
-	directory_name = g_file_get_basename (current_dir);
-	directory_file = g_file_get_child (gfl->base_dir, directory_name);
-	directory_uri = g_file_get_uri (directory_file);
-	base_dir_uri = g_file_get_uri (gfl->base_dir);
-
-	g_directory_list_all_async (directory_uri,
-				    base_dir_uri,
-				    TRUE,
-				    gfl->cancellable,
-				    get_items_for_current_dir_done,
-				    gfl);
-
-	g_free (base_dir_uri);
-	g_free (directory_uri);
-	g_object_unref (directory_file);
-	g_free (directory_name);
-	g_object_unref (current_dir);
+	flags = G_FILE_QUERY_INFO_NONE;
+	if (query_data->flags & FILE_LIST_NO_FOLLOW_LINKS)
+		flags |= G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS;
+
+	g_file_query_info_async ((GFile *) query_data->current->data,
+				 query_data->attributes,
+				 flags,
+				 G_PRIORITY_DEFAULT,
+				 query_data->cancellable,
+				 query_data_info_ready_cb,
+				 query_data);
 }
 
 
 void
-g_list_items_async (GList             *items,
-		    const char        *base_dir,
-		    GCancellable      *cancellable,
-		    ListReadyCallback  done_func,
-		    gpointer           done_data)
+_g_file_list_query_info_async (GList               *file_list,
+			       FileListFlags        flags,
+			       const char          *attributes,
+			       GCancellable        *cancellable,
+			       FilterMatchCallback  directory_filter_func,
+			       FilterMatchCallback  file_filter_func,
+			       InfoReadyCallback    ready_callback,
+			       gpointer             user_data)
 {
-	GetFileListData *gfl;
-	int              base_len;
-	GList           *scan;
-
-	g_return_if_fail (base_dir != NULL);
-
-	gfl = g_new0 (GetFileListData, 1);
-	gfl->base_dir = g_file_new_for_commandline_arg (base_dir);
-	gfl->cancellable = cancellable;
-	gfl->done_func = done_func;
-	gfl->done_data = done_data;
-
-	base_len = 0;
-	if (strcmp (base_dir, "/") != 0)
-		base_len = strlen (base_dir);
-
-	for (scan = items; scan; scan = scan->next) {
-		char *uri = scan->data;
-
-		/* FIXME: this is not async */
-		if (_g_uri_query_is_dir (uri)) {
-			gfl->to_visit = g_list_prepend (gfl->to_visit, g_strdup (uri));
-		}
-		else {
-			char *rel_path = g_uri_unescape_string (uri + base_len + 1, NULL);
-			gfl->files = g_list_prepend (gfl->files, rel_path);
-		}
-	}
-
-	gfl->current_dir = gfl->to_visit;
-	get_items_for_current_dir (gfl);
+	QueryData *query_data;
+
+	query_data = g_new0 (QueryData, 1);
+	query_data->file_list = _g_object_list_ref (file_list);
+	query_data->flags = flags;
+	query_data->attributes = g_strconcat ("standard::name,standard::type,standard::is-hidden,standard::is-backup,id::file",
+					      (((attributes != NULL) && (strcmp (attributes, "") != 0)) ? "," : NULL),
+					      attributes,
+					      NULL);
+	query_data->cancellable = _g_object_ref (cancellable);
+	query_data->directory_filter_func = directory_filter_func;
+	query_data->file_filter_func = file_filter_func;
+	query_data->callback = ready_callback;
+	query_data->user_data = user_data;
+
+	query_data->current = query_data->file_list;
+	query_info__query_current (query_data);
 }
 
 
@@ -1124,37 +1021,6 @@ g_copy_uri_async (const char            *source,
 
 
 typedef struct {
-	char      *uri;
-	GFileInfo *info;
-} ChildData;
-
-
-static ChildData*
-child_data_new (const char *uri,
-		GFileInfo  *info)
-{
-	ChildData *data;
-
-	data = g_new0 (ChildData, 1);
-	data->uri = g_strdup (uri);
-	data->info = g_file_info_dup (info);
-
-	return data;
-}
-
-
-static void
-child_data_free (ChildData *child)
-{
-	if (child == NULL)
-		return;
-	g_free (child->uri);
-	g_object_unref (child->info);
-	g_free (child);
-}
-
-
-typedef struct {
 	GFile                 *source;
 	GFile                 *destination;
 	GFileCopyFlags         flags;
@@ -1193,7 +1059,7 @@ directory_copy_data_free (DirectoryCopyData *dcd)
 		g_object_unref (dcd->current_destination);
 		dcd->current_destination = NULL;
 	}
-	g_list_foreach (dcd->to_copy, (GFunc) child_data_free, NULL);
+	g_list_foreach (dcd->to_copy, (GFunc) _g_info_data_free, NULL);
 	g_list_free (dcd->to_copy);
 	g_free (dcd);
 }
@@ -1218,21 +1084,18 @@ g_directory_copy_done (gpointer user_data)
 
 static GFile *
 get_destination_for_uri (DirectoryCopyData *dcd,
-		         const char        *uri)
+		         GFile             *file)
 {
-	GFile *f_uri;
 	GFile *destination_file;
 	char  *relative_path;
 
-	f_uri = g_file_new_for_uri (uri);
-	relative_path = g_file_get_relative_path (dcd->source, f_uri);
+	relative_path = g_file_get_relative_path (dcd->source, file);
 	if (relative_path != NULL)
 		destination_file = g_file_resolve_relative_path (dcd->destination, relative_path);
 	else
 		destination_file = g_file_dup (dcd->destination);
 
 	g_free (relative_path);
-	g_object_unref (f_uri);
 
 	return destination_file;
 }
@@ -1293,7 +1156,7 @@ g_directory_copy_child_progess_cb (goffset  current_num_bytes,
 static void
 g_directory_copy_current_child (DirectoryCopyData *dcd)
 {
-	ChildData *child;
+	FileInfo *child;
 	gboolean   async_op = FALSE;
 
 	if (dcd->current == NULL) {
@@ -1311,8 +1174,8 @@ g_directory_copy_current_child (DirectoryCopyData *dcd)
 	}
 
 	child = dcd->current->data;
-	dcd->current_source = g_file_new_for_uri (child->uri);
-	dcd->current_destination = get_destination_for_uri (dcd, child->uri);
+	dcd->current_source = g_object_ref (child->file);
+	dcd->current_destination = get_destination_for_uri (dcd, child->file);
 	if (dcd->current_destination == NULL) {
 		dcd->source_id = g_idle_add (g_directory_copy_next_child, dcd);
 		return;
@@ -1411,30 +1274,26 @@ g_directory_copy_list_ready (GError   *error,
 
 
 static void
-g_directory_copy_for_each_file (const char *uri,
-				GFileInfo  *info,
-				gpointer    user_data)
+g_directory_copy_for_each_file (GFile     *file,
+				GFileInfo *info,
+				gpointer   user_data)
 {
 	DirectoryCopyData *dcd = user_data;
 
-	dcd->to_copy = g_list_prepend (dcd->to_copy, child_data_new (uri, info));
+	dcd->to_copy = g_list_prepend (dcd->to_copy, _g_info_data_new (file, info));
 	dcd->tot_files++;
 }
 
 
 static DirOp
-g_directory_copy_start_dir (const char  *uri,
-			    GError     **error,
-			    gpointer     user_data)
+g_directory_copy_start_dir (GFile      *file,
+			    GFileInfo  *info,
+			    GError    **error,
+			    gpointer    user_data)
 {
 	DirectoryCopyData *dcd = user_data;
-	GFileInfo         *info;
-
-	info = g_file_info_new ();
-	g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
-	dcd->to_copy = g_list_prepend (dcd->to_copy, child_data_new (uri, info));
-	g_object_unref (info);
 
+	dcd->to_copy = g_list_prepend (dcd->to_copy, _g_info_data_new (file, info));
 	dcd->tot_files++;
 
 	return DIR_OP_CONTINUE;
@@ -1442,8 +1301,8 @@ g_directory_copy_start_dir (const char  *uri,
 
 
 void
-g_directory_copy_async (const char            *source,
-			const char            *destination,
+g_directory_copy_async (GFile                 *source,
+			GFile                 *destination,
 			GFileCopyFlags         flags,
 			int                    io_priority,
 			GCancellable          *cancellable,
@@ -1456,8 +1315,8 @@ g_directory_copy_async (const char            *source,
 
 	/* Creating GFile objects here will save us lot of effort in path construction */
 	dcd = g_new0 (DirectoryCopyData, 1);
-	dcd->source = g_file_new_for_commandline_arg (source);
-	dcd->destination = g_file_new_for_commandline_arg (destination);
+	dcd->source = g_object_ref (source);
+	dcd->destination = g_object_ref (destination);
 	dcd->flags = flags;
 	dcd->io_priority = io_priority;
 	dcd->cancellable = cancellable;
@@ -1469,6 +1328,7 @@ g_directory_copy_async (const char            *source,
 	g_directory_foreach_child (dcd->source,
 			           TRUE,
 			           TRUE,
+			           NULL,
 			           dcd->cancellable,
 			           g_directory_copy_start_dir,
 			           g_directory_copy_for_each_file,
diff --git a/src/gio-utils.h b/src/gio-utils.h
index 4074310..df366a4 100644
--- a/src/gio-utils.h
+++ b/src/gio-utils.h
@@ -25,7 +25,6 @@
 #include <glib.h>
 #include <gio/gio.h>
 
-/* callback types */
 
 typedef enum {
 	DIR_OP_CONTINUE,
@@ -33,56 +32,83 @@ typedef enum {
 	DIR_OP_STOP
 } DirOp;
 
-typedef DirOp (*StartDirCallback)    (const char  *uri,
-				      GError     **error,
-				      gpointer     user_data);
-typedef void (*ForEachChildCallback) (const char  *uri,
-				      GFileInfo   *info,
-				      gpointer     user_data);
-typedef void (*ForEachDoneCallback)  (GError      *error,
-				      gpointer     data);
-typedef void (*ListReadyCallback)    (GList       *files,
-				      GList       *dirs,
-				      GError      *error,
-				      gpointer     user_data);
-typedef void (*CopyProgressCallback) (goffset      current_file,
-                                      goffset      total_files,
-                                      GFile       *source,
-                                      GFile       *destination,
-                                      goffset      current_num_bytes,
-                                      goffset      total_num_bytes,
-                                      gpointer     user_data);
-typedef void (*CopyDoneCallback)     (GError      *error,
-				      gpointer     user_data);
+
+typedef enum {
+        FILE_LIST_DEFAULT = 0,
+        FILE_LIST_RECURSIVE = 1 << 0,
+        FILE_LIST_NO_FOLLOW_LINKS = 1 << 1,
+        FILE_LIST_NO_BACKUP_FILES = 1 << 2,
+        FILE_LIST_NO_HIDDEN_FILES = 1 << 3
+} FileListFlags;
+
+
+/* FileInfo */
+
+typedef struct {
+	GFile     *file;
+	GFileInfo *info;
+} FileInfo;
+
+/* FileFilter */
+
+typedef struct _FileFilter FileFilter;
+
+FileFilter *  file_filter_new        (const char        *pattern);
+void          file_filter_unref      (FileFilter        *filter);
+gboolean      file_filter_matches    (FileFilter        *filter,
+				      GFile             *file);
+gboolean      file_filter_empty      (FileFilter        *filter);
+
+/* callback types */
+
+typedef gboolean  (*FilterMatchCallback)  (GFile     *file,
+					   GFileInfo *info,
+					   gpointer   user_data);
+typedef DirOp (*StartDirCallback)    (GFile                 *directory,
+				      GFileInfo             *info,
+				      GError               **error,
+				      gpointer               user_data);
+typedef void (*ForEachChildCallback) (GFile                 *file,
+				      GFileInfo             *info,
+				      gpointer               user_data);
+typedef void (*ForEachDoneCallback)  (GError                *error,
+				      gpointer               data);
+typedef void (*ListReadyCallback)    (GList                 *files,
+				      GList                 *dirs,
+				      GError                *error,
+				      gpointer               user_data);
+typedef void (*InfoReadyCallback)    (GList                 *files, /* FileInfo list */
+				      GError                *error,
+				      gpointer               user_data);
+typedef void (*CopyProgressCallback) (goffset                current_file,
+                                      goffset                total_files,
+                                      GFile                 *source,
+                                      GFile                 *destination,
+                                      goffset                current_num_bytes,
+                                      goffset                total_num_bytes,
+                                      gpointer               user_data);
+typedef void (*CopyDoneCallback)     (GError                *error,
+				      gpointer               user_data);
 
 /* asynchronous recursive list functions */
 
 void   g_directory_foreach_child     (GFile                 *directory,
 				      gboolean               recursive,
 				      gboolean               follow_links,
+				      const char            *attributes,
 				      GCancellable          *cancellable,
 				      StartDirCallback       start_dir_func,
 				      ForEachChildCallback   for_each_file_func,
 				      ForEachDoneCallback    done_func,
 				      gpointer               user_data);
-void   g_directory_list_async        (const char            *directory,
-				      const char            *base_dir,
-				      gboolean               recursive,
-				      gboolean               follow_links,
-				      gboolean               no_backup_files,
-				      gboolean               no_dot_files,
-				      const char            *include_files,
-				      const char            *exclude_files,
-				      const char            *exclude_folders,
-				      gboolean               ignorecase,
-				      GCancellable          *cancellable,
-				      ListReadyCallback      done_func,
-				      gpointer               done_data);
-void   g_list_items_async            (GList                 *items,
-				      const char            *base_dir,
-				      GCancellable          *cancellable,
-				      ListReadyCallback      done_func,
-				      gpointer               done_data);
+void   _g_file_list_query_info_async (GList                 *file_list, /* GFile list */
+				      FileListFlags          flags,
+                     	     	      const char            *attributes,
+                     	     	      GCancellable          *cancellable,
+                     	     	      FilterMatchCallback    directory_filter_func,
+                     	     	      FilterMatchCallback    file_filter_func,
+                     	     	      InfoReadyCallback      ready_callback,
+                     	     	      gpointer               user_data);
 
 /* asynchronous copy functions */
 
@@ -122,8 +148,8 @@ void   g_copy_uri_async              (const char            *source,
 				      gpointer               progress_callback_data,
 				      CopyDoneCallback       callback,
 				      gpointer               user_data);
-void   g_directory_copy_async        (const char            *source,
-				      const char            *destination,
+void   g_directory_copy_async        (GFile                 *source,
+				      GFile                 *destination,
 				      GFileCopyFlags         flags,
 				      int                    io_priority,
 				      GCancellable          *cancellable,
diff --git a/src/glib-utils.c b/src/glib-utils.c
index 304d80b..0af5ce8 100644
--- a/src/glib-utils.c
+++ b/src/glib-utils.c
@@ -53,12 +53,30 @@ _g_object_unref (gpointer object)
 void
 _g_clear_object (gpointer p)
 {
-	gpointer *object_p = (gpointer *) p;
+	g_clear_object ((GObject **) p);
+}
 
-	if ((object_p != NULL) && (*object_p != NULL)) {
-		g_object_unref (*object_p);
-		*object_p = NULL;
-	}
+
+GList *
+_g_object_list_ref (GList *list)
+{
+	GList *new_list;
+
+	if (list == NULL)
+		return NULL;
+
+	new_list = g_list_copy (list);
+	g_list_foreach (new_list, (GFunc) g_object_ref, NULL);
+
+	return new_list;
+}
+
+
+void
+_g_object_list_unref (GList *list)
+{
+	g_list_foreach (list, (GFunc) g_object_unref, NULL);
+	g_list_free (list);
 }
 
 
@@ -724,19 +742,6 @@ _g_time_to_string (time_t time)
 /* uri/path/filename */
 
 
-char*
-_g_uri_display_basename (const char  *uri)
-{
-	char *e_name, *name;
-
-	e_name = g_filename_display_basename (uri);
-	name = g_uri_unescape_string (e_name, "");
-	g_free (e_name);
-
-	return name;
-}
-
-
 const char *
 _g_uri_get_home (void)
 {
@@ -809,13 +814,6 @@ _g_uri_get_root (const char *uri)
 }
 
 
-gboolean
-_g_uri_is_local (const char  *uri)
-{
-	return strncmp (uri, "file://", 7) == 0;
-}
-
-
 int
 _g_uri_cmp (const char *uri1,
 	    const char *uri2)
@@ -824,31 +822,10 @@ _g_uri_cmp (const char *uri1,
 }
 
 
-char *
-_g_uri_build (const char *base, ...)
-{
-	va_list     args;
-	const char *child;
-	GString    *uri;
-
-	uri = g_string_new (base);
-
-	va_start (args, base);
-        while ((child = va_arg (args, const char *)) != NULL) {
-        	if (! g_str_has_suffix (uri->str, "/") && ! g_str_has_prefix (child, "/"))
-        		g_string_append (uri, "/");
-        	g_string_append (uri, child);
-        }
-	va_end (args);
-
-	return g_string_free (uri, FALSE);
-}
-
-
 /* like g_path_get_basename but does not warn about NULL and does not
  * alloc a new string. */
 const gchar *
-_g_path_get_file_name (const gchar *file_name)
+_g_path_get_basename (const gchar *file_name)
 {
 	register char   *base;
 	register gssize  last_char;
@@ -994,15 +971,15 @@ _g_path_is_parent_of (const char *dirname,
 
 
 const char *
-_g_path_get_basename (const char *path,
-		      const char *base_dir,
-		      gboolean    junk_paths)
+_g_path_get_relative_basename (const char *path,
+			       const char *base_dir,
+			       gboolean    junk_paths)
 {
 	int         base_dir_len;
 	const char *base_path;
 
 	if (junk_paths)
-		return _g_path_get_file_name (path);
+		return _g_path_get_basename (path);
 
 	if (base_dir == NULL)
 		return (path[0] == '/') ? path + 1 : path;
@@ -1108,6 +1085,70 @@ _g_mime_type_matches (const char *mime_type,
 /* GFile */
 
 
+int
+_g_file_cmp_uris (GFile *a,
+                  GFile *b)
+{
+	char *uri_a;
+	char *uri_b;
+	int   result;
+
+	uri_a = g_file_get_uri (a);
+	uri_b = g_file_get_uri (b);
+	result = g_strcmp0 (uri_a, uri_b);
+
+	g_free (uri_b);
+	g_free (uri_a);
+
+	return result;
+}
+
+
+gboolean
+_g_file_is_local (GFile *file)
+{
+	char     *scheme;
+	gboolean  is_local;
+
+	scheme = g_file_get_uri_scheme (file);
+	is_local = strcmp (scheme, "file") == 0;
+
+	g_free (scheme);
+
+	return is_local;
+}
+
+
+GFile *
+_g_file_get_home (void)
+{
+	static GFile *file = NULL;
+
+	if (file != NULL)
+		return file;
+
+	file = g_file_new_for_path (g_get_home_dir ());
+
+	return file;
+}
+
+
+char *
+_g_file_get_display_basename (GFile *file)
+{
+	char *uri, *e_name, *name;
+
+	uri = g_file_get_uri (file);
+	e_name = g_filename_display_basename (uri);
+	name = g_uri_unescape_string (e_name, "");
+
+	g_free (e_name);
+	g_free (uri);
+
+	return name;
+}
+
+
 GFile *
 _g_file_new_home_relative (const char *partial_uri)
 {
@@ -1152,6 +1193,38 @@ _g_file_list_new_from_uri_list (GList *uris)
 }
 
 
+GFile *
+_g_file_append_path (GFile  *file,
+		     ...)
+{
+	char       *uri;
+	const char *path;
+	va_list     args;
+	GFile      *new_file;
+
+	uri = g_file_get_uri (file);
+
+	va_start (args, file);
+	while ((path = va_arg (args, const char *)) != NULL) {
+		char *escaped;
+		char *new_uri;
+
+		escaped = g_uri_escape_string (path, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
+		new_uri = g_build_filename (uri, escaped, NULL);
+		g_free (uri);
+		uri = new_uri;
+
+		g_free (escaped);
+	}
+	va_end (args);
+	new_file = g_file_new_for_uri (uri);
+
+	g_free (uri);
+
+	return new_file;
+}
+
+
 /* line parser */
 
 
diff --git a/src/glib-utils.h b/src/glib-utils.h
index 8fd3c0b..b58c934 100644
--- a/src/glib-utils.h
+++ b/src/glib-utils.h
@@ -49,6 +49,8 @@
 gpointer            _g_object_ref                  (gpointer             object);
 void                _g_object_unref                (gpointer             object);
 void                _g_clear_object                (gpointer             p);
+GList *             _g_object_list_ref             (GList               *list);
+void                _g_object_list_unref           (GList               *list);
 
 /* error */
 
@@ -119,25 +121,21 @@ char *              _g_time_to_string              (time_t               time);
 
 /* uri/path/filename */
 
-char *              _g_uri_display_basename        (const char          *uri);
 const char *        _g_uri_get_home                (void);
 char *              _g_uri_get_home_relative       (const char          *partial_uri);
 const char *        _g_uri_remove_host             (const char          *uri);
 char *              _g_uri_get_host                (const char          *uri);
 char *              _g_uri_get_root                (const char          *uri);
-gboolean            _g_uri_is_local                (const char          *uri);
 int                 _g_uri_cmp                     (const char          *uri1,
 						    const char          *uri2);
-char *              _g_uri_build                   (const char          *base,
-						    ...);
-const char *        _g_path_get_file_name          (const char          *path);
+const char *        _g_path_get_basename           (const char          *path);
 char *              _g_path_get_dir_name           (const char          *path);
 char *              _g_path_remove_level           (const char          *path);
 char *              _g_path_remove_ending_separator(const char          *path);
 char *              _g_path_remove_extension       (const char          *path);
 gboolean            _g_path_is_parent_of           (const char          *dirname,
 						    const char          *filename);
-const char *        _g_path_get_basename          (const char          *path,
+const char *        _g_path_get_relative_basename  (const char          *path,
 						    const char          *base_dir,
 						    gboolean             junk_paths);
 gboolean            _g_filename_is_hidden          (const char          *name);
@@ -150,10 +148,17 @@ gboolean            _g_mime_type_matches           (const char          *type,
 
 /* GFile */
 
+int                 _g_file_cmp_uris               (GFile               *a,
+						    GFile               *b);
+gboolean            _g_file_is_local               (GFile               *file);
+GFile *             _g_file_get_home               (void);
+char *              _g_file_get_display_basename   (GFile               *file);
 GFile *             _g_file_new_home_relative      (const char          *partial_uri);
 GList *             _g_file_list_dup               (GList               *l);
 void                _g_file_list_free              (GList               *l);
 GList *             _g_file_list_new_from_uri_list (GList               *uris);
+GFile *             _g_file_append_path            (GFile               *file,
+                                                    ...);
 
 /* functions used to parse a command output lines. */
 
diff --git a/src/main.c b/src/main.c
index c4a656d..c86655f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -248,17 +248,24 @@ fr_restore_session (EggSMClient *client)
 
 	for (; i > 0; i--) {
 		GtkWidget *window;
-		gchar *key, *archive;
+		char      *key;
+		char      *uri;
 
 		key = g_strdup_printf ("archive%d", i);
-		archive = g_key_file_get_string (state, "Session", key, NULL);
-		g_free (key);
+		uri = g_key_file_get_string (state, "Session", key, NULL);
 
 		window = fr_window_new ();
-		if (strlen (archive))
-			fr_window_archive_open (FR_WINDOW (window), archive, GTK_WINDOW (window));
+		if (strlen (uri) > 0) {
+			GFile *file;
+
+			file = g_file_new_for_uri (uri);
+			fr_window_archive_open (FR_WINDOW (window), file, GTK_WINDOW (window));
+
+			g_object_unref (file);
+		}
 
-		g_free (archive);
+		g_free (uri);
+		g_free (key);
 	}
 }
 
@@ -369,17 +376,19 @@ handle_method_call (GDBusConnection       *connection,
 		g_free (action);
 	}
 	else if (g_strcmp0 (method_name, "AddToArchive") == 0) {
-		char       *archive;
+		char       *archive_uri;
 		char      **files;
 		gboolean    use_progress_dialog;
 		int         i;
+		GFile      *file;
 		GList      *file_list = NULL;
 		GtkWidget  *window;
 
-		g_variant_get (parameters, "(s^asb)", &archive, &files, &use_progress_dialog);
+		g_variant_get (parameters, "(s^asb)", &archive_uri, &files, &use_progress_dialog);
 
+		file = g_file_new_for_uri (archive_uri);
 		for (i = 0; files[i] != NULL; i++)
-			file_list = g_list_prepend (file_list, files[i]);
+			file_list = g_list_prepend (file_list, g_file_new_for_uri (files[i]));
 		file_list = g_list_reverse (file_list);
 
 		window = fr_window_new ();
@@ -389,29 +398,34 @@ handle_method_call (GDBusConnection       *connection,
 		g_signal_connect (window, "ready", G_CALLBACK (window_ready_cb), invocation);
 
 		fr_window_new_batch (FR_WINDOW (window), _("Compress"));
-		fr_window_set_batch__add (FR_WINDOW (window), archive, file_list);
+		fr_window_set_batch__add (FR_WINDOW (window), file, file_list);
 		fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
 		fr_window_start_batch (FR_WINDOW (window));
 
-		g_free (archive);
+		g_object_unref (file);
+		_g_object_list_unref (file_list);
+		g_free (archive_uri);
 	}
 	else if (g_strcmp0 (method_name, "Compress") == 0) {
 		char      **files;
-		char       *destination;
+		char       *destination_uri;
 		gboolean    use_progress_dialog;
 		int         i;
 		GList      *file_list = NULL;
+		GFile      *destination;
 		GtkWidget  *window;
 
-		g_variant_get (parameters, "(^assb)", &files, &destination, &use_progress_dialog);
+		g_variant_get (parameters, "(^assb)", &files, &destination_uri, &use_progress_dialog);
+
+		if ((destination_uri != NULL) && (strcmp (destination_uri, "") != 0))
+			destination = g_file_new_for_uri (destination_uri);
+		else
+			destination = g_file_get_parent (G_FILE (file_list->data));
 
 		for (i = 0; files[i] != NULL; i++)
-			file_list = g_list_prepend (file_list, files[i]);
+			file_list = g_list_prepend (file_list, g_file_new_for_uri (files[i]));
 		file_list = g_list_reverse (file_list);
 
-		if ((destination == NULL) || (strcmp (destination, "") == 0))
-			destination = _g_path_remove_level (file_list->data);
-
 		window = fr_window_new ();
 		fr_window_use_progress_dialog (FR_WINDOW (window), use_progress_dialog);
 		fr_window_set_default_dir (FR_WINDOW (window), destination, TRUE);
@@ -424,20 +438,33 @@ handle_method_call (GDBusConnection       *connection,
 		fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
 		fr_window_start_batch (FR_WINDOW (window));
 
-		g_free (destination);
+		_g_object_list_unref (file_list);
+		g_object_unref (destination);
+		g_free (destination_uri);
 	}
 	else if (g_strcmp0 (method_name, "Extract") == 0) {
-		char      *archive;
-		char      *destination;
+		char      *archive_uri;
+		char      *destination_uri;
 		gboolean   use_progress_dialog;
 		GtkWidget *window;
+		GFile     *archive;
+		GFile     *destination;
+
+		g_variant_get (parameters, "(ssb)", &archive_uri, &destination_uri, &use_progress_dialog);
 
-		g_variant_get (parameters, "(ssb)", &archive, &destination, &use_progress_dialog);
+		archive = g_file_new_for_uri (archive_uri);
+		destination = g_file_new_for_uri (destination_uri);
 
 		window = fr_window_new ();
 		fr_window_use_progress_dialog (FR_WINDOW (window), use_progress_dialog);
-		if ((destination != NULL) & (strcmp (destination, "") != 0))
-			fr_window_set_default_dir (FR_WINDOW (window), destination, TRUE);
+		if ((destination_uri != NULL) & (strcmp (destination_uri, "") != 0)) {
+			GFile *file;
+
+			file = g_file_new_for_uri (destination_uri);
+			fr_window_set_default_dir (FR_WINDOW (window), file, TRUE);
+
+			g_object_unref (file);
+		}
 
 		g_signal_connect (window, "progress", G_CALLBACK (window_progress_cb), connection);
 		g_signal_connect (window, "ready", G_CALLBACK (window_ready_cb), invocation);
@@ -447,15 +474,20 @@ handle_method_call (GDBusConnection       *connection,
 		fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
 		fr_window_start_batch (FR_WINDOW (window));
 
-		g_free (destination);
-		g_free (archive);
+		g_object_unref (archive);
+		g_object_unref (destination);
+		g_free (destination_uri);
+		g_free (archive_uri);
 	}
 	else if (g_strcmp0 (method_name, "ExtractHere") == 0) {
-		char      *archive;
+		char      *uri;
+		GFile     *archive;
 		gboolean   use_progress_dialog;
 		GtkWidget *window;
 
-		g_variant_get (parameters, "(sb)", &archive, &use_progress_dialog);
+		g_variant_get (parameters, "(sb)", &uri, &use_progress_dialog);
+
+		archive = g_file_new_for_uri (uri);
 
 		window = fr_window_new ();
 		fr_window_use_progress_dialog (FR_WINDOW (window), use_progress_dialog);
@@ -468,7 +500,8 @@ handle_method_call (GDBusConnection       *connection,
 		fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
 		fr_window_start_batch (FR_WINDOW (window));
 
-		g_free (archive);
+		g_object_unref (archive);
+		g_free (uri);
 	}
 }
 
@@ -629,20 +662,6 @@ fr_application_create_option_context (void)
 }
 
 
-static char *
-_g_uri_get_from_command_line (const char *path)
-{
-	GFile *file;
-	char  *uri;
-
-	file = g_file_new_for_commandline_arg (path);
-	uri = g_file_get_uri (file);
-	g_object_unref (file);
-
-	return uri;
-}
-
-
 static int
 fr_application_command_line_finished (GApplication *application,
 				      int           status)
@@ -673,9 +692,9 @@ fr_application_command_line (GApplication            *application,
 	int              argc;
 	GOptionContext  *context;
 	GError          *error = NULL;
-	char            *extract_to_uri = NULL;
-	char            *add_to_uri = NULL;
-	char            *default_uri = NULL;
+	GFile           *extraction_destination = NULL;
+	GFile           *add_to_archive = NULL;
+	GFile           *default_directory = NULL;
 
 	argv = g_application_command_line_get_arguments (command_line, &argc);
 
@@ -720,13 +739,13 @@ fr_application_command_line (GApplication            *application,
 	}
 
 	if (arg_extract_to != NULL)
-		extract_to_uri = _g_uri_get_from_command_line (arg_extract_to);
+		extraction_destination = g_file_new_for_commandline_arg (arg_extract_to);
 
 	if (arg_add_to != NULL)
-		add_to_uri = _g_uri_get_from_command_line (arg_add_to);
+		add_to_archive = g_file_new_for_commandline_arg (arg_add_to);
 
 	if (arg_default_dir != NULL)
-		default_uri = _g_uri_get_from_command_line (arg_default_dir);
+		default_directory = g_file_new_for_commandline_arg (arg_default_dir);
 
 	if ((arg_add_to != NULL) || (arg_add == 1)) { /* Add files to an archive */
 		GtkWidget   *window;
@@ -736,22 +755,24 @@ fr_application_command_line (GApplication            *application,
 
 		window = fr_window_new ();
 
-		if (default_uri != NULL)
-			fr_window_set_default_dir (FR_WINDOW (window), default_uri, TRUE);
+		if (default_directory != NULL)
+			fr_window_set_default_dir (FR_WINDOW (window), default_directory, TRUE);
 
 		file_list = NULL;
 		while ((filename = remaining_args[i++]) != NULL)
-			file_list = g_list_prepend (file_list, _g_uri_get_from_command_line (filename));
+			file_list = g_list_prepend (file_list, g_file_new_for_commandline_arg (filename));
 		file_list = g_list_reverse (file_list);
 
 		fr_window_new_batch (FR_WINDOW (window), _("Compress"));
-		fr_window_set_batch__add (FR_WINDOW (window), add_to_uri, file_list);
+		fr_window_set_batch__add (FR_WINDOW (window), add_to_archive, file_list);
 
 		if (! arg_notify)
 			fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
 		else
 			fr_window_set_notify (FR_WINDOW (window), TRUE);
 		fr_window_start_batch (FR_WINDOW (window));
+
+		_g_object_list_unref (file_list);
 	}
 	else if ((arg_extract_to != NULL) || (arg_extract == 1) || (arg_extract_here == 1)) {
 
@@ -763,19 +784,20 @@ fr_application_command_line (GApplication            *application,
 
 		window = fr_window_new ();
 
-		if (default_uri != NULL)
-			fr_window_set_default_dir (FR_WINDOW (window), default_uri, TRUE);
+		if (default_directory != NULL)
+			fr_window_set_default_dir (FR_WINDOW (window), default_directory, TRUE);
 
 		fr_window_new_batch (FR_WINDOW (window), _("Extract archive"));
 		while ((archive = remaining_args[i++]) != NULL) {
-			char *archive_uri;
+			GFile *file;
 
-			archive_uri = _g_uri_get_from_command_line (archive);
+			file = g_file_new_for_commandline_arg (archive);
 			if (arg_extract_here == 1)
-				fr_window_set_batch__extract_here (FR_WINDOW (window), archive_uri);
+				fr_window_set_batch__extract_here (FR_WINDOW (window), file);
 			else
-				fr_window_set_batch__extract (FR_WINDOW (window), archive_uri, extract_to_uri);
-			g_free (archive_uri);
+				fr_window_set_batch__extract (FR_WINDOW (window), file, extraction_destination);
+
+			g_object_unref (file);
 		}
 		fr_window_append_batch_action (FR_WINDOW (window), FR_BATCH_ACTION_QUIT, NULL, NULL);
 
@@ -787,21 +809,21 @@ fr_application_command_line (GApplication            *application,
 		int i = 0;
 		while ((filename = remaining_args[i++]) != NULL) {
 			GtkWidget *window;
-			char      *uri;
+			GFile     *file;
 
 			window = fr_window_new ();
 			gtk_widget_show (window);
 
-			uri = _g_uri_get_from_command_line (filename);
-			fr_window_archive_open (FR_WINDOW (window), uri, GTK_WINDOW (window));
+			file = g_file_new_for_commandline_arg (filename);
+			fr_window_archive_open (FR_WINDOW (window), file, GTK_WINDOW (window));
 
-			g_free (uri);
+			g_object_unref (file);
 		}
 	}
 
-	g_free (default_uri);
-	g_free (add_to_uri);
-	g_free (extract_to_uri);
+	_g_object_unref (default_directory);
+	_g_object_unref (add_to_archive);
+	g_free (extraction_destination);
 
 	return fr_application_command_line_finished (application, EXIT_SUCCESS);
 }
diff --git a/src/open-file.c b/src/open-file.c
index 1eaf9b3..56dbed0 100644
--- a/src/open-file.c
+++ b/src/open-file.c
@@ -22,24 +22,24 @@
 #include <config.h>
 #include "open-file.h"
 #include "file-utils.h"
+#include "glib-utils.h"
 
 
-OpenFile*
-open_file_new (const char *path,
-	       const char *extracted_path,
-	       const char *temp_dir)
+OpenFile *
+open_file_new (const char *original_path,
+	       GFile      *extracted_file,
+	       GFile      *temp_dir)
 {
 	OpenFile *ofile;
 
 	ofile = g_new0 (OpenFile, 1);
-	ofile->path = g_strdup (path);
-	ofile->extracted_uri = g_filename_to_uri (extracted_path, NULL, NULL);
-	if (! _g_uri_query_exists (ofile->extracted_uri)) {
+	ofile->extracted_file = g_object_ref (extracted_file);
+	if (! g_file_query_exists (ofile->extracted_file, NULL)) {
 		open_file_free (ofile);
 		return NULL;
 	}
-	ofile->temp_dir = g_strdup (temp_dir);
-	ofile->last_modified = _g_uri_get_file_mtime (ofile->extracted_uri);
+	ofile->temp_dir = g_object_ref (temp_dir);
+	ofile->last_modified = _g_file_get_file_mtime (ofile->extracted_file);
 
 	return ofile;
 }
@@ -52,9 +52,8 @@ open_file_free (OpenFile *ofile)
 		return;
 	if (ofile->monitor != NULL)
 		g_object_unref (ofile->monitor);
-	g_free (ofile->path);
-	g_free (ofile->extracted_uri);
-	g_free (ofile->temp_dir);
+	_g_object_unref (ofile->extracted_file);
+	_g_object_unref (ofile->temp_dir);
 	g_free (ofile);
 }
 
@@ -65,9 +64,8 @@ open_file_copy (OpenFile *src)
 	OpenFile *ofile;
 
 	ofile = g_new0 (OpenFile, 1);
-	ofile->path = g_strdup (src->path);
-	ofile->extracted_uri = g_strdup (src->extracted_uri);
-	ofile->temp_dir = g_strdup (src->temp_dir);
+	ofile->extracted_file = g_object_ref (src->extracted_file);
+	ofile->temp_dir = g_object_ref (src->temp_dir);
 	ofile->last_modified = src->last_modified;
 
 	return ofile;
diff --git a/src/open-file.h b/src/open-file.h
index 51c6837..895e1a7 100644
--- a/src/open-file.h
+++ b/src/open-file.h
@@ -28,9 +28,8 @@
 #include <time.h>
 
 typedef struct {
-	char         *path;
-	char         *extracted_uri;
-	char         *temp_dir;
+	GFile        *extracted_file;
+	GFile        *temp_dir;
 	time_t        last_modified;
 	GFileMonitor *monitor;
 } OpenFile;
@@ -38,9 +37,9 @@ typedef struct {
 #define FR_TYPE_OPEN_FILE (open_file_get_type ())
 
 GType       open_file_get_type (void);
-OpenFile *  open_file_new      (const char *path,
-			        const char *extracted_path,
-			        const char *temp_dir);
+OpenFile *  open_file_new      (const char *original_path,
+			        GFile      *extracted_file,
+			        GFile      *temp_dir);
 OpenFile *  open_file_copy     (OpenFile   *src);
 void        open_file_free     (OpenFile   *ofile);
 
diff --git a/src/rar-utils.c b/src/rar-utils.c
index 3abb7ce..f110ced 100644
--- a/src/rar-utils.c
+++ b/src/rar-utils.c
@@ -111,7 +111,7 @@ rar_check_multi_volume (FrCommand *comm)
 		char   *volume_name = NULL;
 		char   *name;
 
-		name = g_filename_to_utf8 (_g_path_get_file_name (comm->filename), -1, NULL, NULL, NULL);
+		name = g_filename_to_utf8 (_g_path_get_basename (comm->filename), -1, NULL, NULL, NULL);
 
 		volume_name = get_first_volume_name (name, "^(.*\\.part)([0-9]+)(\\.rar)$", FIRST_VOLUME_IS_001);
 		if (volume_name == NULL)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]