diff --git a/ChangeLog b/ChangeLog
index 12d9c061693d606dbd345f2bca38f97147c8ba01..9c7bbc3e4170f7eeb59b31f938e1eac91890b5bb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2005-08-06	Benedikt Meurer <benny@xfce.org>
+
+	* thunar-vfs/thunar-vfs-mime-legacy.c: Add support for the various
+	  globs to the legacy mime provider.
+	* thunar-vfs/thunar-vfs-mime-database.c(thunar_vfs_mime_database_init):
+	  Read atleast 64 bytes from every file to reliably detect text files.
+	* thunar-vfs/thunar-vfs-mime-database.c: When looking up the MIME info
+	  for a given file, and the magic check doesn't return a match, we'll
+	  return "application/x-executable" for every regular file that is
+	  atleast 1 byte in size and has the executable bit set, as this is
+	  more precise than "application/octet-stream".
+
 2005-08-06	Benedikt Meurer <benny@xfce.org>
 
 	* configure.in.in: Use AC_TRY_LINK() to avoid trouble with funky
diff --git a/thunar-vfs/thunar-vfs-mime-database.c b/thunar-vfs/thunar-vfs-mime-database.c
index 78dd1daea11279868831859a7b1729ed2ede83df..4e4eda0a319c6e8b3e8623b058fa078bb8ab64ca 100644
--- a/thunar-vfs/thunar-vfs-mime-database.c
+++ b/thunar-vfs/thunar-vfs-mime-database.c
@@ -74,6 +74,9 @@ static void               thunar_vfs_mime_database_init                       (T
 static void               thunar_vfs_mime_database_finalize                   (ExoObject                  *object);
 static ThunarVfsMimeInfo *thunar_vfs_mime_database_get_info_unlocked          (ThunarVfsMimeDatabase      *database,
                                                                                const gchar                *mime_type);
+static ThunarVfsMimeInfo *thunar_vfs_mime_database_get_info_for_data_unlocked (ThunarVfsMimeDatabase      *database,
+                                                                               gconstpointer               data,
+                                                                               gsize                       length);
 static ThunarVfsMimeInfo *thunar_vfs_mime_database_get_info_for_name_unlocked (ThunarVfsMimeDatabase      *database,
                                                                                const gchar                *name);
 
@@ -182,10 +185,11 @@ thunar_vfs_mime_database_init (ThunarVfsMimeDatabase *database)
     }
   g_strfreev (basedirs);
 
-  /* clamp the max buffer extents to [1..256] to make
-   * sure we don't try insane values.
+  /* clamp the max buffer extents to [64..256] to make
+   * sure we don't try insane values (everything below
+   * 64 bytes would be useless for the UTF-8 check).
    */
-  database->max_buffer_extents = CLAMP (database->max_buffer_extents, 1, 256);
+  database->max_buffer_extents = CLAMP (database->max_buffer_extents, 64, 256);
 
   /* collect the stop characters */
   database->stopchars = g_new (gchar, g_list_length (stopchars) + 1);
@@ -309,6 +313,53 @@ again:
 
 
 
+static ThunarVfsMimeInfo*
+thunar_vfs_mime_database_get_info_for_data_unlocked (ThunarVfsMimeDatabase *database,
+                                                     gconstpointer          data,
+                                                     gsize                  length)
+{
+  ThunarVfsMimeProvider *provider;
+  ThunarVfsMimeInfo     *info = NULL;
+  const gchar           *type_best;
+  const gchar           *type;
+  GList                 *lp;
+  gint                   prio_best;
+  gint                   prio;
+
+  if (G_LIKELY (data != NULL && length > 0))
+    {
+      /* perform a 'best fit' lookup on all active providers */
+      for (type_best = NULL, prio_best = -1, 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_data (provider, data, length, &prio);
+              if (G_LIKELY (type != NULL && prio > prio_best))
+                {
+                  prio_best = prio;
+                  type_best = type;
+                }
+            }
+        }
+
+      if (G_LIKELY (type_best != NULL))
+        {
+          /* lookup the info for the best type (if any) */
+          info = thunar_vfs_mime_database_get_info_unlocked (database, type_best);
+        }
+      else if (g_utf8_validate (data, length, NULL))
+        {
+          /* we have valid UTF-8 text here! */
+          info = thunar_vfs_mime_database_get_info_unlocked (database, "text/plain");
+        }
+    }
+
+  return info;
+}
+
+
+
 static ThunarVfsMimeInfo*
 thunar_vfs_mime_database_get_info_for_name_unlocked (ThunarVfsMimeDatabase *database,
                                                      const gchar           *name)
@@ -443,46 +494,14 @@ thunar_vfs_mime_database_get_info_for_data (ThunarVfsMimeDatabase *database,
                                             gconstpointer          data,
                                             gsize                  length)
 {
-  ThunarVfsMimeProvider *provider;
-  ThunarVfsMimeInfo     *info = NULL;
-  const gchar           *type_best;
-  const gchar           *type;
-  GList                 *lp;
-  gint                   prio_best;
-  gint                   prio;
+  ThunarVfsMimeInfo *info;
 
   g_return_val_if_fail (THUNAR_VFS_IS_MIME_DATABASE (database), NULL);
 
   g_mutex_lock (database->lock);
 
-  if (G_LIKELY (data != NULL && length > 0))
-    {
-      /* perform a 'best fit' lookup on all active providers */
-      for (type_best = NULL, prio_best = -1, 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_data (provider, data, length, &prio);
-              if (G_LIKELY (type != NULL && prio > prio_best))
-                {
-                  prio_best = prio;
-                  type_best = type;
-                }
-            }
-        }
-
-      if (G_LIKELY (type_best != NULL))
-        {
-          /* lookup the info for the best type (if any) */
-          info = thunar_vfs_mime_database_get_info_unlocked (database, type_best);
-        }
-      else if (g_utf8_validate (data, length, NULL))
-        {
-          /* we have valid UTF-8 text here! */
-          info = thunar_vfs_mime_database_get_info_unlocked (database, "text/plain");
-        }
-    }
+  /* try to determine a MIME type based on the data */
+  info = thunar_vfs_mime_database_get_info_for_data_unlocked (database, data, length);
 
   /* fallback to 'application/octet-stream' if we could not determine any type */
   if (G_UNLIKELY (info == NULL))
@@ -617,7 +636,21 @@ thunar_vfs_mime_database_get_info_for_file (ThunarVfsMimeDatabase *database,
 
               /* try to determine a type from the buffer contents */
               if (G_LIKELY (nbytes > 0))
-                info = thunar_vfs_mime_database_get_info_for_data (database, buffer, nbytes);
+                {
+                  g_mutex_lock (database->lock);
+
+                  /* the regular magic check first */
+                  info = thunar_vfs_mime_database_get_info_for_data_unlocked (database, buffer, nbytes);
+
+                  /* then if magic doesn't tell us anything and the file is marked,
+                   * as executable, we just guess "application/x-executable", which
+                   * is atleast more precise than "application/octet-stream".
+                   */
+                  if (G_UNLIKELY (info == NULL && (stat.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0))
+                    info = thunar_vfs_mime_database_get_info_unlocked (database, "application/x-executable");
+
+                  g_mutex_unlock (database->lock);
+                }
 
               /* cleanup */
               g_free (buffer);
diff --git a/thunar-vfs/thunar-vfs-mime-legacy.c b/thunar-vfs/thunar-vfs-mime-legacy.c
index f154652eef8f31be3b50862004d67773b2858090..f49e0aeea979414a9210403b0d260529f01fa7ed 100644
--- a/thunar-vfs/thunar-vfs-mime-legacy.c
+++ b/thunar-vfs/thunar-vfs-mime-legacy.c
@@ -25,11 +25,32 @@
 #include <config.h>
 #endif
 
+#ifdef HAVE_FNMATCH_H
+#include <fnmatch.h>
+#endif
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
 #include <thunar-vfs/thunar-vfs-mime-legacy.h>
 
 
 
+#define THUNAR_VFS_MIME_LEGACY_GLOB(obj)   ((ThunarVfsMimeLegacyGlob *) (obj))
+#define THUNAR_VFS_MIME_LEGACY_SUFFIX(obj) ((ThunarVfsMimeLegacySuffix *) (obj))
+
+
+
+typedef struct _ThunarVfsMimeLegacyGlob   ThunarVfsMimeLegacyGlob;
+typedef struct _ThunarVfsMimeLegacySuffix ThunarVfsMimeLegacySuffix;
+
+
+
 static void         thunar_vfs_mime_legacy_class_init             (ThunarVfsMimeLegacyClass *klass);
+static void         thunar_vfs_mime_legacy_init                   (ThunarVfsMimeLegacy      *legacy);
 static void         thunar_vfs_mime_legacy_finalize               (ExoObject                *object);
 static const gchar *thunar_vfs_mime_legacy_lookup_data            (ThunarVfsMimeProvider    *provider,
                                                                    gconstpointer             data,
@@ -44,6 +65,8 @@ static const gchar *thunar_vfs_mime_legacy_lookup_glob            (ThunarVfsMime
                                                                    const gchar              *filename);
 static GList       *thunar_vfs_mime_legacy_get_stop_characters    (ThunarVfsMimeProvider    *provider);
 static gsize        thunar_vfs_mime_legacy_get_max_buffer_extents (ThunarVfsMimeProvider    *provider);
+static gboolean     thunar_vfs_mime_legacy_parse_globs            (ThunarVfsMimeLegacy      *legacy,
+                                                                   const gchar              *directory);
 
 
 
@@ -55,6 +78,28 @@ struct _ThunarVfsMimeLegacyClass
 struct _ThunarVfsMimeLegacy
 {
   ThunarVfsMimeProvider __parent__;
+
+  GStringChunk              *string_chunk;
+  GMemChunk                 *suffix_chunk;
+  GMemChunk                 *glob_chunk;
+
+  GHashTable                *literals;
+  ThunarVfsMimeLegacySuffix *suffixes;
+  GList                     *globs;
+};
+
+struct _ThunarVfsMimeLegacyGlob
+{
+  const gchar *pattern;
+  const gchar *mime_type;
+};
+
+struct _ThunarVfsMimeLegacySuffix
+{
+  ThunarVfsMimeLegacySuffix *child;
+  ThunarVfsMimeLegacySuffix *next;
+  const gchar               *mime_type;
+  gunichar                   character;
 };
 
 
@@ -80,7 +125,7 @@ thunar_vfs_mime_legacy_get_type (void)
         NULL,
         sizeof (ThunarVfsMimeLegacy),
         0,
-        NULL,
+        (GInstanceInitFunc) thunar_vfs_mime_legacy_init,
         NULL,
       };
 
@@ -115,9 +160,34 @@ thunar_vfs_mime_legacy_class_init (ThunarVfsMimeLegacyClass *klass)
 
 
 
+static void
+thunar_vfs_mime_legacy_init (ThunarVfsMimeLegacy *legacy)
+{
+  legacy->string_chunk = g_string_chunk_new (1024);
+  legacy->glob_chunk = g_mem_chunk_create (ThunarVfsMimeLegacyGlob, 32, G_ALLOC_ONLY);
+  legacy->suffix_chunk = g_mem_chunk_create (ThunarVfsMimeLegacySuffix, 128, G_ALLOC_ONLY);
+
+  legacy->literals = g_hash_table_new (g_str_hash, g_str_equal);
+}
+
+
+
 static void
 thunar_vfs_mime_legacy_finalize (ExoObject *object)
 {
+  ThunarVfsMimeLegacy *legacy = THUNAR_VFS_MIME_LEGACY (object);
+
+  /* free the list of globs */
+  g_list_free (legacy->globs);
+
+  /* free literals hash table */
+  g_hash_table_destroy (legacy->literals);
+
+  /* free chunks */
+  g_string_chunk_free (legacy->string_chunk);
+  g_mem_chunk_destroy (legacy->suffix_chunk);
+  g_mem_chunk_destroy (legacy->glob_chunk);
+
   (*EXO_OBJECT_CLASS (thunar_vfs_mime_legacy_parent_class)->finalize) (object);
 }
 
@@ -138,6 +208,100 @@ static const gchar*
 thunar_vfs_mime_legacy_lookup_literal (ThunarVfsMimeProvider *provider,
                                        const gchar           *filename)
 {
+  return g_hash_table_lookup (THUNAR_VFS_MIME_LEGACY (provider)->literals, filename);
+}
+
+
+
+static ThunarVfsMimeLegacySuffix*
+suffix_insert (ThunarVfsMimeLegacy       *legacy,
+               ThunarVfsMimeLegacySuffix *suffix_node,
+               const gchar               *pattern,
+               const gchar               *mime_type)
+{
+  ThunarVfsMimeLegacySuffix *previous;
+  ThunarVfsMimeLegacySuffix *node;
+  gboolean                   found_node = FALSE;
+  gunichar                   character;
+
+  character = g_utf8_get_char (pattern);
+
+  if (suffix_node == NULL || character < suffix_node->character)
+    {
+      node = g_chunk_new0 (ThunarVfsMimeLegacySuffix, legacy->suffix_chunk);
+      node->next = suffix_node;
+      node->character = character;
+      suffix_node = node;
+    }
+  else if (character == suffix_node->character)
+    {
+      node = suffix_node;
+    }
+  else
+    {
+      for (previous = suffix_node, node = previous->next; node != NULL; previous = node, node = node->next)
+        {
+          if (character < node->character)
+            {
+              node = g_chunk_new0 (ThunarVfsMimeLegacySuffix, legacy->suffix_chunk);
+              node->next = previous->next;
+              node->character = character;
+              previous->next = node;
+              found_node = TRUE;
+              break;
+            }
+          else if (character == node->character)
+            {
+              found_node = TRUE;
+              break;
+            }
+        }
+
+      if (!found_node)
+        {
+          node = g_chunk_new0 (ThunarVfsMimeLegacySuffix, legacy->suffix_chunk);
+          node->next = previous->next;
+          node->character = character;
+          previous->next = node;
+        }
+    }
+
+  pattern = g_utf8_next_char (pattern);
+  if (G_UNLIKELY (*pattern == '\0'))
+    node->mime_type = mime_type;
+  else
+    node->child = suffix_insert (legacy, node->child, pattern, mime_type);
+
+  return suffix_node;
+}
+
+
+
+static const gchar*
+suffix_lookup (ThunarVfsMimeLegacySuffix *suffix_node,
+               const gchar               *filename,
+               gboolean                   ignore_case)
+{
+  ThunarVfsMimeLegacySuffix *node;
+  gunichar                   character;
+
+  if (G_UNLIKELY (suffix_node == NULL))
+    return NULL;
+
+  character = g_utf8_get_char (filename);
+  if (G_UNLIKELY (ignore_case))
+    character = g_unichar_tolower (character);
+
+  for (node = suffix_node; node != NULL && character >= node->character; node = node->next)
+    if (character == node->character)
+      {
+        filename = g_utf8_next_char (filename);
+        if (*filename == '\0')
+          return node->mime_type;
+        else
+          return suffix_lookup (node->child, filename, ignore_case);
+      }
+
   return NULL;
 }
 
@@ -148,7 +312,7 @@ thunar_vfs_mime_legacy_lookup_suffix (ThunarVfsMimeProvider *provider,
                                       const gchar           *suffix,
                                       gboolean               ignore_case)
 {
-  return NULL;
+  return suffix_lookup (THUNAR_VFS_MIME_LEGACY (provider)->suffixes, suffix, ignore_case);
 }
 
 
@@ -157,6 +321,12 @@ static const gchar*
 thunar_vfs_mime_legacy_lookup_glob (ThunarVfsMimeProvider *provider,
                                     const gchar           *filename)
 {
+  GList *lp;
+
+  for (lp = THUNAR_VFS_MIME_LEGACY (provider)->globs; lp != NULL; lp = lp->next)
+    if (fnmatch (THUNAR_VFS_MIME_LEGACY_GLOB (lp->data)->pattern, filename, 0) == 0)
+      return THUNAR_VFS_MIME_LEGACY_GLOB (lp->data)->mime_type;
+
   return NULL;
 }
 
@@ -165,7 +335,14 @@ thunar_vfs_mime_legacy_lookup_glob (ThunarVfsMimeProvider *provider,
 static GList*
 thunar_vfs_mime_legacy_get_stop_characters (ThunarVfsMimeProvider *provider)
 {
-  return NULL;
+  ThunarVfsMimeLegacySuffix *node;
+  GList                     *stopchars = NULL;
+
+  for (node = THUNAR_VFS_MIME_LEGACY (provider)->suffixes; node != NULL; node = node->next)
+    if (node->character < 128u)
+      stopchars = g_list_prepend (stopchars, GUINT_TO_POINTER (node->character));
+
+  return stopchars;
 }
 
 
@@ -178,6 +355,74 @@ thunar_vfs_mime_legacy_get_max_buffer_extents (ThunarVfsMimeProvider *provider)
 
 
 
+static gboolean
+thunar_vfs_mime_legacy_parse_globs (ThunarVfsMimeLegacy *legacy,
+                                    const gchar         *directory)
+{
+  ThunarVfsMimeLegacyGlob *glob;
+  gchar                    line[2048];
+  gchar                   *pattern;
+  gchar                   *path;
+  gchar                   *name;
+  gchar                   *lp;
+  FILE                    *fp;
+
+  /* try to open the "globs" file */
+  path = g_build_filename (directory, "globs", NULL);
+  fp = fopen (path, "r");
+  g_free (path);
+
+  /* cannot continue */
+  if (G_UNLIKELY (fp == NULL))
+    return FALSE;
+
+  /* parse all globs */
+  while (fgets (line, sizeof (line), fp) != NULL)
+    {
+      /* skip whitespace/comments */
+      for (lp = line; g_ascii_isspace (*lp); ++lp);
+      if (*lp == '\0' || *lp == '#')
+        continue;
+
+      /* extract the MIME-type name */
+      for (name = lp; *lp != '\0' && *lp != ':'; ++lp);
+      if (*lp == '\0' || name == lp)
+        continue;
+
+      /* extract the pattern */
+      for (*lp = '\0', pattern = ++lp; *lp != '\0' && *lp != '\n' && *lp != '\r'; ++lp);
+      *lp = '\0';
+      if (*pattern == '\0')
+        continue;
+
+      /* insert the name into the string chunk */
+      name = g_string_chunk_insert_const (legacy->string_chunk, name);
+
+      /* determine the type of the pattern */
+      if (strpbrk (pattern, "*?[") == NULL)
+        {
+          g_hash_table_insert (legacy->literals, g_string_chunk_insert (legacy->string_chunk, pattern), name);
+        }
+      else if (pattern[0] == '*' && pattern[1] == '.' && strpbrk (pattern + 2, "*?[") == NULL)
+        {
+          legacy->suffixes = suffix_insert (legacy, legacy->suffixes, pattern + 1, name);
+        }
+      else
+        {
+          glob = g_chunk_new (ThunarVfsMimeLegacyGlob, legacy->glob_chunk);
+          glob->pattern = g_string_chunk_insert (legacy->string_chunk, pattern);
+          glob->mime_type = name;
+          legacy->globs = g_list_append (legacy->globs, glob);
+        }
+    }
+
+  fclose (fp);
+
+  return TRUE;
+}
+
+
+
 /**
  * thunar_vfs_mime_legacy_new:
  * @directory : an XDG mime base directory.
@@ -194,7 +439,20 @@ thunar_vfs_mime_legacy_get_max_buffer_extents (ThunarVfsMimeProvider *provider)
 ThunarVfsMimeProvider*
 thunar_vfs_mime_legacy_new (const gchar *directory)
 {
-  return NULL;
+  ThunarVfsMimeLegacy *legacy;
+
+  /* allocate the new object */
+  legacy = exo_object_new (THUNAR_VFS_TYPE_MIME_LEGACY);
+
+  /* try to parse the globs file */
+  if (!thunar_vfs_mime_legacy_parse_globs (legacy, directory))
+    {
+      exo_object_unref (legacy);
+      return NULL;
+    }
+
+  /* we got it */
+  return THUNAR_VFS_MIME_PROVIDER (legacy);
 }