diff --git a/ChangeLog b/ChangeLog index a39b519ace7123cd2e3acbab956cf5f626e44bfa..1570b563602823440f50a34955b0b2c51b15d1bb 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 84cad84bb0c0a4fc69cbe05b9e9d650bf1114a96..39b0f158d743bde39ec8f4839b7180ece5c26229 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 fb553fe29561878abd68d13b3a09a435681c7024..805719bdddfa38152f4cd8c26a2c1948326b60b8 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 7d7e8ffe5c5c37208b56b3e174fd74cdeda0f1ab..c1d7dc91b6f6dd1162f8bafa77bbd677d2d9ca5c 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); }