File nautilus-177861-copy-remote-files.diff of Package nautilus
Patch by Joe Shaw <joeshaw@novell.com>
Some .desktop launchers specify that the launched application can only
open local files ("/home/foo/document.txt"), and not remote URIs
("smb://server/share/dir/document.txt"). This makes Nautilus download
those URIs before invoking an application which only supports local
files.
Fixes https://bugzilla.novell.com/show_bug.cgi?id=177861
Index: libnautilus-private/nautilus-mime-actions.c
===================================================================
--- libnautilus-private/nautilus-mime-actions.c.orig
+++ libnautilus-private/nautilus-mime-actions.c
@@ -108,17 +108,15 @@ GnomeVFSMimeApplication *
nautilus_mime_get_default_application_for_file (NautilusFile *file)
{
GnomeVFSMimeApplication *app;
- char *uri, *mime_type;
+ char *mime_type;
if (!nautilus_mime_actions_check_if_open_with_attributes_ready (file)) {
return NULL;
}
- uri = nautilus_file_get_uri (file);
mime_type = nautilus_file_get_mime_type (file);
- app = gnome_vfs_mime_get_default_application_for_uri (uri, mime_type);
+ app = gnome_vfs_mime_get_default_application (mime_type);
- g_free (uri);
g_free (mime_type);
return app;
@@ -142,14 +140,13 @@ static GList *
get_open_with_mime_applications (NautilusFile *file)
{
char *guessed_mime_type;
- char *mime_type, *uri;
+ char *mime_type;
GList *result;
guessed_mime_type = nautilus_file_get_guessed_mime_type (file);
mime_type = nautilus_file_get_mime_type (file);
- uri = nautilus_file_get_uri (file);
- result = gnome_vfs_mime_get_all_applications_for_uri (uri, mime_type);
+ result = gnome_vfs_mime_get_all_applications (mime_type);
result = g_list_sort (result, (GCompareFunc) application_compare_by_name);
if (strcmp (guessed_mime_type, mime_type) != 0) {
@@ -168,7 +165,6 @@ get_open_with_mime_applications (Nautilu
}
g_free (mime_type);
- g_free (uri);
g_free (guessed_mime_type);
return result;
@@ -212,13 +208,12 @@ gboolean
nautilus_mime_has_any_applications_for_file (NautilusFile *file)
{
GList *apps;
- char *uri, *mime_type;
+ char *mime_type;
gboolean result;
- uri = nautilus_file_get_uri (file);
mime_type = nautilus_file_get_mime_type (file);
- apps = gnome_vfs_mime_get_all_applications_for_uri (uri, mime_type);
+ apps = gnome_vfs_mime_get_all_applications (mime_type);
apps = filter_nautilus_handler (apps);
if (apps) {
@@ -229,7 +224,6 @@ nautilus_mime_has_any_applications_for_f
}
g_free (mime_type);
- g_free (uri);
return result;
}
Index: libnautilus-private/nautilus-program-choosing.c
===================================================================
--- libnautilus-private/nautilus-program-choosing.c.orig
+++ libnautilus-private/nautilus-program-choosing.c
@@ -29,6 +29,7 @@
#include "nautilus-mime-actions.h"
#include "nautilus-global-preferences.h"
#include "nautilus-icon-factory.h"
+#include "nautilus-file-operations-progress.h"
#include <eel/eel-glib-extensions.h>
#include <eel/eel-gnome-extensions.h>
#include <eel/eel-vfs-extensions.h>
@@ -416,24 +417,16 @@ slowly_and_stupidly_obtain_timestamp (Di
-
-
-/**
- * nautilus_launch_show_file:
- *
- * Shows a file using gnome_url_show.
- *
- * @file: the file whose uri will be shown.
- * @parent_window: window to use as parent for error dialog.
- */
-void nautilus_launch_show_file (NautilusFile *file,
- GtkWindow *parent_window)
+static void
+launch_show_file (NautilusFile *file,
+ const char *uri,
+ GnomeVFSMimeApplication *application,
+ GtkWindow *parent_window)
{
GnomeVFSResult result;
- GnomeVFSMimeApplication *application;
GdkScreen *screen;
char **envp;
- char *uri, *uri_scheme;
+ char *uri_scheme;
char *error_message, *detail_message;
char *full_uri_for_display;
char *uri_for_display;
@@ -446,19 +439,6 @@ void nautilus_launch_show_file (Nautilus
startup_notify = FALSE;
#endif
- g_return_if_fail (!nautilus_file_needs_slow_mime_type (file));
-
- uri = NULL;
- if (nautilus_file_is_nautilus_link (file)) {
- uri = nautilus_file_get_activation_uri (file);
- }
-
- if (uri == NULL) {
- uri = nautilus_file_get_uri (file);
- }
-
- application = nautilus_mime_get_default_application_for_file (file);
-
screen = gtk_window_get_screen (parent_window);
envp = my_gdk_spawn_make_environment_for_screen (screen, NULL);
@@ -650,31 +630,16 @@ void nautilus_launch_show_file (Nautilus
}
g_free (uri_for_display);
-
- if (application != NULL)
- gnome_vfs_mime_application_free (application);
-
g_strfreev (envp);
- g_free (uri);
}
-/**
- * nautilus_launch_application:
- *
- * Fork off a process to launch an application with a given file as a
- * parameter. Provide a parent window for error dialogs.
- *
- * @application: The application to be launched.
- * @file: The file whose location should be passed as a parameter to the application
- * @parent_window: A window to use as the parent for any error dialogs.
- */
-void
-nautilus_launch_application (GnomeVFSMimeApplication *application,
- NautilusFile *file,
- GtkWindow *parent_window)
+static void
+launch_application (NautilusFile *file,
+ const char *uri,
+ GnomeVFSMimeApplication *application,
+ GtkWindow *parent_window)
{
GdkScreen *screen;
- char *uri;
char *uri_scheme;
GList uris;
char **envp;
@@ -684,18 +649,9 @@ nautilus_launch_application (GnomeVFSMim
SnDisplay *sn_display;
#endif
- uri = NULL;
- if (nautilus_file_is_nautilus_link (file)) {
- uri = nautilus_file_get_activation_uri (file);
- }
-
- if (uri == NULL) {
- uri = nautilus_file_get_uri (file);
- }
-
uris.next = NULL;
uris.prev = NULL;
- uris.data = uri;
+ uris.data = (gpointer) uri;
screen = gtk_window_get_screen (parent_window);
envp = my_gdk_spawn_make_environment_for_screen (screen, NULL);
@@ -802,10 +758,350 @@ nautilus_launch_application (GnomeVFSMim
break;
}
- g_free (uri);
g_strfreev (envp);
}
+typedef void (*LaunchFunc) (NautilusFile *file,
+ const char *uri,
+ GnomeVFSMimeApplication *application,
+ GtkWindow *parent_window);
+
+typedef struct {
+ LaunchFunc launch_func;
+
+ NautilusFile *file;
+ GnomeVFSURI *src_uri;
+ char *tmp_uri;
+ GnomeVFSMimeApplication *application;
+ NautilusFileOperationsProgress *progress_dialog;
+ GtkWindow *parent_window;
+ GnomeVFSAsyncHandle *handle;
+
+ gboolean set_file;
+} DownloadInfo;
+
+static void
+free_download_info (DownloadInfo *info)
+{
+ nautilus_file_unref (info->file);
+ gnome_vfs_uri_unref (info->src_uri);
+ g_free (info->tmp_uri);
+ gnome_vfs_mime_application_free (info->application);
+ g_object_unref (info->parent_window);
+ if (info->progress_dialog != NULL)
+ gtk_widget_destroy (GTK_WIDGET (info->progress_dialog));
+ g_free (info);
+}
+
+static int
+progress_update_callback (GnomeVFSAsyncHandle *handle,
+ GnomeVFSXferProgressInfo *progress_info,
+ gpointer user_data)
+{
+ DownloadInfo *download_info = user_data;
+
+ if (progress_info->bytes_total > 0) {
+ nautilus_file_operations_progress_set_total (download_info->progress_dialog,
+ 1, progress_info->bytes_total);
+
+ if (!download_info->set_file) {
+ char *short_name, *src_path, *from_text;
+
+ short_name = gnome_vfs_uri_extract_short_name (download_info->src_uri);
+ src_path = gnome_vfs_uri_extract_dirname (download_info->src_uri);
+
+ from_text = g_strdup_printf (_("%s on %s"), src_path,
+ gnome_vfs_uri_get_host_name (download_info->src_uri));
+
+ nautilus_file_operations_progress_new_file (download_info->progress_dialog,
+ _("Copying"),
+ short_name,
+ from_text,
+ "",
+ _("From"),
+ "",
+ 1,
+ progress_info->bytes_copied);
+
+ g_free (short_name);
+ g_free (src_path);
+ g_free (from_text);
+
+ download_info->set_file = TRUE;
+ }
+ }
+
+ nautilus_file_operations_progress_update_sizes (download_info->progress_dialog,
+ progress_info->bytes_copied,
+ progress_info->bytes_copied);
+
+ if (progress_info->phase == GNOME_VFS_XFER_PHASE_COMPLETED) {
+ nautilus_file_operations_progress_done (download_info->progress_dialog);
+ download_info->progress_dialog = NULL;
+
+ if (progress_info->vfs_status != GNOME_VFS_OK) {
+ eel_show_error_dialog (_("Can't Connect to Server"),
+ gnome_vfs_result_to_string (progress_info->vfs_status),
+ _("Can't Display Location"),
+ GTK_WINDOW (download_info->parent_window));
+ } else {
+ /*
+ * Mark the file as read-only to help let the user
+ * know that this is a temporary file, not the
+ * real thing.
+ */
+ chmod (download_info->tmp_uri + 7, 0400);
+
+ download_info->launch_func (download_info->file,
+ download_info->tmp_uri,
+ download_info->application,
+ download_info->parent_window);
+ }
+
+ free_download_info (download_info);
+ }
+
+ return 1;
+}
+
+static void
+handle_response_callback (GtkDialog *dialog, int response, gpointer user_data)
+{
+ DownloadInfo *info = user_data;
+
+ gnome_vfs_async_cancel (info->handle);
+ nautilus_file_operations_progress_done (info->progress_dialog);
+ info->progress_dialog = NULL;
+ free_download_info (info);
+}
+
+static void
+handle_close_callback (GtkDialog *dialog, gpointer user_data)
+{
+ DownloadInfo *info = user_data;
+
+ gnome_vfs_async_cancel (info->handle);
+ nautilus_file_operations_progress_done (info->progress_dialog);
+ info->progress_dialog = NULL;
+ free_download_info (info);
+}
+
+static GnomeVFSResult
+copy_file_locally (NautilusFile *file,
+ const char *uri,
+ GnomeVFSMimeApplication *application,
+ GtkWindow *parent_window,
+ LaunchFunc launch_func)
+{
+ char *tmp_dir, *tmptmp;
+ char *tmp_uri;
+ GnomeVFSURI *src, *dest;
+ GList *src_list, *dest_list;
+ DownloadInfo *info;
+ GnomeVFSResult result;
+
+ /*
+ * FIXME: Sigh, we have no way of cleaning this temporary
+ * directory up. We don't know the pid of the program started,
+ * so we can't track its lifecycle and clean up after it's
+ * closed.
+ */
+ tmp_dir = g_build_path (G_DIR_SEPARATOR_S, g_get_tmp_dir (), "nautilus-XXXXXX", NULL);
+ tmptmp = mkdtemp (tmp_dir);
+ result = gnome_vfs_result_from_errno ();
+
+ if (tmptmp == NULL) {
+ char *full_display_uri, *display_uri;
+ char *error_message;
+
+ g_free (tmp_dir);
+
+ full_display_uri = eel_format_uri_for_display (uri);
+ display_uri = eel_str_middle_truncate (full_display_uri,
+ MAX_URI_IN_DIALOG_LENGTH);
+ g_free (full_display_uri);
+
+ error_message = g_strdup_printf (_("Couldn't display \"%s\"."),
+ display_uri);
+ eel_show_error_dialog (error_message,
+ _("There was an error launching the application."),
+ _("Can't Display Location"), parent_window);
+ g_free (error_message);
+
+ return result;
+ }
+
+ tmp_uri = g_strconcat ("file://", tmp_dir, G_DIR_SEPARATOR_S, g_basename (uri), NULL);
+ g_free (tmp_dir);
+
+ src = gnome_vfs_uri_new (uri);
+ dest = gnome_vfs_uri_new (tmp_uri);
+
+ src_list = g_list_append (NULL, src);
+ dest_list = g_list_append (NULL, dest);
+
+ info = g_new0 (DownloadInfo, 1);
+ info->launch_func = launch_func;
+ info->file = nautilus_file_ref (file);
+ info->src_uri = gnome_vfs_uri_ref (src);
+ info->tmp_uri = tmp_uri;
+ /* Sucky strings, but we're in a string freeze */
+ info->progress_dialog = nautilus_file_operations_progress_new (_("Copying files"),
+ _("Copying files"),
+ _("From:"),
+ "", 1, 0, TRUE);
+ info->application = gnome_vfs_mime_application_copy (application);
+ info->parent_window = g_object_ref (parent_window);
+
+ gtk_window_set_transient_for (GTK_WINDOW (info->progress_dialog),
+ parent_window);
+
+ g_signal_connect (info->progress_dialog,
+ "response",
+ G_CALLBACK (handle_response_callback),
+ info);
+ g_signal_connect (info->progress_dialog,
+ "close",
+ G_CALLBACK (handle_close_callback),
+ info);
+
+ result = gnome_vfs_async_xfer (&info->handle,
+ src_list,
+ dest_list,
+ GNOME_VFS_XFER_DEFAULT,
+ GNOME_VFS_XFER_ERROR_MODE_ABORT,
+ GNOME_VFS_XFER_OVERWRITE_MODE_ABORT,
+ GNOME_VFS_PRIORITY_DEFAULT,
+ progress_update_callback, info,
+ NULL, NULL);
+
+ g_list_free (src_list);
+ g_list_free (dest_list);
+ gnome_vfs_uri_unref (src);
+ gnome_vfs_uri_unref (dest);
+
+ return result;
+}
+
+/**
+ * nautilus_launch_show_file:
+ *
+ * Shows a file using gnome_url_show.
+ *
+ * @file: the file whose uri will be shown.
+ * @parent_window: window to use as parent for error dialog.
+ */
+void
+nautilus_launch_show_file (NautilusFile *file,
+ GtkWindow *parent_window)
+{
+ char *uri;
+ GnomeVFSMimeApplication *application;
+
+ g_return_if_fail (!nautilus_file_needs_slow_mime_type (file));
+
+ uri = NULL;
+ if (nautilus_file_is_nautilus_link (file)) {
+ uri = nautilus_file_get_activation_uri (file);
+ }
+
+ if (uri == NULL) {
+ uri = nautilus_file_get_uri (file);
+ }
+
+ application = nautilus_mime_get_default_application_for_file (file);
+
+ if (g_ascii_strncasecmp (uri, "file://", 7) != 0
+ && application != NULL
+ && !gnome_vfs_mime_application_supports_uris (application)) {
+
+ GnomeVFSResult result;
+
+ result = copy_file_locally (file, uri, application, parent_window, launch_show_file);
+
+ if (result != GNOME_VFS_OK) {
+ char *full_display_uri, *display_uri;
+ char *error_message;
+
+ full_display_uri = eel_format_uri_for_display (uri);
+ display_uri = eel_str_middle_truncate (full_display_uri,
+ MAX_URI_IN_DIALOG_LENGTH);
+ g_free (full_display_uri);
+
+ error_message = g_strdup_printf (_("Couldn't display \"%s\"."),
+ display_uri);
+ eel_show_error_dialog (error_message,
+ _("There was an error launching the application."),
+ _("Can't Display Location"), parent_window);
+ g_free (error_message);
+ }
+ } else {
+ launch_show_file (file, uri, application, parent_window);
+ }
+
+ if (application != NULL) {
+ gnome_vfs_mime_application_free (application);
+ }
+
+ g_free (uri);
+}
+
+/**
+ * nautilus_launch_application:
+ *
+ * Fork off a process to launch an application with a given file as a
+ * parameter. Provide a parent window for error dialogs.
+ *
+ * @application: The application to be launched.
+ * @file: The file whose location should be passed as a parameter to the application
+ * @parent_window: A window to use as the parent for any error dialogs.
+ */
+void
+nautilus_launch_application (GnomeVFSMimeApplication *application,
+ NautilusFile *file,
+ GtkWindow *parent_window)
+{
+ char *uri;
+
+ uri = NULL;
+ if (nautilus_file_is_nautilus_link (file)) {
+ uri = nautilus_file_get_activation_uri (file);
+ }
+
+ if (uri == NULL) {
+ uri = nautilus_file_get_uri (file);
+ }
+
+ if (!g_ascii_strncasecmp (uri, "file://", 7) != 0
+ && !gnome_vfs_mime_application_supports_uris (application)) {
+
+ GnomeVFSResult result;
+
+ result = copy_file_locally (file, uri, application, parent_window, launch_application);
+
+ if (result != GNOME_VFS_OK) {
+ char *full_display_uri, *display_uri;
+ char *error_message;
+
+ full_display_uri = eel_format_uri_for_display (uri);
+ display_uri = eel_str_middle_truncate (full_display_uri,
+ MAX_URI_IN_DIALOG_LENGTH);
+ g_free (full_display_uri);
+
+ error_message = g_strdup_printf (_("Couldn't display \"%s\"."),
+ display_uri);
+ eel_show_error_dialog (error_message,
+ _("There was an error launching the application."),
+ _("Can't Display Location"), parent_window);
+ g_free (error_message);
+ }
+ } else {
+ launch_application (file, uri, application, parent_window);
+ }
+
+ g_free (uri);
+}
+
/**
* nautilus_launch_application_from_command:
*