From 4d01a84a7bc9808eae25c79d262c829d54cc8848 Mon Sep 17 00:00:00 2001
From: Benedikt Meurer <benny@xfce.org>
Date: Sat, 27 Aug 2005 14:49:13 +0000
Subject: [PATCH] 2005-08-27	Benedikt Meurer <benny@xfce.org>

	* thunar-vfs/thunar-vfs-mime-legacy.c: Add support for MIME-type
	  aliases and parents to the legacy implementation.
	* configure.in.in, thunar-vfs/thunar-vfs-mime-database.c: Add support
	  for determining the MIME type from an extended attribute on SunOS
	  and Linux.




(Old svn revision: 17126)
---
 ChangeLog                             |   8 ++
 configure.in.in                       |   8 +-
 thunar-vfs/thunar-vfs-mime-database.c |  42 ++++++-
 thunar-vfs/thunar-vfs-mime-legacy.c   | 159 +++++++++++++++++++++++++-
 4 files changed, 210 insertions(+), 7 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a39b519ac..1570b5636 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2005-08-27	Benedikt Meurer <benny@xfce.org>
+
+	* thunar-vfs/thunar-vfs-mime-legacy.c: Add support for MIME-type
+	  aliases and parents to the legacy implementation.
+	* configure.in.in, thunar-vfs/thunar-vfs-mime-database.c: Add support
+	  for determining the MIME type from an extended attribute on SunOS
+	  and Linux.
+
 2005-08-22	Benedikt Meurer <benny@xfce.org>
 
 	* thunar/thunar-path-entry.c: Add drag support for the path entry icon.
diff --git a/configure.in.in b/configure.in.in
index 84cad84bb..39b0f158d 100644
--- a/configure.in.in
+++ b/configure.in.in
@@ -70,16 +70,16 @@ AC_SUBST([THUNAR_VERSION_API])
 dnl **********************************
 dnl *** Check for standard headers ***
 dnl **********************************
-AC_CHECK_HEADERS([dirent.h errno.h fcntl.h fnmatch.h fstab.h grp.h locale.h \
-                  math.h memory.h pwd.h stdlib.h string.h \
-                  sys/extattr.h sys/cdio.h sys/mman.h \
+AC_CHECK_HEADERS([dirent.h errno.h fcntl.h fnmatch.h fstab.h \
+                  grp.h locale.h math.h memory.h pwd.h stdlib.h string.h \
+                  sys/xattr.h sys/extattr.h sys/cdio.h sys/mman.h \
                   sys/mount.h sys/stat.h sys/time.h sys/param.h time.h])
 
 dnl ************************************
 dnl *** Check for standard functions ***
 dnl ************************************
 AC_FUNC_MMAP()
-AC_CHECK_FUNCS([extattr_get_fd lchmod localtime_r readdir_r \
+AC_CHECK_FUNCS([attropen extattr_get_fd fgetxattr lchmod localtime_r readdir_r \
                 setgroupent setpassent])
 
 dnl ***************************************
diff --git a/thunar-vfs/thunar-vfs-mime-database.c b/thunar-vfs/thunar-vfs-mime-database.c
index fb553fe29..805719bdd 100644
--- a/thunar-vfs/thunar-vfs-mime-database.c
+++ b/thunar-vfs/thunar-vfs-mime-database.c
@@ -34,6 +34,9 @@
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
 #endif
+#ifdef HAVE_SYS_XATTR_H
+#include <sys/xattr.h>
+#endif
 
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
@@ -986,6 +989,29 @@ thunar_vfs_mime_database_get_info_for_file (ThunarVfsMimeDatabase *database,
   info = thunar_vfs_mime_database_get_info_for_name_locked (database, name);
   g_mutex_unlock (database->lock);
 
+#ifdef HAVE_ATTROPEN
+  /* check if we have a valid mime type stored in the extattr (SunOS) */
+  if (G_UNLIKELY (info == NULL))
+    {
+      fd = attropen (path, "user.mime_type", O_RDONLY);
+      if (G_UNLIKELY (fd >= 0))
+        {
+          if (fstat (fd, &stat) == 0)
+            {
+              buffer = g_new (gchar, stat.st_size + 1);
+              nbytes = read (fd, buffer, stat.st_size);
+              if (G_LIKELY (nbytes >= 3))
+                {
+                  buffer[nbytes] = '\0';
+                  info = thunar_vfs_mime_database_get_info (database, buffer);
+                }
+              g_free (buffer);
+            }
+          close (fd);
+        }
+    }
+#endif
+
   /* try to determine the type from the file content */
   if (G_UNLIKELY (info == NULL))
     {
@@ -993,7 +1019,7 @@ thunar_vfs_mime_database_get_info_for_file (ThunarVfsMimeDatabase *database,
       if (G_LIKELY (fd >= 0))
         {
 #ifdef HAVE_EXTATTR_GET_FD
-          /* check if we have a valid mime type stored in the extattr */
+          /* check if we have a valid mime type stored in the extattr (TrustedBSD) */
           nbytes = extattr_get_fd (fd, EXTATTR_NAMESPACE_USER, "mime_type", NULL, 0);
           if (G_UNLIKELY (nbytes >= 3))
             {
@@ -1006,6 +1032,20 @@ thunar_vfs_mime_database_get_info_for_file (ThunarVfsMimeDatabase *database,
                 }
               g_free (buffer);
             }
+#elif defined(HAVE_FGETXATTR)
+          /* check for valid mime type stored in the extattr (Linux) */
+          nbytes = fgetxattr (fd, "user.mime_type", NULL, 0);
+          if (G_UNLIKELY (nbytes >= 3))
+            {
+              buffer = g_new (gchar, nbytes + 1);
+              nbytes = fgetxattr (fd, "user.mime_type", buffer, nbytes);
+              if (G_LIKELY (nbytes >= 3))
+                {
+                  buffer[nbytes] = '\0';
+                  info = thunar_vfs_mime_database_get_info (database, buffer);
+                }
+              g_free (buffer);
+            }
 #endif
 
           /* stat the file and verify that we have a regular file, which is not empty */
diff --git a/thunar-vfs/thunar-vfs-mime-legacy.c b/thunar-vfs/thunar-vfs-mime-legacy.c
index 7d7e8ffe5..c1d7dc91b 100644
--- a/thunar-vfs/thunar-vfs-mime-legacy.c
+++ b/thunar-vfs/thunar-vfs-mime-legacy.c
@@ -71,8 +71,12 @@ static guint        thunar_vfs_mime_legacy_lookup_parents         (ThunarVfsMime
                                                                    guint                     max_parents);
 static GList       *thunar_vfs_mime_legacy_get_stop_characters    (ThunarVfsMimeProvider    *provider);
 static gsize        thunar_vfs_mime_legacy_get_max_buffer_extents (ThunarVfsMimeProvider    *provider);
+static void         thunar_vfs_mime_legacy_parse_aliases          (ThunarVfsMimeLegacy      *legacy,
+                                                                   const gchar              *directory);
 static gboolean     thunar_vfs_mime_legacy_parse_globs            (ThunarVfsMimeLegacy      *legacy,
                                                                    const gchar              *directory);
+static void         thunar_vfs_mime_legacy_parse_subclasses       (ThunarVfsMimeLegacy      *legacy,
+                                                                   const gchar              *directory);
 
 
 
@@ -92,6 +96,9 @@ struct _ThunarVfsMimeLegacy
   GHashTable                *literals;
   ThunarVfsMimeLegacySuffix *suffixes;
   GList                     *globs;
+
+  GHashTable                *aliases;
+  GHashTable                *parents;
 };
 
 struct _ThunarVfsMimeLegacyGlob
@@ -176,6 +183,9 @@ thunar_vfs_mime_legacy_init (ThunarVfsMimeLegacy *legacy)
   legacy->suffix_chunk = g_mem_chunk_create (ThunarVfsMimeLegacySuffix, 128, G_ALLOC_ONLY);
 
   legacy->literals = g_hash_table_new (g_str_hash, g_str_equal);
+
+  legacy->aliases = g_hash_table_new (g_str_hash, g_str_equal);
+  legacy->parents = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_list_free);
 }
 
 
@@ -185,6 +195,12 @@ thunar_vfs_mime_legacy_finalize (ExoObject *object)
 {
   ThunarVfsMimeLegacy *legacy = THUNAR_VFS_MIME_LEGACY (object);
 
+  /* free parents hash table */
+  g_hash_table_destroy (legacy->parents);
+
+  /* free aliases hash table */
+  g_hash_table_destroy (legacy->aliases);
+
   /* free the list of globs */
   g_list_free (legacy->globs);
 
@@ -344,7 +360,7 @@ static const gchar*
 thunar_vfs_mime_legacy_lookup_alias (ThunarVfsMimeProvider *provider,
                                      const gchar           *alias)
 {
-  return NULL;
+  return g_hash_table_lookup (THUNAR_VFS_MIME_LEGACY (provider)->aliases, alias);
 }
 
 
@@ -355,7 +371,15 @@ thunar_vfs_mime_legacy_lookup_parents (ThunarVfsMimeProvider *provider,
                                        gchar                **parents,
                                        guint                  max_parents)
 {
-  return 0;
+  GList *lp;
+  guint  n = 0;
+
+  /* determine the known parents for the MIME-type */
+  lp = g_hash_table_lookup (THUNAR_VFS_MIME_LEGACY (provider)->parents, mime_type);
+  for (; lp != NULL && n < max_parents; lp = lp->next, ++n, ++parents)
+    *parents = lp->data;
+
+  return n;
 }
 
 
@@ -383,6 +407,66 @@ thunar_vfs_mime_legacy_get_max_buffer_extents (ThunarVfsMimeProvider *provider)
 
 
 
+static void
+thunar_vfs_mime_legacy_parse_aliases (ThunarVfsMimeLegacy *legacy,
+                                      const gchar         *directory)
+{
+  gchar  line[2048];
+  gchar *alias;
+  gchar *name;
+  gchar *path;
+  gchar *lp;
+  FILE  *fp;
+
+  /* try to open the "aliases" file */
+  path = g_build_filename (directory, "aliases", NULL);
+  fp = fopen (path, "r");
+  g_free (path);
+
+  /* check if we succeed */
+  if (G_UNLIKELY (fp == NULL))
+    return;
+
+  /* parse all aliases */
+  while (fgets (line, sizeof (line), fp) != NULL)
+    {
+      /* skip whitespace/comments */
+      for (lp = line; g_ascii_isspace (*lp); ++lp);
+      if (G_UNLIKELY (*lp == '\0' || *lp == '#'))
+        continue;
+
+      /* extract the alias name */
+      for (alias = lp; *lp != '\0' && !g_ascii_isspace (*lp); ++lp);
+      if (G_UNLIKELY (*lp == '\0' || alias == lp))
+        continue;
+      *lp++ = '\0';
+
+      /* skip whitespace */
+      for (; G_UNLIKELY (g_ascii_isspace (*lp)); ++lp);
+      if (G_UNLIKELY (*lp == '\0'))
+        continue;
+
+      /* extract the MIME-type name */
+      for (name = lp; *lp != '\0' && *lp != '\n' && *lp != '\r'; ++lp);
+      if (G_UNLIKELY (name == lp))
+        continue;
+      *lp = '\0';
+
+      /* insert the alias into the string chunk */
+      alias = g_string_chunk_insert_const (legacy->string_chunk, alias);
+
+      /* insert the MIME-type name into the string chunk */
+      name = g_string_chunk_insert_const (legacy->string_chunk, name);
+
+      /* insert the association into the aliases hash table */
+      g_hash_table_insert (legacy->aliases, alias, name);
+    }
+
+  fclose (fp);
+}
+
+
+
 static gboolean
 thunar_vfs_mime_legacy_parse_globs (ThunarVfsMimeLegacy *legacy,
                                     const gchar         *directory)
@@ -451,6 +535,71 @@ thunar_vfs_mime_legacy_parse_globs (ThunarVfsMimeLegacy *legacy,
 
 
 
+static void
+thunar_vfs_mime_legacy_parse_subclasses (ThunarVfsMimeLegacy *legacy,
+                                         const gchar         *directory)
+{
+  gchar  line[2048];
+  GList *parents;
+  gchar *subclass;
+  gchar *name;
+  gchar *path;
+  gchar *lp;
+  FILE  *fp;
+
+  /* try to open the "subclasses" file */
+  path = g_build_filename (directory, "subclasses", NULL);
+  fp = fopen (path, "r");
+  g_free (path);
+
+  /* check if we succeed */
+  if (G_UNLIKELY (fp == NULL))
+    return;
+
+  /* parse all subclasses */
+  while (fgets (line, sizeof (line), fp) != NULL)
+    {
+      /* skip whitespace/comments */
+      for (lp = line; g_ascii_isspace (*lp); ++lp);
+      if (G_UNLIKELY (*lp == '\0' || *lp == '#'))
+        continue;
+
+      /* extract the subclass name */
+      for (subclass = lp; *lp != '\0' && !g_ascii_isspace (*lp); ++lp);
+      if (G_UNLIKELY (*lp == '\0' || subclass == lp))
+        continue;
+      *lp++ = '\0';
+
+      /* skip whitespace */
+      for (; G_UNLIKELY (g_ascii_isspace (*lp)); ++lp);
+      if (G_UNLIKELY (*lp == '\0'))
+        continue;
+
+      /* extract the MIME-type name */
+      for (name = lp; *lp != '\0' && *lp != '\n' && *lp != '\r'; ++lp);
+      if (G_UNLIKELY (name == lp))
+        continue;
+      *lp = '\0';
+
+      /* insert the subclass into the string chunk */
+      subclass = g_string_chunk_insert_const (legacy->string_chunk, subclass);
+
+      /* insert the MIME-type name into the string chunk */
+      name = g_string_chunk_insert_const (legacy->string_chunk, name);
+
+      /* add the MIME-type name to the list of parents for the subclass */
+      parents = g_hash_table_lookup (legacy->parents, subclass);
+      if (G_UNLIKELY (parents != NULL))
+        parents = g_list_copy (parents);
+      parents = g_list_append (parents, name);
+      g_hash_table_insert (legacy->parents, subclass, parents);
+    }
+
+  fclose (fp);
+}
+
+
+
 /**
  * thunar_vfs_mime_legacy_new:
  * @directory : an XDG mime base directory.
@@ -479,6 +628,12 @@ thunar_vfs_mime_legacy_new (const gchar *directory)
       return NULL;
     }
 
+  /* parse the aliases file (optional) */
+  thunar_vfs_mime_legacy_parse_aliases (legacy, directory);
+
+  /* parse the subclasses file (optional) */
+  thunar_vfs_mime_legacy_parse_subclasses (legacy, directory);
+
   /* we got it */
   return THUNAR_VFS_MIME_PROVIDER (legacy);
 }
-- 
GitLab