diff --git a/ChangeLog b/ChangeLog index a5f2c6c06fdc09055822be715c999541f66a548e..18c19e4008730d62ac0a4ac20e04999b985de056 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,37 @@ +2005-08-28 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.{c,h}, thunar/thunar-local-file.c, + thunar/thunar-standard-view.c: Rename can_execute(), can_read() and + can_write() to is_executable(), is_readable() and is_writable() to + get consistent naming. + * thunar-vfs/thunar-vfs-info.{c,h}: Add THUNAR_VFS_FILE_FLAGS_EXECUTABLE + to the ThunarVfsFileFlags, which will be set if a ThunarVfsInfo + can be executed, either as regular binary or as .desktop file. + * thunar-vfs/thunar-vfs-mime-application.c, + thunar-vfs/thunar-vfs-sysdep.{c,h}: Move the Exec parsing code from + ThunarVfsMimeApplication to thunar-vfs-sysdep, so it can be used by + other modules as well. + * thunar-vfs/thunar-vfs-info.{c,h}, thunar-vfs/thunar-vfs.symbols: Add + new method thunar_vfs_info_execute(), which is used to execute + files with a list of URIs. These method can handle both regular + executable files as well as .desktop files. + * thunar/thunar-file.{c,h}, thunar/thunar-launcher.c, + thunar/thunar-local-file.c: Add support to execute files that are + marked as executable by the ThunarVfsInfo module. + * thunar-vfs/thunar-vfs-mime-database.c + (thunar_vfs_mime_database_get_info_locked), + (thunar_vfs_mime_database_get_infos_for_info_locked): Be sure to + always unalias MIME-types prior to returning them from the mime + database instance. This way we don't need to care for unaliasing + when determining the MIME-type comment or MIME-type icon. + * thunar-vfs/thunar-vfs-mime-database.{c,h}, + thunar-vfs/thunar-vfs.symbols: Add new method + thunar_vfs_mime_database_get_infos_for_info() to the public API, to + allow other components to access the subclassing information. + * FAQ, Makefile.am: Add initial items for the list of frequently asked + questions. + * TODO: Remove obsolete items. + 2005-08-27 Benedikt Meurer <benny@xfce.org> * thunar-vfs/thunar-vfs-info.{c,h}: Add support to pass hints from the diff --git a/FAQ b/FAQ new file mode 100644 index 0000000000000000000000000000000000000000..c4faefeeed4e2a3e1f0299afb29427b361ce40b8 --- /dev/null +++ b/FAQ @@ -0,0 +1,24 @@ +This file contains a list of frequently asked questions about Thunar and the +appropriate answers to these questions. + + +1. What is Thunar? +================== + + Thunar is a fast and easy-to-use file manager for the X Window System, with a + special focus on the Xfce Desktop Environment. + + +2. Why doesn't Thunar execute files marked as executable? +========================================================= + + For security reasons Thunar only executes files of type application/x-desktop, + application/x-executable and application/x-shellscript. For desktop files + the execution feature will only be enabled if the desktop file is of type + Application and a valid Exec line is given. For the other types the feature + is available if the file is marked executable for the current user. + + Also note that for application/x-executable and application/x-shellscript, the + types of the file don't really need to match these types exactly, but it is + suffice if the detected type has a parent that matches one of the two types + listed above, or if the MIME-type is an alias for one of the above. diff --git a/Makefile.am b/Makefile.am index 5cbdcd8b745164f5c82ffdd0a026e23bb14b7616..df7419412131ebd97653a2fb4cec3475329383fc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -25,6 +25,7 @@ desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) @INTLTOOL_DESKTOP_RULE@ EXTRA_DIST = \ + FAQ \ HACKING \ intltool-extract.in \ intltool-merge.in \ diff --git a/TODO b/TODO index 683176e193b6db78ff0fa0932aca846279d24cae..ae170099e6c15c02414a32c2a4521ad3539f94c4 100644 --- a/TODO +++ b/TODO @@ -8,9 +8,6 @@ Important for Thunar 1.0 - We need a way to "refresh" folders after a "Cut"-operation with Nautilus. With local folders - with not many files inside - the move is too fast! - - ThunarVfsURI should have it's own parameter specification, that - can be used for GValue handling. - - The ThunarTrashFile constructor needs some rework, as it's currently mostly brain-dead. Should probably be splitted into several functions. In addition the ThunarTrashFile should enable the monitoring on the @@ -70,8 +67,3 @@ Important for Thunar 1.0 development of Thunar core modules is to be done, and what material each developer in addition to the source code. - - The ThunarVfsMonitor framework must be designed and implemented. - The list of supported backends for 1.0 is kqueue, fam and - the stat-thread. Backend technologies must be thread-safe. If - there's a lot of time or manpower in the end, additional - backends can be added, as long as they fit into the framework. diff --git a/thunar-vfs/thunar-vfs-info.c b/thunar-vfs/thunar-vfs-info.c index ecd3c25e8a865cb24bbb44d4a3ec7967ec4a6800..5f6efe0a23a6d0599c30ed98448dee9f61e11aa3 100644 --- a/thunar-vfs/thunar-vfs-info.c +++ b/thunar-vfs/thunar-vfs-info.c @@ -35,11 +35,22 @@ #ifdef HAVE_STRING_H #include <string.h> #endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif #include <thunar-vfs/thunar-vfs-info.h> #include <thunar-vfs/thunar-vfs-mime-database.h> +#include <thunar-vfs/thunar-vfs-sysdep.h> #include <thunar-vfs/thunar-vfs-alias.h> +/* Use g_access() if possible */ +#if GLIB_CHECK_VERSION(2,8,0) +#include <glib/gstdio.h> +#else +#define g_access(path, mode) (access ((path), (mode))) +#endif + /** @@ -59,12 +70,15 @@ thunar_vfs_info_new_for_uri (ThunarVfsURI *uri, GError **error) { ThunarVfsMimeDatabase *database; + ThunarVfsMimeInfo *mime_info; ThunarVfsInfo *info; const gchar *path; const gchar *str; struct stat lsb; struct stat sb; XfceRc *rc; + GList *mime_infos; + GList *lp; g_return_val_if_fail (THUNAR_VFS_IS_URI (uri), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); @@ -84,6 +98,7 @@ thunar_vfs_info_new_for_uri (ThunarVfsURI *uri, info->display_name = thunar_vfs_uri_get_display_name (uri); info->hints = NULL; + /* determine the POSIX file attributes */ if (G_LIKELY (!S_ISLNK (lsb.st_mode))) { info->type = (lsb.st_mode & S_IFMT) >> 12; @@ -130,6 +145,7 @@ thunar_vfs_info_new_for_uri (ThunarVfsURI *uri, } } + /* determine the file's mime type */ database = thunar_vfs_mime_database_get_default (); switch (info->type) { @@ -158,7 +174,28 @@ thunar_vfs_info_new_for_uri (ThunarVfsURI *uri, break; case THUNAR_VFS_FILE_TYPE_REGULAR: + /* determine the MIME-type for the regular file */ info->mime_info = thunar_vfs_mime_database_get_info_for_file (database, path, info->display_name); + + /* check if the file is executable (for security reasons + * we only allow execution of well known file types). + */ + if (G_LIKELY (info->type == THUNAR_VFS_FILE_TYPE_REGULAR) + && (info->mode & 0444) != 0 && g_access (path, X_OK) == 0) + { + mime_infos = thunar_vfs_mime_database_get_infos_for_info (database, info->mime_info); + for (lp = mime_infos; lp != NULL; lp = lp->next) + { + mime_info = THUNAR_VFS_MIME_INFO (lp->data); + if (strcmp (mime_info->name, "application/x-executable") == 0 + || strcmp (mime_info->name, "application/x-shellscript") == 0) + { + info->flags |= THUNAR_VFS_FILE_FLAGS_EXECUTABLE; + break; + } + } + thunar_vfs_mime_info_list_free (mime_infos); + } break; default: @@ -190,6 +227,16 @@ thunar_vfs_info_new_for_uri (ThunarVfsURI *uri, if (G_LIKELY (str != NULL)) info->hints[THUNAR_VFS_FILE_HINT_NAME] = g_strdup (str); + /* check if the desktop file refers to an application + * and has a non-NULL Exec field set. + */ + str = xfce_rc_read_entry (rc, "Type", "Application"); + if (G_LIKELY (exo_str_is_equal (str, "Application")) + && xfce_rc_read_entry (rc, "Exec", NULL) != NULL) + { + info->flags |= THUNAR_VFS_FILE_FLAGS_EXECUTABLE; + } + /* close the file */ xfce_rc_close (rc); } @@ -268,6 +315,112 @@ thunar_vfs_info_unref (ThunarVfsInfo *info) +/** + * thunar_vfs_info_execute: + * @info : a #ThunarVfsInfo. + * @screen : a #GdkScreen or %NULL to use the default #GdkScreen. + * @uris : the list of #ThunarVfsURI<!---->s to give as parameters + * to the file referred to by @info on execution. + * @error : return location for errors or %NULL. + * + * Executes the file referred to by @info, given @uris as parameters, + * on the specified @screen. @info may refer to either a regular, + * executable file, or a <filename>.desktop</filename> file, whose + * type is <literal>Application</literal>. + * + * Return value: %TRUE on success, else %FALSE. + **/ +gboolean +thunar_vfs_info_execute (const ThunarVfsInfo *info, + GdkScreen *screen, + GList *uris, + GError **error) +{ + const gchar *icon; + const gchar *name; + const gchar *path; + gboolean terminal; + gboolean result = FALSE; + XfceRc *rc; + gchar *working_directory; + gchar *path_escaped; + gchar **argv = NULL; + gchar *exec; + + g_return_val_if_fail (info != NULL, FALSE); + g_return_val_if_fail (info->ref_count > 0, FALSE); + g_return_val_if_fail (screen == NULL || GDK_IS_SCREEN (screen), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* fallback to the default screen if none given */ + if (G_UNLIKELY (screen == NULL)) + screen = gdk_screen_get_default (); + + /* determine the path */ + path = thunar_vfs_uri_get_path (info->uri); + + /* check if we have a .desktop file here */ + if (G_UNLIKELY (strcmp (info->mime_info->name, "application/x-desktop") == 0)) + { + rc = xfce_rc_simple_open (path, TRUE); + if (G_LIKELY (rc != NULL)) + { + /* check if we have a valid Exec field */ + exec = (gchar *) xfce_rc_read_entry_untranslated (rc, "Exec", NULL); + if (G_LIKELY (exec != NULL)) + { + /* parse the Exec field */ + name = xfce_rc_read_entry (rc, "Name", NULL); + icon = xfce_rc_read_entry_untranslated (rc, "Icon", NULL); + terminal = xfce_rc_read_bool_entry (rc, "Terminal", FALSE); + result = _thunar_vfs_sysdep_parse_exec (exec, uris, icon, name, path, + terminal, NULL, &argv, error); + } + else + { + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("No Exec field specified")); + } + + /* close the rc file */ + xfce_rc_close (rc); + } + else + { + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Unable to parse file")); + } + } + else + { + /* fake the Exec line */ + path_escaped = g_shell_quote (path); + exec = g_strconcat (path_escaped, " %F", NULL); + result = _thunar_vfs_sysdep_parse_exec (exec, uris, NULL, NULL, NULL, FALSE, NULL, &argv, error); + g_free (path_escaped); + g_free (exec); + } + + if (G_LIKELY (result)) + { + /* determine the working directory */ + working_directory = g_path_get_dirname ((uris != NULL) ? thunar_vfs_uri_get_path (uris->data) : path); + + /* execute the command */ + result = gdk_spawn_on_screen (screen, working_directory, argv, + NULL, G_SPAWN_SEARCH_PATH, NULL, + NULL, NULL, error); + + /* release the working directory */ + g_free (working_directory); + } + + /* clean up */ + g_strfreev (argv); + + return result; +} + + + /** * thunar_vfs_info_get_hint: * @info : a #ThunarVfsInfo. diff --git a/thunar-vfs/thunar-vfs-info.h b/thunar-vfs/thunar-vfs-info.h index 1ae3f75de0c096f3adc9b9769caa90d9952f9a45..eaa374bf18fed6b1c131367a45996683999c6b53 100644 --- a/thunar-vfs/thunar-vfs-info.h +++ b/thunar-vfs/thunar-vfs-info.h @@ -97,18 +97,21 @@ typedef enum { /*< flags >*/ /** * ThunarVfsFileFlags: - * @THUNAR_VFS_FILE_FLAGS_NONE : No additional information available. - * @THUNAR_VFS_FILE_FLAGS_SYMLINK : The file is a symlink. Whether or not - * the info fields refer to the symlink - * itself or the linked file, depends on - * whether the symlink is broken or not. + * @THUNAR_VFS_FILE_FLAGS_NONE : No additional information available. + * @THUNAR_VFS_FILE_FLAGS_SYMLINK : The file is a symlink. Whether or not + * the info fields refer to the symlink + * itself or the linked file, depends on + * whether the symlink is broken or not. + * @THUNAR_VFS_FILE_FLAGS_EXECUTABLE : The file can most probably be executed + * by #thunar_vfs_info_execute(). * * Flags providing additional information about the * file system entity. **/ typedef enum { /*< flags >*/ - THUNAR_VFS_FILE_FLAGS_NONE = 0, - THUNAR_VFS_FILE_FLAGS_SYMLINK = 1 << 0, + THUNAR_VFS_FILE_FLAGS_NONE = 0, + THUNAR_VFS_FILE_FLAGS_SYMLINK = 1L << 0, + THUNAR_VFS_FILE_FLAGS_EXECUTABLE = 1L << 1, } ThunarVfsFileFlags; /** @@ -231,6 +234,11 @@ ThunarVfsInfo *thunar_vfs_info_new_for_uri (ThunarVfsURI *uri, ThunarVfsInfo *thunar_vfs_info_ref (ThunarVfsInfo *info); void thunar_vfs_info_unref (ThunarVfsInfo *info); +gboolean thunar_vfs_info_execute (const ThunarVfsInfo *info, + GdkScreen *screen, + GList *uris, + GError **error); + const gchar *thunar_vfs_info_get_hint (const ThunarVfsInfo *info, ThunarVfsFileHint hint); diff --git a/thunar-vfs/thunar-vfs-mime-application.c b/thunar-vfs/thunar-vfs-mime-application.c index eae6fd50efcd3d290e477cd37bb4f3112d3caac7..96f7ef3ab87125b9c5c54b41b8867458d0946eba 100644 --- a/thunar-vfs/thunar-vfs-mime-application.c +++ b/thunar-vfs/thunar-vfs-mime-application.c @@ -30,6 +30,8 @@ #endif #include <thunar-vfs/thunar-vfs-mime-application.h> +#include <thunar-vfs/thunar-vfs-sysdep.h> +#include <thunar-vfs/thunar-vfs-util.h> #include <thunar-vfs/thunar-vfs-alias.h> @@ -157,141 +159,7 @@ thunar_vfs_mime_application_get_argv (const ThunarVfsMimeApplication *applicatio gchar ***argv, GError **error) { - const gchar *p; - gboolean result; - GString *command_line = g_string_new (NULL); - GList *lp; - gchar *uri_string; - gchar *quoted; - - /* prepend terminal command if required */ - if (G_UNLIKELY (application->requires_terminal)) - { - quoted = g_shell_quote (application->name); - g_string_append (command_line, "Terminal -T "); - g_string_append (command_line, quoted); - g_string_append (command_line, " -x "); - g_free (quoted); - } - - for (p = application->exec; *p != '\0'; ++p) - { - if (p[0] == '%' && p[1] != '\0') - { - switch (*++p) - { - case 'f': - quoted = g_shell_quote (thunar_vfs_uri_get_path (uris->data)); - g_string_append (command_line, quoted); - g_free (quoted); - break; - - case 'F': - for (lp = uris; lp != NULL; lp = lp->next) - { - if (G_LIKELY (lp != uris)) - g_string_append_c (command_line, ' '); - quoted = g_shell_quote (thunar_vfs_uri_get_path (lp->data)); - g_string_append (command_line, quoted); - g_free (quoted); - } - break; - - case 'u': - /* we need to hide the host parameter here, because there are quite a few - * applications out there (namely GNOME applications), which cannot handle - * 'file:'-URIs with host names. - */ - uri_string = thunar_vfs_uri_to_string (uris->data, THUNAR_VFS_URI_HIDE_HOST); - quoted = g_shell_quote (uri_string); - g_string_append (command_line, quoted); - g_free (uri_string); - g_free (quoted); - break; - - case 'U': - for (lp = uris; lp != NULL; lp = lp->next) - { - if (G_LIKELY (lp != uris)) - g_string_append_c (command_line, ' '); - uri_string = thunar_vfs_uri_to_string (lp->data, THUNAR_VFS_URI_HIDE_HOST); - quoted = g_shell_quote (uri_string); - g_string_append (command_line, quoted); - g_free (uri_string); - g_free (quoted); - } - break; - - case 'd': - uri_string = g_path_get_dirname (thunar_vfs_uri_get_path (uris->data)); - quoted = g_shell_quote (uri_string); - g_string_append (command_line, quoted); - g_free (uri_string); - g_free (quoted); - break; - - case 'D': - for (lp = uris; lp != NULL; lp = lp->next) - { - if (G_LIKELY (lp != uris)) - g_string_append_c (command_line, ' '); - uri_string = g_path_get_dirname (thunar_vfs_uri_get_path (lp->data)); - quoted = g_shell_quote (uri_string); - g_string_append (command_line, quoted); - g_free (uri_string); - g_free (quoted); - } - break; - - case 'n': - quoted = g_shell_quote (thunar_vfs_uri_get_name (uris->data)); - g_string_append (command_line, quoted); - g_free (quoted); - break; - - case 'N': - for (lp = uris; lp != NULL; lp = lp->next) - { - if (G_LIKELY (lp != uris)) - g_string_append_c (command_line, ' '); - quoted = g_shell_quote (thunar_vfs_uri_get_name (lp->data)); - g_string_append (command_line, quoted); - g_free (quoted); - } - break; - - case 'i': - if (G_LIKELY (application->icon != NULL)) - { - quoted = g_shell_quote (application->icon); - g_string_append (command_line, "--icon "); - g_string_append (command_line, quoted); - g_free (quoted); - } - break; - - case 'c': - quoted = g_shell_quote (application->name); - g_string_append (command_line, quoted); - g_free (quoted); - break; - - case '%': - g_string_append_c (command_line, '%'); - break; - } - } - else - { - g_string_append_c (command_line, *p); - } - } - - result = g_shell_parse_argv (command_line->str, argc, argv, NULL); - - g_string_free (command_line, TRUE); - - return result; + return _thunar_vfs_sysdep_parse_exec (application->exec, uris, application->icon, application->name, NULL, application->requires_terminal, argc, argv, error); } diff --git a/thunar-vfs/thunar-vfs-mime-database.c b/thunar-vfs/thunar-vfs-mime-database.c index 805719bdddfa38152f4cd8c26a2c1948326b60b8..7651a48e642cbd42e44e8f8d9c1bbd0eb64dfdef 100644 --- a/thunar-vfs/thunar-vfs-mime-database.c +++ b/thunar-vfs/thunar-vfs-mime-database.c @@ -270,12 +270,29 @@ static ThunarVfsMimeInfo* thunar_vfs_mime_database_get_info_locked (ThunarVfsMimeDatabase *database, const gchar *mime_type) { - ThunarVfsMimeInfo *info; - const gchar *s; - const gchar *t; - const gchar *u; - gchar *v; - guint n; + ThunarVfsMimeProvider *provider; + ThunarVfsMimeInfo *info; + const gchar *s; + const gchar *t; + const gchar *u; + GList *lp; + gchar *v; + guint n; + + /* unalias the mime type */ + for (lp = database->providers; lp != NULL; lp = lp->next) + { + provider = THUNAR_VFS_MIME_PROVIDER_DATA (lp->data)->provider; + if (G_LIKELY (provider != NULL)) + { + t = thunar_vfs_mime_provider_lookup_alias (provider, mime_type); + if (G_UNLIKELY (t != NULL && strcmp (mime_type, t) != 0)) + { + mime_type = t; + break; + } + } + } /* check if we have a cached version of the mime type */ info = g_hash_table_lookup (database->infos, mime_type); @@ -446,7 +463,6 @@ thunar_vfs_mime_database_get_infos_for_info_locked (ThunarVfsMimeDatabase *datab ThunarVfsMimeProvider *provider; ThunarVfsMimeInfo *parent_info; const gchar *name = thunar_vfs_mime_info_get_name (info); - const gchar *type; gchar *parents[128]; GList *infos; GList *lp; @@ -455,23 +471,6 @@ thunar_vfs_mime_database_get_infos_for_info_locked (ThunarVfsMimeDatabase *datab /* the info itself is of course on the list */ infos = g_list_prepend (NULL, thunar_vfs_mime_info_ref (info)); - /* check if the info is an alias */ - for (lp = database->providers; lp != NULL; lp = lp->next) - { - provider = THUNAR_VFS_MIME_PROVIDER_DATA (lp->data)->provider; - if (G_LIKELY (provider != NULL)) - { - type = thunar_vfs_mime_provider_lookup_alias (provider, name); - if (G_UNLIKELY (type != NULL && strcmp (name, type) != 0)) - { - /* it is indeed an alias, so we use the unaliased type instead */ - info = thunar_vfs_mime_database_get_info_locked (database, type); - name = thunar_vfs_mime_info_get_name (info); - infos = g_list_append (infos, info); - } - } - } - /* lookup all parents on every provider */ for (lp = database->providers; lp != NULL; lp = lp->next) { @@ -1113,6 +1112,49 @@ thunar_vfs_mime_database_get_info_for_file (ThunarVfsMimeDatabase *database, +/** + * thunar_vfs_mime_database_get_infos_for_info: + * @database : a #ThunarVfsMimeDatabase. + * @info : a #ThunarVfsMimeInfo. + * + * Returns a list of all #ThunarVfsMimeInfo<!---->s, + * that are related to @info in @database. Currently + * this is the list of parent MIME-types for @info, + * as defined in the Shared Mime Database. + * + * Note that the returned list will also include + * a reference @info itself. In addition, this + * method also handles details specified by the + * Shared Mime Database Specification like the + * fact that every "text/xxxx" MIME-type is a + * subclass of "text/plain" and every MIME-type + * is a subclass of "application/octet-stream". + * + * The caller is responsible to free the returned + * list using #thunar_vfs_mime_info_list_free() + * when done with it. + * + * Return value: the list of #ThunarVfsMimeInfo<!---->s + * related to @info. + **/ +GList* +thunar_vfs_mime_database_get_infos_for_info (ThunarVfsMimeDatabase *database, + ThunarVfsMimeInfo *info) +{ + GList *infos; + + g_return_val_if_fail (THUNAR_VFS_IS_MIME_DATABASE (database), NULL); + g_return_val_if_fail (THUNAR_VFS_IS_MIME_INFO (info), NULL); + + g_mutex_lock (database->lock); + infos = thunar_vfs_mime_database_get_infos_for_info_locked (database, info); + g_mutex_unlock (database->lock); + + return infos; +} + + + /** * thunar_vfs_mime_database_get_applications: * @database : a #ThunarVfsMimeDatabase. diff --git a/thunar-vfs/thunar-vfs-mime-database.h b/thunar-vfs/thunar-vfs-mime-database.h index ec4d0aaae4d6e3d3a64819400bacc0ab585f5575..6d401211022fe11d335baae6021e81511e8ab542 100644 --- a/thunar-vfs/thunar-vfs-mime-database.h +++ b/thunar-vfs/thunar-vfs-mime-database.h @@ -51,6 +51,9 @@ ThunarVfsMimeInfo *thunar_vfs_mime_database_get_info_for_file (Thu const gchar *path, const gchar *name); +GList *thunar_vfs_mime_database_get_infos_for_info (ThunarVfsMimeDatabase *database, + ThunarVfsMimeInfo *info); + GList *thunar_vfs_mime_database_get_applications (ThunarVfsMimeDatabase *database, ThunarVfsMimeInfo *info); ThunarVfsMimeApplication *thunar_vfs_mime_database_get_default_application (ThunarVfsMimeDatabase *database, diff --git a/thunar-vfs/thunar-vfs-sysdep.c b/thunar-vfs/thunar-vfs-sysdep.c index 46e89164a8529f66577773ba9e8053bc807602d2..691b41abf110c2610af1efbb1d46172d875c1dd6 100644 --- a/thunar-vfs/thunar-vfs-sysdep.c +++ b/thunar-vfs/thunar-vfs-sysdep.c @@ -40,6 +40,8 @@ #endif #include <thunar-vfs/thunar-vfs-sysdep.h> +#include <thunar-vfs/thunar-vfs-uri.h> +#include <thunar-vfs/thunar-vfs-alias.h> @@ -113,3 +115,210 @@ _thunar_vfs_sysdep_readdir (gpointer dirp, +/** + * _thunar_vfs_sysdep_parse_exec: + * @exec : the value of the <literal>Exec</literal> field. + * @uris : the list of #ThunarVfsURI<!---->s. + * @icon : value of the <literal>Icon</literal> field or %NULL. + * @name : translated value for the <literal>Name</literal> field or %NULL. + * @path : full path to the desktop file or %NULL. + * @terminal : whether to execute the command in a terminal. + * @argc : return location for the number of items placed into @argv. + * @argv : return location for the argument vector. + * @error : return location for errors or %NULL. + * + * Substitutes <literal>Exec</literal> parameter variables according + * to the <ulink href="http://freedesktop.org/wiki/Standards_2fdesktop_2dentry_2dspec" + * type="http">Desktop Entry Specification</ulink> and returns the + * parsed argument vector (in @argv) and the number of items placed + * into @argv (in @argc). + * + * The @icon, @name and @path fields are optional and may be %NULL + * if you don't know their values. The @icon parameter should be + * the value of the <literal>Icon</literal> field from the desktop + * file, the @name parameter should be the translated <literal>Name</literal> + * value, while the @path parameter should refer to the full path + * to the desktop file, whose <literal>Exec</literal> field is + * being parsed here. + * + * Return value: %TRUE on success, else %FALSE. + **/ +gboolean +_thunar_vfs_sysdep_parse_exec (const gchar *exec, + GList *uris, + const gchar *icon, + const gchar *name, + const gchar *path, + gboolean terminal, + gint *argc, + gchar ***argv, + GError **error) +{ + const gchar *p; + gboolean result; + GString *command_line = g_string_new (NULL); + GList *lp; + gchar *uri_string; + gchar *quoted; + + /* prepend terminal command if required */ + if (G_UNLIKELY (terminal)) + { + g_string_append (command_line, "Terminal "); + if (G_LIKELY (name != NULL)) + { + quoted = g_shell_quote (name); + g_string_append (command_line, "-T "); + g_string_append (command_line, quoted); + g_free (quoted); + } + g_string_append (command_line, "-x "); + } + + for (p = exec; *p != '\0'; ++p) + { + if (p[0] == '%' && p[1] != '\0') + { + switch (*++p) + { + case 'f': + if (G_LIKELY (uris != NULL)) + { + quoted = g_shell_quote (thunar_vfs_uri_get_path (uris->data)); + g_string_append (command_line, quoted); + g_free (quoted); + } + break; + + case 'F': + for (lp = uris; lp != NULL; lp = lp->next) + { + if (G_LIKELY (lp != uris)) + g_string_append_c (command_line, ' '); + quoted = g_shell_quote (thunar_vfs_uri_get_path (lp->data)); + g_string_append (command_line, quoted); + g_free (quoted); + } + break; + + case 'u': + /* we need to hide the host parameter here, because there are quite a few + * applications out there (namely GNOME applications), which cannot handle + * 'file:'-URIs with host names. + */ + if (G_LIKELY (uris != NULL)) + { + uri_string = thunar_vfs_uri_to_string (uris->data, THUNAR_VFS_URI_HIDE_HOST); + quoted = g_shell_quote (uri_string); + g_string_append (command_line, quoted); + g_free (uri_string); + g_free (quoted); + } + break; + + case 'U': + for (lp = uris; lp != NULL; lp = lp->next) + { + if (G_LIKELY (lp != uris)) + g_string_append_c (command_line, ' '); + uri_string = thunar_vfs_uri_to_string (lp->data, THUNAR_VFS_URI_HIDE_HOST); + quoted = g_shell_quote (uri_string); + g_string_append (command_line, quoted); + g_free (uri_string); + g_free (quoted); + } + break; + + case 'd': + if (G_LIKELY (uris != NULL)) + { + uri_string = g_path_get_dirname (thunar_vfs_uri_get_path (uris->data)); + quoted = g_shell_quote (uri_string); + g_string_append (command_line, quoted); + g_free (uri_string); + g_free (quoted); + } + break; + + case 'D': + for (lp = uris; lp != NULL; lp = lp->next) + { + if (G_LIKELY (lp != uris)) + g_string_append_c (command_line, ' '); + uri_string = g_path_get_dirname (thunar_vfs_uri_get_path (lp->data)); + quoted = g_shell_quote (uri_string); + g_string_append (command_line, quoted); + g_free (uri_string); + g_free (quoted); + } + break; + + case 'n': + if (G_LIKELY (uris != NULL)) + { + quoted = g_shell_quote (thunar_vfs_uri_get_name (uris->data)); + g_string_append (command_line, quoted); + g_free (quoted); + } + break; + + case 'N': + for (lp = uris; lp != NULL; lp = lp->next) + { + if (G_LIKELY (lp != uris)) + g_string_append_c (command_line, ' '); + quoted = g_shell_quote (thunar_vfs_uri_get_name (lp->data)); + g_string_append (command_line, quoted); + g_free (quoted); + } + break; + + case 'i': + if (G_LIKELY (icon != NULL)) + { + quoted = g_shell_quote (icon); + g_string_append (command_line, "--icon "); + g_string_append (command_line, quoted); + g_free (quoted); + } + break; + + case 'c': + if (G_LIKELY (name != NULL)) + { + quoted = g_shell_quote (name); + g_string_append (command_line, quoted); + g_free (quoted); + } + break; + + case 'k': + if (G_LIKELY (path != NULL)) + { + quoted = g_shell_quote (path); + g_string_append (command_line, path); + g_free (quoted); + } + break; + + case '%': + g_string_append_c (command_line, '%'); + break; + } + } + else + { + g_string_append_c (command_line, *p); + } + } + + result = g_shell_parse_argv (command_line->str, argc, argv, error); + + g_string_free (command_line, TRUE); + + return result; +} + + + + diff --git a/thunar-vfs/thunar-vfs-sysdep.h b/thunar-vfs/thunar-vfs-sysdep.h index 68534ce0544e3a3dafd77fe8be784ca0e7e2cb26..64b6441eb59a5b9c629019f6c2db02934853c2f6 100644 --- a/thunar-vfs/thunar-vfs-sysdep.h +++ b/thunar-vfs/thunar-vfs-sysdep.h @@ -25,10 +25,23 @@ G_BEGIN_DECLS; -gboolean _thunar_vfs_sysdep_readdir (gpointer dirp, - struct dirent *entry, - struct dirent **result, - GError **error); +/* forward declarations */ +struct dirent; + +gboolean _thunar_vfs_sysdep_readdir (gpointer dirp, + struct dirent *entry, + struct dirent **result, + GError **error); + +gboolean _thunar_vfs_sysdep_parse_exec (const gchar *exec, + GList *uris, + const gchar *icon, + const gchar *name, + const gchar *path, + gboolean terminal, + gint *argc, + gchar ***argv, + GError **error) G_END_DECLS; diff --git a/thunar-vfs/thunar-vfs.symbols b/thunar-vfs/thunar-vfs.symbols index c992999fccaa5653fddad01b1bc5ea346be9d01d..7d54dd83684a420ff9a78f1f02eec3e1e5d57111 100644 --- a/thunar-vfs/thunar-vfs.symbols +++ b/thunar-vfs/thunar-vfs.symbols @@ -52,6 +52,7 @@ thunar_vfs_unlink thunar_vfs_info_new_for_uri thunar_vfs_info_ref thunar_vfs_info_unref +thunar_vfs_info_execute thunar_vfs_info_get_hint thunar_vfs_info_matches thunar_vfs_info_list_free @@ -116,6 +117,7 @@ thunar_vfs_mime_database_get_info thunar_vfs_mime_database_get_info_for_data thunar_vfs_mime_database_get_info_for_name thunar_vfs_mime_database_get_info_for_file +thunar_vfs_mime_database_get_infos_for_info thunar_vfs_mime_database_get_applications thunar_vfs_mime_database_get_default_application #endif diff --git a/thunar/thunar-file.c b/thunar/thunar-file.c index a3c83168eab7401ea361345e5ccb6d6bed4682cb..c196b438cd70c883977ab0fe81ddf3e4a60a2e20 100644 --- a/thunar/thunar-file.c +++ b/thunar/thunar-file.c @@ -47,12 +47,15 @@ static void thunar_file_class_init (ThunarFileClass static void thunar_file_finalize (GObject *object); static ThunarFile *thunar_file_real_get_parent (ThunarFile *file, GError **error); +static gboolean thunar_file_real_execute (ThunarFile *file, + GdkScreen *screen, + GList *uris, + GError **error); static ThunarFolder *thunar_file_real_open_as_folder (ThunarFile *file, GError **error); static const gchar *thunar_file_real_get_special_name (ThunarFile *file); -static gboolean thunar_file_real_can_execute (ThunarFile *file); -static gboolean thunar_file_real_can_read (ThunarFile *file); -static gboolean thunar_file_real_can_write (ThunarFile *file); +static gboolean thunar_file_real_is_readable (ThunarFile *file); +static gboolean thunar_file_real_is_writable (ThunarFile *file); static void thunar_file_real_changed (ThunarFile *file); static ThunarFile *thunar_file_new_internal (ThunarVfsURI *uri, GError **error); @@ -154,6 +157,7 @@ thunar_file_class_init (ThunarFileClass *klass) klass->has_parent = (gpointer) exo_noop_true; klass->get_parent = thunar_file_real_get_parent; + klass->execute = thunar_file_real_execute; klass->open_as_folder = thunar_file_real_open_as_folder; klass->get_mime_info = (gpointer) exo_noop_null; klass->get_special_name = thunar_file_real_get_special_name; @@ -162,9 +166,9 @@ thunar_file_class_init (ThunarFileClass *klass) klass->get_volume = (gpointer) exo_noop_null; klass->get_group = (gpointer) exo_noop_null; klass->get_user = (gpointer) exo_noop_null; - klass->can_execute = thunar_file_real_can_execute; - klass->can_read = thunar_file_real_can_read; - klass->can_write = thunar_file_real_can_write; + klass->is_executable = (gpointer) exo_noop_false; + klass->is_readable = thunar_file_real_is_readable; + klass->is_writable = thunar_file_real_is_writable; klass->get_emblem_names = (gpointer) exo_noop_null; klass->reload = (gpointer) exo_noop; klass->changed = thunar_file_real_changed; @@ -239,6 +243,18 @@ thunar_file_real_get_parent (ThunarFile *file, +static gboolean +thunar_file_real_execute (ThunarFile *file, + GdkScreen *screen, + GList *uris, + GError **error) +{ + g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (ENOEXEC), g_strerror (ENOEXEC)); + return FALSE; +} + + + static ThunarFolder* thunar_file_real_open_as_folder (ThunarFile *file, GError **error) @@ -258,18 +274,7 @@ thunar_file_real_get_special_name (ThunarFile *file) static gboolean -thunar_file_real_can_execute (ThunarFile *file) -{ - return !thunar_file_denies_access_permission (file, - THUNAR_VFS_FILE_MODE_USR_EXEC, - THUNAR_VFS_FILE_MODE_GRP_EXEC, - THUNAR_VFS_FILE_MODE_OTH_EXEC); -} - - - -static gboolean -thunar_file_real_can_read (ThunarFile *file) +thunar_file_real_is_readable (ThunarFile *file) { return !thunar_file_denies_access_permission (file, THUNAR_VFS_FILE_MODE_USR_READ, @@ -280,7 +285,7 @@ thunar_file_real_can_read (ThunarFile *file) static gboolean -thunar_file_real_can_write (ThunarFile *file) +thunar_file_real_is_writable (ThunarFile *file) { return !thunar_file_denies_access_permission (file, THUNAR_VFS_FILE_MODE_USR_WRITE, @@ -551,6 +556,34 @@ thunar_file_get_parent (ThunarFile *file, +/** + * thunar_file_execute: + * @file : a #ThunarFile instance. + * @screen : a #GdkScreen. + * @uris : the list of #ThunarVfsURI<!---->s to supply to @file on + * execution. + * @error : return location for errors or %NULL. + * + * Tries to execute @file on the specified @screen. If @file is executable + * and could have been spawned successfully, %TRUE is returned, else %FALSE + * will be returned and @error will be set to point to the error location. + * + * Return value: %TRUE on success, else %FALSE. + **/ +gboolean +thunar_file_execute (ThunarFile *file, + GdkScreen *screen, + GList *uris, + GError **error) +{ + g_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + return (*THUNAR_FILE_GET_CLASS (file)->execute) (file, screen, uris, error); +} + + + /** * thunar_file_open_as_folder: * @file : a #ThunarFile instance. @@ -968,7 +1001,7 @@ thunar_file_get_user (ThunarFile *file) /** - * thunar_file_can_execute: + * thunar_file_is_executable: * @file : a #ThunarFile instance. * * Determines whether the owner of the current process is allowed @@ -976,7 +1009,7 @@ thunar_file_get_user (ThunarFile *file) * @file). * * If the specific #ThunarFile implementation does not provide - * a custom #thunar_file_can_execute() method, the fallback + * a custom #thunar_file_is_executable() method, the fallback * method provided by #ThunarFile is used, which determines * whether the @file can be executed based on the data provided * by #thunar_file_get_mode(), #thunar_file_get_user() and @@ -985,23 +1018,23 @@ thunar_file_get_user (ThunarFile *file) * Return value: %TRUE if @file can be executed. **/ gboolean -thunar_file_can_execute (ThunarFile *file) +thunar_file_is_executable (ThunarFile *file) { g_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); - return THUNAR_FILE_GET_CLASS (file)->can_execute (file); + return THUNAR_FILE_GET_CLASS (file)->is_executable (file); } /** - * thunar_file_can_read: + * thunar_file_is_readable: * @file : a #ThunarFile instance. * * Determines whether the owner of the current process is allowed * to read the @file. * * If the specific #ThunarFile implementation does not provide - * a custom #thunar_file_can_read() method, the fallback + * a custom #thunar_file_is_readable() method, the fallback * method provided by #ThunarFile is used, which determines * whether the @file can be read based on the data provided * by #thunar_file_get_mode(), #thunar_file_get_user() and @@ -1010,23 +1043,23 @@ thunar_file_can_execute (ThunarFile *file) * Return value: %TRUE if @file can be read. **/ gboolean -thunar_file_can_read (ThunarFile *file) +thunar_file_is_readable (ThunarFile *file) { g_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); - return THUNAR_FILE_GET_CLASS (file)->can_read (file); + return THUNAR_FILE_GET_CLASS (file)->is_readable (file); } /** - * thunar_file_can_write: + * thunar_file_is_writable: * @file : a #ThunarFile instance. * * Determines whether the owner of the current process is allowed * to write the @file. * * If the specific #ThunarFile implementation does not provide - * a custom #thunar_file_can_write() method, the fallback + * a custom #thunar_file_is_writable() method, the fallback * method provided by #ThunarFile is used, which determines * whether the @file can be written based on the data provided * by #thunar_file_get_mode(), #thunar_file_get_user() and @@ -1035,10 +1068,10 @@ thunar_file_can_read (ThunarFile *file) * Return value: %TRUE if @file can be read. **/ gboolean -thunar_file_can_write (ThunarFile *file) +thunar_file_is_writable (ThunarFile *file) { g_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); - return THUNAR_FILE_GET_CLASS (file)->can_write (file); + return THUNAR_FILE_GET_CLASS (file)->is_writable (file); } diff --git a/thunar/thunar-file.h b/thunar/thunar-file.h index b23adfebc0e97ad7151b22910385744d875d6fbe..bf2d098a37a8b21fdbb5b8b3c059cbba23e72914 100644 --- a/thunar/thunar-file.h +++ b/thunar/thunar-file.h @@ -71,6 +71,11 @@ struct _ThunarFileClass ThunarFile *(*get_parent) (ThunarFile *file, GError **error); + gboolean (*execute) (ThunarFile *file, + GdkScreen *screen, + GList *uris, + GError **error); + ThunarFolder *(*open_as_folder) (ThunarFile *file, GError **error); @@ -95,9 +100,9 @@ struct _ThunarFileClass ThunarVfsGroup *(*get_group) (ThunarFile *file); ThunarVfsUser *(*get_user) (ThunarFile *file); - gboolean (*can_execute) (ThunarFile *file); - gboolean (*can_read) (ThunarFile *file); - gboolean (*can_write) (ThunarFile *file); + gboolean (*is_executable) (ThunarFile *file); + gboolean (*is_readable) (ThunarFile *file); + gboolean (*is_writable) (ThunarFile *file); GList *(*get_emblem_names) (ThunarFile *file); const gchar *(*get_icon_name) (ThunarFile *file, @@ -135,6 +140,11 @@ gboolean thunar_file_has_parent (ThunarFile *file); ThunarFile *thunar_file_get_parent (ThunarFile *file, GError **error); +gboolean thunar_file_execute (ThunarFile *file, + GdkScreen *screen, + GList *uris, + GError **error); + ThunarFolder *thunar_file_open_as_folder (ThunarFile *file, GError **error); @@ -164,9 +174,9 @@ ThunarVfsVolume *thunar_file_get_volume (ThunarFile *file, ThunarVfsGroup *thunar_file_get_group (ThunarFile *file); ThunarVfsUser *thunar_file_get_user (ThunarFile *file); -gboolean thunar_file_can_execute (ThunarFile *file); -gboolean thunar_file_can_read (ThunarFile *file); -gboolean thunar_file_can_write (ThunarFile *file); +gboolean thunar_file_is_executable (ThunarFile *file); +gboolean thunar_file_is_readable (ThunarFile *file); +gboolean thunar_file_is_writable (ThunarFile *file); GList *thunar_file_get_emblem_names (ThunarFile *file); GdkPixbuf *thunar_file_load_icon (ThunarFile *file, diff --git a/thunar/thunar-launcher.c b/thunar/thunar-launcher.c index a49f93e345d8918961215de1b17749f5abc9aeb0..852bf8f049ea674d8b85b4d33eb97d21dc515f0a 100644 --- a/thunar/thunar-launcher.c +++ b/thunar/thunar-launcher.c @@ -55,6 +55,8 @@ static void thunar_launcher_set_property (GObject guint prop_id, const GValue *value, GParamSpec *pspec); +static void thunar_launcher_execute_files (ThunarLauncher *launcher, + GList *files); static void thunar_launcher_open_uris (ThunarVfsMimeApplication *application, GList *uri_list, ThunarLauncher *launcher); @@ -283,6 +285,47 @@ thunar_launcher_set_property (GObject *object, +static void +thunar_launcher_execute_files (ThunarLauncher *launcher, + GList *files) +{ + ThunarFile *file; + GtkWidget *message; + GtkWidget *window; + GdkScreen *screen; + GError *error = NULL; + GList *lp; + + /* determine the screen on which to run the file(s) */ + screen = (launcher->widget != NULL) + ? gtk_widget_get_screen (launcher->widget) + : gdk_screen_get_default (); + + /* execute all selected files */ + for (lp = files; lp != NULL; lp = lp->next) + { + file = THUNAR_FILE (lp->data); + if (!thunar_file_execute (file, screen, NULL, &error)) + { + window = (launcher->widget != NULL) ? gtk_widget_get_toplevel (launcher->widget) : NULL; + message = gtk_message_dialog_new ((GtkWindow *) window, + GTK_DIALOG_MODAL + | GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + _("Unable to execute file \"%s\"."), + thunar_file_get_display_name (file)); + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message), "%s.", error->message); + gtk_dialog_run (GTK_DIALOG (message)); + gtk_widget_destroy (message); + g_error_free (error); + break; + } + } +} + + + static void thunar_launcher_open_uris (ThunarVfsMimeApplication *application, GList *uri_list, @@ -460,6 +503,7 @@ thunar_launcher_update (ThunarLauncher *launcher) GList *lp; gchar text[256]; gint n_directories = 0; + gint n_executables = 0; gint n_files = 0; gint n_items; @@ -471,9 +515,15 @@ thunar_launcher_update (ThunarLauncher *launcher) for (lp = items; lp != NULL; lp = lp->next) { if (thunar_file_is_directory (lp->data)) - ++n_directories; + { + ++n_directories; + } else - ++n_files; + { + if (thunar_file_is_executable (lp->data)) + ++n_executables; + ++n_files; + } } if (G_UNLIKELY (n_directories == n_items)) @@ -496,6 +546,12 @@ thunar_launcher_update (ThunarLauncher *launcher) } else { + /* we turn the "Open" label into "Execute" if we have only one executable file */ + if (G_UNLIKELY (n_executables == 1 && n_items == 1)) + g_object_set (G_OBJECT (launcher->action_open), "label", _("Execute"), NULL); + else + g_object_set (G_OBJECT (launcher->action_open), "label", _("Open"), NULL); + #if GTK_CHECK_VERSION(2,6,0) gtk_action_set_sensitive (launcher->action_open, (n_items > 0)); gtk_action_set_visible (launcher->action_open_in_new_window, FALSE); @@ -548,7 +604,10 @@ thunar_launcher_action_open (GtkAction *action, /* open the files */ if (files != NULL) { - thunar_launcher_open_files (launcher, files); + if (g_list_length (files) == 1 && thunar_file_is_executable (files->data)) + thunar_launcher_execute_files (launcher, files); + else + thunar_launcher_open_files (launcher, files); thunar_file_list_free (files); } } diff --git a/thunar/thunar-local-file.c b/thunar/thunar-local-file.c index 17458727c860621ccc8be7dc5dfd46399eb97983..b0f2bdb29de6dbdb33da92790fc6c8217cf41a5f 100644 --- a/thunar/thunar-local-file.c +++ b/thunar/thunar-local-file.c @@ -30,6 +30,10 @@ static void thunar_local_file_class_init (ThunarLocalFileCl static void thunar_local_file_finalize (GObject *object); static ThunarFile *thunar_local_file_get_parent (ThunarFile *file, GError **error); +static gboolean thunar_local_file_execute (ThunarFile *file, + GdkScreen *screen, + GList *uris, + GError **error); static ThunarFolder *thunar_local_file_open_as_folder (ThunarFile *file, GError **error); static ThunarVfsURI *thunar_local_file_get_uri (ThunarFile *file); @@ -47,6 +51,7 @@ static ThunarVfsVolume *thunar_local_file_get_volume (ThunarFile ThunarVfsVolumeManager *volume_manager); static ThunarVfsGroup *thunar_local_file_get_group (ThunarFile *file); static ThunarVfsUser *thunar_local_file_get_user (ThunarFile *file); +static gboolean thunar_local_file_is_executable (ThunarFile *file); static GList *thunar_local_file_get_emblem_names (ThunarFile *file); static const gchar *thunar_local_file_get_icon_name (ThunarFile *file, GtkIconTheme *icon_theme); @@ -133,6 +138,7 @@ thunar_local_file_class_init (ThunarLocalFileClass *klass) thunarfile_class = THUNAR_FILE_CLASS (klass); thunarfile_class->get_parent = thunar_local_file_get_parent; + thunarfile_class->execute = thunar_local_file_execute; thunarfile_class->open_as_folder = thunar_local_file_open_as_folder; thunarfile_class->get_uri = thunar_local_file_get_uri; thunarfile_class->get_mime_info = thunar_local_file_get_mime_info; @@ -145,6 +151,7 @@ thunar_local_file_class_init (ThunarLocalFileClass *klass) thunarfile_class->get_volume = thunar_local_file_get_volume; thunarfile_class->get_group = thunar_local_file_get_group; thunarfile_class->get_user = thunar_local_file_get_user; + thunarfile_class->is_executable = thunar_local_file_is_executable; thunarfile_class->get_emblem_names = thunar_local_file_get_emblem_names; thunarfile_class->get_icon_name = thunar_local_file_get_icon_name; thunarfile_class->watch = thunar_local_file_watch; @@ -206,6 +213,18 @@ thunar_local_file_get_parent (ThunarFile *file, +static gboolean +thunar_local_file_execute (ThunarFile *file, + GdkScreen *screen, + GList *uris, + GError **error) +{ + ThunarLocalFile *local_file = THUNAR_LOCAL_FILE (file); + return thunar_vfs_info_execute (local_file->info, screen, uris, error); +} + + + static ThunarFolder* thunar_local_file_open_as_folder (ThunarFile *file, GError **error) @@ -352,6 +371,15 @@ thunar_local_file_get_user (ThunarFile *file) +static gboolean +thunar_local_file_is_executable (ThunarFile *file) +{ + ThunarLocalFile *local_file = THUNAR_LOCAL_FILE (file); + return ((local_file->info->flags & THUNAR_VFS_FILE_FLAGS_EXECUTABLE) != 0); +} + + + static GList* thunar_local_file_get_emblem_names (ThunarFile *file) { @@ -371,7 +399,7 @@ thunar_local_file_get_emblem_names (ThunarFile *file) if ((info->flags & THUNAR_VFS_FILE_FLAGS_SYMLINK) != 0) emblems = g_list_prepend (emblems, THUNAR_FILE_EMBLEM_NAME_SYMBOLIC_LINK); - if (!thunar_file_can_read (file)) + if (!thunar_file_is_readable (file)) emblems = g_list_prepend (emblems, THUNAR_FILE_EMBLEM_NAME_CANT_READ); return emblems; diff --git a/thunar/thunar-standard-view.c b/thunar/thunar-standard-view.c index 5b5d97a1abf2d1dcbc7882ecd50e25c905d107cc..9d18a9741efddd5bfc8cba0f20d07281a251eb2a 100644 --- a/thunar/thunar-standard-view.c +++ b/thunar/thunar-standard-view.c @@ -1172,7 +1172,7 @@ thunar_standard_view_selection_changed (ThunarStandardView *standard_view) /* check whether the folder displayed by the view is writable */ current_directory = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (standard_view)); - writable = (current_directory != NULL && thunar_file_can_write (current_directory)); + writable = (current_directory != NULL && thunar_file_is_writable (current_directory)); /* check whether the clipboard contains data that can be pasted here */ pastable = (standard_view->clipboard != NULL && thunar_clipboard_manager_get_can_paste (standard_view->clipboard)); @@ -1185,7 +1185,7 @@ thunar_standard_view_selection_changed (ThunarStandardView *standard_view) * folder to which we can paste to */ can_paste_into_folder = (n_selected_files == 1) && thunar_file_is_directory (selected_files->data) - && thunar_file_can_write (selected_files->data); + && thunar_file_is_writable (selected_files->data); /* update the "Properties" action */ gtk_action_set_sensitive (standard_view->priv->action_properties, (n_selected_files == 1));