File use-file-metadata-for-trusting-desktop-files.patch of Package nautilus.8242

diff --git a/libnautilus-private/nautilus-directory-async.c b/libnautilus-private/nautilus-directory-async.c
index 358dfb4..9eeb098 100644
--- a/libnautilus-private/nautilus-directory-async.c
+++ b/libnautilus-private/nautilus-directory-async.c
@@ -31,6 +31,7 @@
 #include "nautilus-global-preferences.h"
 #include "nautilus-link.h"
 #include "nautilus-profile.h"
+#include "nautilus-metadata.h"
 #include <eel/eel-glib-extensions.h>
 #include <gtk/gtk.h>
 #include <libxml/parser.h>
@@ -3229,12 +3230,18 @@ is_link_trusted (NautilusFile *file,
 {
 	GFile *location;
 	gboolean res;
+    g_autofree gchar* trusted = NULL;
+
 	
 	if (!is_launcher) {
 		return TRUE;
 	}
 	
-	if (nautilus_file_can_execute (file)) {
+    trusted = nautilus_file_get_metadata (file,
+                                          NAUTILUS_METADATA_KEY_DESKTOP_FILE_TRUSTED,
+                                          NULL);
+
+    if (nautilus_file_can_execute (file) && trusted != NULL) {
 		return TRUE;
 	}
 
diff --git a/libnautilus-private/nautilus-file-operations.c b/libnautilus-private/nautilus-file-operations.c
index c0b9305..451af01 100644
--- a/libnautilus-private/nautilus-file-operations.c
+++ b/libnautilus-private/nautilus-file-operations.c
@@ -192,10 +192,10 @@ typedef struct {
 #define COPY_FORCE _("Copy _Anyway")
 
 static void
-mark_desktop_file_trusted (CommonJob *common,
-			   GCancellable *cancellable,
-			   GFile *file,
-			   gboolean interactive);
+mark_desktop_file_executable (CommonJob *common,
+                              GCancellable *cancellable,
+                              GFile *file,
+                              gboolean interactive);
 
 static gboolean
 is_all_button_text (const char *button_text)
@@ -4699,7 +4699,7 @@ copy_move_file (CopyMoveJob *copy_job,
 		if (copy_job->desktop_location != NULL &&
 		    g_file_equal (copy_job->desktop_location, dest_dir) &&
 		    is_trusted_desktop_file (src, job->cancellable)) {
-			mark_desktop_file_trusted (job,
+            mark_desktop_file_executable (job,
 						   job->cancellable,
 						   dest,
 						   FALSE);
@@ -6971,7 +6971,7 @@ nautilus_file_operations_empty_trash (GtkWidget *parent_view)
 }
 
 static void
-mark_trusted_task_done (GObject *source_object,
+mark_desktop_file_executable_task_done (GObject *source_object,
                         GAsyncResult *res,
                         gpointer user_data)
 {
@@ -6990,91 +6990,19 @@ mark_trusted_task_done (GObject *source_object,
 #define TRUSTED_SHEBANG "#!/usr/bin/env xdg-open\n"
 
 static void
-mark_desktop_file_trusted (CommonJob *common,
+mark_desktop_file_executable (CommonJob *common,
 			   GCancellable *cancellable,
 			   GFile *file,
 			   gboolean interactive)
 {
-	char *contents, *new_contents;
-	gsize length, new_length;
 	GError *error;
 	guint32 current_perms, new_perms;
 	int response;
 	GFileInfo *info;
 	
  retry:
-	error = NULL;
-	if (!g_file_load_contents (file,
-				  cancellable,
-				  &contents, &length,
-				  NULL, &error)) {
-		if (interactive) {
-			response = run_error (common,
-					      g_strdup (_("Unable to mark launcher trusted (executable)")),
-					      error->message,
-					      NULL,
-					      FALSE,
-					      CANCEL, RETRY,
-					      NULL);
-		} else {
-			response = 0;
-		}
-		
-
-		if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
-			abort_job (common);
-		} else if (response == 1) {
-			goto retry;
-		} else {
-			g_assert_not_reached ();
-		}
-
-		goto out;
-	}
-
-	if (!g_str_has_prefix (contents, "#!")) {
-		new_length = length + strlen (TRUSTED_SHEBANG);
-		new_contents = g_malloc (new_length);
-		
-		strcpy (new_contents, TRUSTED_SHEBANG);
-		memcpy (new_contents + strlen (TRUSTED_SHEBANG),
-			contents, length);
-		
-		if (!g_file_replace_contents (file,
-					      new_contents,
-					      new_length,
-					      NULL,
-					      FALSE, 0,
-					      NULL, cancellable, &error)) {
-			g_free (contents);
-			g_free (new_contents);
-			
-			if (interactive) {
-				response = run_error (common,
-						      g_strdup (_("Unable to mark launcher trusted (executable)")),
-						      error->message,
-						      NULL,
-						      FALSE,
-						      CANCEL, RETRY,
-						      NULL);
-			} else {
-				response = 0;
-			}
 
-			if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) {
-				abort_job (common);
-			} else if (response == 1) {
-				goto retry;
-			} else {
-				g_assert_not_reached ();
-			}
-			
-			goto out;
-		}
-		g_free (new_contents);
-		
-	}
-	g_free (contents);
+    error = NULL;
 	
 	info = g_file_query_info (file,
 				  G_FILE_ATTRIBUTE_STANDARD_TYPE","
@@ -7148,10 +7076,10 @@ mark_desktop_file_trusted (CommonJob *common,
 }
 
 static void
-mark_trusted_task_thread_func (GTask *task,
-                               gpointer source_object,
-                               gpointer task_data,
-                               GCancellable *cancellable)
+mark_desktop_file_executable_task_thread_func (GTask *task,
+                                               gpointer source_object,
+                                               gpointer task_data,
+                                               GCancellable *cancellable)
 {
 	MarkTrustedJob *job = task_data;
 	CommonJob *common;
@@ -7160,18 +7088,18 @@ mark_trusted_task_thread_func (GTask *task,
 	
 	nautilus_progress_info_start (job->common.progress);
 
-	mark_desktop_file_trusted (common,
-				   cancellable,
-				   job->file,
-				   job->interactive);
+    mark_desktop_file_executable (common,
+                                  cancellable,
+                                  job->file,
+                                  job->interactive);
 }
 
 void
-nautilus_file_mark_desktop_file_trusted (GFile *file,
-					 GtkWindow *parent_window,
-					 gboolean interactive,
-					 NautilusOpCallback done_callback,
-					 gpointer done_callback_data)
+nautilus_file_mark_desktop_file_executable (GFile *file,
+                                            GtkWindow *parent_window,
+                                            gboolean interactive,
+                                            NautilusOpCallback done_callback,
+                                            gpointer done_callback_data)
 {
 	GTask *task;
 	MarkTrustedJob *job;
@@ -7182,9 +7110,9 @@ nautilus_file_mark_desktop_file_trusted (GFile *file,
 	job->done_callback = done_callback;
 	job->done_callback_data = done_callback_data;
 
-	task = g_task_new (NULL, NULL, mark_trusted_task_done, job);
+    task = g_task_new (NULL, NULL, mark_desktop_file_executable_task_done, job);
 	g_task_set_task_data (task, job, NULL);
-	g_task_run_in_thread (task, mark_trusted_task_thread_func);
+    g_task_run_in_thread (task, mark_desktop_file_executable_task_thread_func);
 	g_object_unref (task);
 }
 
diff --git a/libnautilus-private/nautilus-file-operations.h b/libnautilus-private/nautilus-file-operations.h
index 38b714f..7d61667 100644
--- a/libnautilus-private/nautilus-file-operations.h
+++ b/libnautilus-private/nautilus-file-operations.h
@@ -143,7 +143,7 @@ void nautilus_file_operations_link      (GList                *files,
 					 GtkWindow            *parent_window,
 					 NautilusCopyCallback  done_callback,
 					 gpointer              done_callback_data);
-void nautilus_file_mark_desktop_file_trusted (GFile           *file,
+void nautilus_file_mark_desktop_file_executable (GFile           *file,
 					      GtkWindow        *parent_window,
 					      gboolean          interactive,
 					      NautilusOpCallback done_callback,
diff --git a/libnautilus-private/nautilus-metadata.c b/libnautilus-private/nautilus-metadata.c
index 4032a08..5522ee5 100644
--- a/libnautilus-private/nautilus-metadata.c
+++ b/libnautilus-private/nautilus-metadata.c
@@ -52,6 +52,7 @@ static char *used_metadata_names[] = {
   NAUTILUS_METADATA_KEY_CUSTOM_ICON_NAME,
   NAUTILUS_METADATA_KEY_SCREEN,
   NAUTILUS_METADATA_KEY_EMBLEMS,
+  NAUTILUS_METADATA_KEY_DESKTOP_FILE_TRUSTED,
   NULL
 };
 
diff --git a/libnautilus-private/nautilus-metadata.h b/libnautilus-private/nautilus-metadata.h
index 511160d..7807a84 100644
--- a/libnautilus-private/nautilus-metadata.h
+++ b/libnautilus-private/nautilus-metadata.h
@@ -67,6 +67,7 @@
 #define NAUTILUS_METADATA_KEY_CUSTOM_ICON_NAME                	"custom-icon-name"
 #define NAUTILUS_METADATA_KEY_SCREEN				"screen"
 #define NAUTILUS_METADATA_KEY_EMBLEMS				"emblems"
+#define NAUTILUS_METADATA_KEY_DESKTOP_FILE_TRUSTED  "trusted"
 
 guint nautilus_metadata_get_id (const char *metadata);
 
diff --git a/src/nautilus-mime-actions.c b/src/nautilus-mime-actions.c
index b5e77a1..b6661c4 100644
--- a/src/nautilus-mime-actions.c
+++ b/src/nautilus-mime-actions.c
@@ -45,6 +45,7 @@
 #include <libnautilus-private/nautilus-desktop-icon-file.h>
 #include <libnautilus-private/nautilus-global-preferences.h>
 #include <libnautilus-private/nautilus-signaller.h>
+#include <libnautilus-private/nautilus-metadata.h>
 
 #define DEBUG_FLAG NAUTILUS_DEBUG_MIME
 #include <libnautilus-private/nautilus-debug.h>
@@ -237,7 +238,6 @@ struct {
 #define RESPONSE_RUN 1000
 #define RESPONSE_DISPLAY 1001
 #define RESPONSE_RUN_IN_TERMINAL 1002
-#define RESPONSE_MARK_TRUSTED 1003
 
 #define SILENT_WINDOW_OPEN_LIMIT 5
 #define SILENT_OPEN_LIMIT 5
@@ -1413,20 +1413,33 @@ untrusted_launcher_response_callback (GtkDialog *dialog,
 	GFile *file;
 	
 	switch (response_id) {
-	case RESPONSE_RUN:
+    case GTK_RESPONSE_OK:
+        file = nautilus_file_get_location (parameters->file);
+
+        /* We need to do this in order to prevent malicious desktop files
+         * with the executable bit already set.
+         * See https://bugzilla.gnome.org/show_bug.cgi?id=777991
+         */
+        nautilus_file_set_metadata (parameters->file, NAUTILUS_METADATA_KEY_DESKTOP_FILE_TRUSTED,
+                                    NULL,
+                                    "yes");
+
+        nautilus_file_mark_desktop_file_executable (file,
+                                                    parameters->parent_window,
+                                                    TRUE,
+                                                    NULL, NULL);
+
+        /* Need to force a reload of the attributes so is_trusted is marked
+         * correctly. Not sure why the general monitor doesn't fire in this
+         * case when setting the metadata
+         */
+        nautilus_file_invalidate_all_attributes (parameters->file);
 		screen = gtk_widget_get_screen (GTK_WIDGET (parameters->parent_window));
 		uri = nautilus_file_get_uri (parameters->file);
 		DEBUG ("Launching untrusted launcher %s", uri);
 		nautilus_launch_desktop_file (screen, uri, NULL,
 					      parameters->parent_window);
 		g_free (uri);
-		break;
-	case RESPONSE_MARK_TRUSTED:
-		file = nautilus_file_get_location (parameters->file);
-		nautilus_file_mark_desktop_file_trusted (file,
-							 parameters->parent_window,
-							 TRUE, 
-							 NULL, NULL);
 		g_object_unref (file);
 		break;
 	default:
@@ -1477,14 +1490,12 @@ activate_desktop_file (ActivateParameters *parameters,
 			      "secondary-text", secondary,
 			      NULL);
 		gtk_dialog_add_button (GTK_DIALOG (dialog),
-				       _("_Launch Anyway"), RESPONSE_RUN);
+                       _("_Cancel"), GTK_RESPONSE_CANCEL);
+        gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
 		if (nautilus_file_can_set_permissions (file)) {
 			gtk_dialog_add_button (GTK_DIALOG (dialog),
-					       _("Mark as _Trusted"), RESPONSE_MARK_TRUSTED);
+                           _("Trust and _Launch"), GTK_RESPONSE_OK);
 		}
-		gtk_dialog_add_button (GTK_DIALOG (dialog),
-				       _("_Cancel"), GTK_RESPONSE_CANCEL);
-		gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
 
 		g_signal_connect (dialog, "response",
 				  G_CALLBACK (untrusted_launcher_response_callback),
openSUSE Build Service is sponsored by