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));