Index: thunar/thunar-file.c =================================================================== --- thunar/thunar-file.c (revision 30378) +++ thunar/thunar-file.c (working copy) @@ -68,6 +68,7 @@ /* Additional flags associated with a ThunarFile */ #define THUNAR_FILE_IN_DESTRUCTION 0x04 +#define THUNAR_FILE_INSECURE_DESKTOP_FILE 0x05 #define THUNAR_FILE_OWNS_METAFILE_REFERENCE 0x08 #define THUNAR_FILE_OWNS_EMBLEM_NAMES 0x10 @@ -743,6 +744,7 @@ gchar *md5_hash; gchar *thumbnail_dir_path; gchar *uri = NULL; + gboolean is_secure; _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); @@ -825,8 +827,15 @@ /* use the filename as custom icon name for thumbnails */ file->custom_icon_name = g_file_get_path (file->gfile); } - else if (thunar_file_is_desktop_file (file)) + else if (thunar_file_is_desktop_file (file, &is_secure)) { + /* store weather the desktop file is secure in a flag for + * returning emblems quickly */ + if (is_secure) + file->flags &= ~THUNAR_FILE_INSECURE_DESKTOP_FILE; + else + file->flags |= THUNAR_FILE_INSECURE_DESKTOP_FILE; + /* determine the custom icon name for .desktop files */ /* query a key file for the .desktop file */ @@ -994,6 +1003,7 @@ gchar **argv = NULL; gchar *exec; gchar *directory; + gboolean is_secure; _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); _thunar_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE); @@ -1001,8 +1011,18 @@ location = g_file_get_location (file->gfile); - if (thunar_file_is_desktop_file (file)) + if (thunar_file_is_desktop_file (file, &is_secure)) { + if (!is_secure) + { + /* return an error why we don't execute this file */ + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, + _("The desktop file is in an unsecure location and " + "is not executable, please make it executable " + "in the preferences if you're sure it is safe")); + return FALSE; + } + key_file = g_file_query_key_file (file->gfile, NULL, &err); if (key_file == NULL) @@ -2056,7 +2076,7 @@ } } - return can_execute || thunar_file_is_desktop_file (file); + return can_execute || (thunar_file_is_desktop_file (file, NULL)); } @@ -2197,30 +2217,74 @@ /** * thunar_file_is_desktop_file: - * @file : a #ThunarFile. + * @file : a #ThunarFile. + * @return_secure : * - * Returns %TRUE if @file is a .desktop file, but not a .directory file. - * + * If both the function and @return_secure are %TRUE, then this file + * is secure to execute. If the function return %TRUE but @return_secure + * is %FALSE, it looks like a valid desktop file, but it's not in a + * safe location to execute or does not have the +x flag. + * * Return value: %TRUE if @file is a .desktop file. **/ gboolean -thunar_file_is_desktop_file (const ThunarFile *file) +thunar_file_is_desktop_file (const ThunarFile *file, + gboolean *is_secure) { - const gchar *content_type; - gboolean is_desktop_file = FALSE; + const gchar *content_type; + const gchar * const *data_dirs; + guint i; + gchar *path; + gboolean secure = FALSE; _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); - if (file->info == NULL) + /* only allow real .desktop files */ + if (file->info == NULL || file->gfile == NULL + || !g_str_has_suffix (thunar_file_get_basename (file), ".desktop")) return FALSE; content_type = g_file_info_get_content_type (file->info); + if (content_type != NULL + && g_content_type_is_a (content_type, "application/x-desktop")) + { + /* leave here if the user does not seem to care about a secure desktop file */ + if (is_secure == NULL) + return TRUE; - if (content_type != NULL) - is_desktop_file = g_content_type_equals (content_type, "application/x-desktop"); + if (g_file_info_get_attribute_boolean (file->info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE)) + { + /* if's always secure to execute files with the +x flag */ + secure = TRUE; + } + else + { + /* get full path to the desktop file */ + path = g_file_get_path (file->gfile); + if (G_LIKELY (path != NULL)) + { + /* look if the file is in one of the system data dirs... */ + data_dirs = g_get_system_data_dirs (); + for (i = 0; data_dirs[i] != NULL && !secure; i++) + if (g_str_has_prefix (path, data_dirs[i])) + secure = TRUE; - return is_desktop_file - && !g_str_has_suffix (thunar_file_get_basename (file), ".directory"); + /* ...or the user's data dir */ + if (!secure && g_str_has_prefix (path, g_get_user_data_dir ())) + secure = TRUE; + + /* cleanup */ + g_free (path); + } + } + + /* whether we consider this file to be safe */ + *is_secure = secure; + + return TRUE; + } + + return FALSE; } @@ -2432,6 +2496,9 @@ if (thunar_file_is_symlink (file)) emblems = g_list_prepend (emblems, THUNAR_FILE_EMBLEM_NAME_SYMBOLIC_LINK); + if (G_UNLIKELY ((file->flags & THUNAR_FILE_INSECURE_DESKTOP_FILE) != 0)) + emblems = g_list_prepend (emblems, THUNAR_FILE_EMBLEM_NAME_INSECURE); + /* determine the user ID of the file owner */ /* TODO what are we going to do here on non-UNIX systems? */ uid = file->info != NULL Index: thunar/thunar-file.h =================================================================== --- thunar/thunar-file.h (revision 30378) +++ thunar/thunar-file.h (working copy) @@ -98,6 +98,7 @@ #define THUNAR_FILE_EMBLEM_NAME_CANT_READ "emblem-noread" #define THUNAR_FILE_EMBLEM_NAME_CANT_WRITE "emblem-nowrite" #define THUNAR_FILE_EMBLEM_NAME_DESKTOP "emblem-desktop" +#define THUNAR_FILE_EMBLEM_NAME_INSECURE GTK_STOCK_DIALOG_WARNING struct _ThunarFileClass { @@ -199,7 +200,8 @@ gboolean thunar_file_is_home (const ThunarFile *file); gboolean thunar_file_is_regular (const ThunarFile *file); gboolean thunar_file_is_trashed (const ThunarFile *file); -gboolean thunar_file_is_desktop_file (const ThunarFile *file); +gboolean thunar_file_is_desktop_file (const ThunarFile *file, + gboolean *is_secure); const gchar *thunar_file_get_display_name (const ThunarFile *file); gchar *thunar_file_get_deletion_date (const ThunarFile *file, Index: thunar/thunar-properties-dialog.c =================================================================== --- thunar/thunar-properties-dialog.c (revision 30378) +++ thunar/thunar-properties-dialog.c (working copy) @@ -864,7 +864,7 @@ /* check if the icon may be changed (only for writable .desktop files) */ g_object_ref (G_OBJECT (dialog->icon_image)); gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (dialog->icon_image)), dialog->icon_image); - if (thunar_file_is_writable (dialog->file) && thunar_file_is_desktop_file (dialog->file)) + if (thunar_file_is_writable (dialog->file) && thunar_file_is_desktop_file (dialog->file, NULL)) { gtk_container_add (GTK_CONTAINER (dialog->icon_button), dialog->icon_image); gtk_widget_show (dialog->icon_button); Index: thunar/thunar-permissions-chooser.c =================================================================== --- thunar/thunar-permissions-chooser.c (revision 30378) +++ thunar/thunar-permissions-chooser.c (working copy) @@ -901,7 +901,8 @@ g_signal_handlers_block_by_func (G_OBJECT (chooser->program_button), thunar_permissions_chooser_program_toggled, chooser); g_object_set (G_OBJECT (chooser->program_button), "visible", thunar_file_is_regular (file) && (thunarx_file_info_has_mime_type (THUNARX_FILE_INFO (file), "application/x-executable") - || thunarx_file_info_has_mime_type (THUNARX_FILE_INFO (file), "application/x-shellscript")), NULL); + || thunarx_file_info_has_mime_type (THUNARX_FILE_INFO (file), "application/x-shellscript") + || thunarx_file_info_has_mime_type (THUNARX_FILE_INFO (file), "application/x-desktop")), NULL); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chooser->program_button), (mode & 0111) != 0); g_signal_handlers_unblock_by_func (G_OBJECT (chooser->program_button), thunar_permissions_chooser_program_toggled, chooser);