From 2c1bfce38da557bd20019689c15cd03881863097 Mon Sep 17 00:00:00 2001
From: Benedikt Meurer <benny@xfce.org>
Date: Fri, 1 Jul 2005 22:55:40 +0000
Subject: [PATCH] 2005-07-02	Benedikt Meurer <benny@xfce.org>

	* configure.in.in: Add checks for functions used in the user module.
	* thunar-vfs/thunar-vfs-user.{c,h}: Add a user module to the VFS
	  library, which is extensible and performs some caching to reduce
	  the overhead caused by the underlying NSS implementation.
	* docs/papers/HackingOnThunar.odt: Add comments about the newly added
	  ThunarVfsUser module.
	* thunar-vfs/thunar-vfs-info.h: Add ThunarVfsUserId and ThunarVfsGroupId
	  typedefs.
	* thunar-vfs/thunar-vfs.h, thunar-vfs/Makefile.am: Add the new
	  ThunarVfsUser module to the build framework.
	* thunar/thunar-file.{c,h}, thunar/thunar-local-file.c,
	  thunar/thunar-trash-file.c: Add two new methods to the ThunarFile
	  class - get_group() and get_user() - and add an implementation of
	  these methods to the local and trash backends.




(Old svn revision: 16363)
---
 ChangeLog                       |  17 +
 configure.in.in                 |   6 +-
 docs/papers/HackingOnThunar.odt | Bin 16367 -> 16595 bytes
 thunar-vfs/Makefile.am          |   2 +
 thunar-vfs/thunar-vfs-info.h    |  16 +-
 thunar-vfs/thunar-vfs-user.c    | 938 ++++++++++++++++++++++++++++++++
 thunar-vfs/thunar-vfs-user.h    | 129 +++++
 thunar-vfs/thunar-vfs.h         |   1 +
 thunar/thunar-file.c            | 100 +++-
 thunar/thunar-file.h            |   6 +
 thunar/thunar-local-file.c      |  27 +
 thunar/thunar-trash-file.c      |  20 +
 12 files changed, 1239 insertions(+), 23 deletions(-)
 create mode 100644 thunar-vfs/thunar-vfs-user.c
 create mode 100644 thunar-vfs/thunar-vfs-user.h

diff --git a/ChangeLog b/ChangeLog
index 8585c8095..32d9a1b27 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2005-07-02	Benedikt Meurer <benny@xfce.org>
+
+	* configure.in.in: Add checks for functions used in the user module.
+	* thunar-vfs/thunar-vfs-user.{c,h}: Add a user module to the VFS
+	  library, which is extensible and performs some caching to reduce
+	  the overhead caused by the underlying NSS implementation.
+	* docs/papers/HackingOnThunar.odt: Add comments about the newly added
+	  ThunarVfsUser module.
+	* thunar-vfs/thunar-vfs-info.h: Add ThunarVfsUserId and ThunarVfsGroupId
+	  typedefs.
+	* thunar-vfs/thunar-vfs.h, thunar-vfs/Makefile.am: Add the new
+	  ThunarVfsUser module to the build framework.
+	* thunar/thunar-file.{c,h}, thunar/thunar-local-file.c,
+	  thunar/thunar-trash-file.c: Add two new methods to the ThunarFile
+	  class - get_group() and get_user() - and add an implementation of
+	  these methods to the local and trash backends.
+
 2005-06-29	Benedikt Meurer <benny@xfce.org>
 
 	* thunar/thunar-details-view-icon-renderer.c
diff --git a/configure.in.in b/configure.in.in
index 9502fe587..41426884b 100644
--- a/configure.in.in
+++ b/configure.in.in
@@ -41,12 +41,12 @@ AC_PROG_INSTALL()
 AC_PROG_LIBTOOL()
 
 dnl Check for standard headers
-AC_CHECK_HEADERS([errno.h fcntl.h fstab.h memory.h stdlib.h string.h \
-                  sys/cdio.h sys/event.h \
+AC_CHECK_HEADERS([errno.h fcntl.h fstab.h grp.h memory.h pwd.h \
+                  stdlib.h string.h sys/cdio.h sys/event.h \
                   sys/mount.h sys/stat.h sys/time.h sys/param.h time.h])
 
 dnl Check for standard functions
-AC_CHECK_FUNCS([kqueue localtime_r])
+AC_CHECK_FUNCS([kqueue localtime_r setgroupent setpassent])
 
 dnl Check for required packages
 XDT_CHECK_PACKAGE([EXO], [exo-0.3], [0.3.1])
diff --git a/docs/papers/HackingOnThunar.odt b/docs/papers/HackingOnThunar.odt
index 08be983bb8f0571eb3e043092adc637e88e49475..c2ff310f16ba07fdb5b5d9b5b8006dab147686f3 100644
GIT binary patch
delta 12409
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
M2-8A43jH<yKTOwsrvLx|

delta 12042
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

diff --git a/thunar-vfs/Makefile.am b/thunar-vfs/Makefile.am
index 8d176d2f5..78f760f54 100644
--- a/thunar-vfs/Makefile.am
+++ b/thunar-vfs/Makefile.am
@@ -17,6 +17,7 @@ libthunar_vfs_headers =							\
 	thunar-vfs-info.h						\
 	thunar-vfs-monitor.h						\
 	thunar-vfs-trash.h						\
+	thunar-vfs-user.h						\
 	thunar-vfs-util.h						\
 	thunar-vfs-uri.h						\
 	thunar-vfs-volume.h						\
@@ -28,6 +29,7 @@ libthunar_vfs_la_SOURCES =						\
 	thunar-vfs-info.c						\
 	thunar-vfs-monitor.c						\
 	thunar-vfs-trash.c						\
+	thunar-vfs-user.c						\
 	thunar-vfs-util.c						\
 	thunar-vfs-uri.c						\
 	thunar-vfs-volume.c						\
diff --git a/thunar-vfs/thunar-vfs-info.h b/thunar-vfs/thunar-vfs-info.h
index b62495557..6d1ab3eff 100644
--- a/thunar-vfs/thunar-vfs-info.h
+++ b/thunar-vfs/thunar-vfs-info.h
@@ -134,6 +134,18 @@ typedef off_t ThunarVfsFileSize;
  **/
 typedef time_t ThunarVfsFileTime;
 
+/**
+ * ThunarVfsGroupId:
+ * Datatype to represent a group id.
+ **/
+typedef gid_t ThunarVfsGroupId;
+
+/**
+ * ThunarVfsUserId:
+ * Datatype to represent a user id.
+ **/
+typedef uid_t ThunarVfsUserId;
+
 /**
  * ThunarVfsInfo:
  *
@@ -152,10 +164,10 @@ typedef struct
   ThunarVfsFileFlags flags;
 
   /* Owner's user id */
-  uid_t uid;
+  ThunarVfsUserId uid;
 
   /* Owner's group id */
-  gid_t gid;
+  ThunarVfsGroupId gid;
 
   /* Size in bytes */
   ThunarVfsFileSize size;
diff --git a/thunar-vfs/thunar-vfs-user.c b/thunar-vfs/thunar-vfs-user.c
new file mode 100644
index 000000000..7c6f4ec1a
--- /dev/null
+++ b/thunar-vfs/thunar-vfs-user.c
@@ -0,0 +1,938 @@
+/* $Id$ */
+/*-
+ * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <thunar-vfs/thunar-vfs-user.h>
+
+
+
+/* the interval in which the user/group cache is flushed (in ms) */
+#define THUNAR_VFS_USER_MANAGER_FLUSH_INTERVAL (10 * 60 * 1000)
+
+
+
+GType
+thunar_vfs_group_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GTypeInfo info =
+      {
+        sizeof (ThunarVfsGroupClass),
+        NULL,
+        NULL,
+        NULL,
+        NULL,
+        NULL,
+        sizeof (ThunarVfsGroup),
+        0,
+        NULL,
+        NULL,
+      };
+
+      type = g_type_register_static (G_TYPE_OBJECT, "ThunarVfsGroup",
+                                     &info, G_TYPE_FLAG_ABSTRACT);
+    }
+
+  return type;
+}
+
+
+
+/**
+ * thunar_vfs_group_get_id:
+ * @group : a #ThunarVfsGroup.
+ *
+ * Returns the unique id of the given @group.
+ *
+ * Return value: the unique id of @group.
+ **/
+ThunarVfsGroupId
+thunar_vfs_group_get_id (ThunarVfsGroup *group)
+{
+  g_return_val_if_fail (THUNAR_VFS_IS_GROUP (group), 0);
+  return THUNAR_VFS_GROUP_GET_CLASS (group)->get_id (group);
+}
+
+
+
+/**
+ * thunar_vfs_group_get_name:
+ * @group : a #ThunarVfsGroup.
+ *
+ * Returns the name of the @group. If the system is
+ * unable to determine the name of @group, it'll
+ * return the group id as string.
+ *
+ * Return value: the name of @group.
+ **/
+const gchar*
+thunar_vfs_group_get_name (ThunarVfsGroup *group)
+{
+  g_return_val_if_fail (THUNAR_VFS_IS_GROUP (group), NULL);
+  return THUNAR_VFS_GROUP_GET_CLASS (group)->get_name (group);
+}
+
+
+
+
+GType
+thunar_vfs_user_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GTypeInfo info =
+      {
+        sizeof (ThunarVfsUserClass),
+        NULL,
+        NULL,
+        NULL,
+        NULL,
+        NULL,
+        sizeof (ThunarVfsUser),
+        0,
+        NULL,
+        NULL,
+      };
+
+      type = g_type_register_static (G_TYPE_OBJECT, "ThunarVfsUser",
+                                     &info, G_TYPE_FLAG_ABSTRACT);
+    }
+
+  return type;
+}
+
+
+
+/**
+ * thunar_vfs_user_get_groups:
+ * @user : a #ThunarVfsUser.
+ *
+ * Returns all #ThunarVfsGroup<!---->s that @user
+ * belongs to. The returned list and the #ThunarVfsGroup<!---->s
+ * contained within the list are owned by @user and must not be
+ * freed or altered by the caller.
+ *
+ * Note that if @user has a primary group, this group will
+ * also be contained in the returned list.
+ *
+ * Return value: the groups that @user belongs to.
+ **/
+GList*
+thunar_vfs_user_get_groups (ThunarVfsUser *user)
+{
+  g_return_val_if_fail (THUNAR_VFS_IS_USER (user), NULL);
+  return THUNAR_VFS_USER_GET_CLASS (user)->get_groups (user);
+}
+
+
+
+/**
+ * thunar_vfs_user_get_primary_group:
+ * @user : a #ThunarVfsUser.
+ *
+ * Returns the primary group of @user or %NULL if @user
+ * has no primary group.
+ *
+ * No reference is taken for the caller, so you must
+ * not call #g_object_unref() on the returned object.
+ *
+ * Return value: the primary group of @user or %NULL.
+ **/
+ThunarVfsGroup*
+thunar_vfs_user_get_primary_group (ThunarVfsUser *user)
+{
+  g_return_val_if_fail (THUNAR_VFS_IS_USER (user), NULL);
+  return THUNAR_VFS_USER_GET_CLASS (user)->get_primary_group (user);
+}
+
+
+
+/**
+ * thunar_vfs_user_get_id:
+ * @user : a #ThunarVfsUser.
+ *
+ * Returns the unique id of @user.
+ *
+ * Return value: the unique id of @user.
+ **/
+ThunarVfsUserId
+thunar_vfs_user_get_id (ThunarVfsUser *user)
+{
+  g_return_val_if_fail (THUNAR_VFS_IS_USER (user), 0);
+  return THUNAR_VFS_USER_GET_CLASS (user)->get_id (user);
+}
+
+
+
+/**
+ * thunar_vfs_user_get_name:
+ * @user : a #ThunarVfsUser.
+ *
+ * Returns the name of @user. If the system is
+ * unable to determine the account name of @user,
+ * it'll return the user id as string.
+ *
+ * Return value: the name of @user.
+ **/
+const gchar*
+thunar_vfs_user_get_name (ThunarVfsUser *user)
+{
+  g_return_val_if_fail (THUNAR_VFS_IS_USER (user), 0);
+  return THUNAR_VFS_USER_GET_CLASS (user)->get_name (user);
+}
+
+
+
+/**
+ * thunar_vfs_user_get_real_name:
+ * @user : a #ThunarVfsUser.
+ *
+ * Returns the real name of @user or %NULL if the
+ * real name for @user is not known to the underlying
+ * system.
+ *
+ * Return value: the real name for @user or %NULL.
+ **/
+const gchar*
+thunar_vfs_user_get_real_name (ThunarVfsUser *user)
+{
+  g_return_val_if_fail (THUNAR_VFS_IS_USER (user), 0);
+  return THUNAR_VFS_USER_GET_CLASS (user)->get_real_name (user);
+}
+
+
+
+/**
+ * thunar_vfs_user_is_me:
+ * @user : a #ThunarVfsUser.
+ *
+ * Checks whether the owner of the current process is
+ * described by @user.
+ *
+ * Return value: %TRUE if @user is the owner of the current
+ *               process, else %FALSE.
+ **/
+gboolean
+thunar_vfs_user_is_me (ThunarVfsUser *user)
+{
+  g_return_val_if_fail (THUNAR_VFS_IS_USER (user), FALSE);
+  return THUNAR_VFS_USER_GET_CLASS (user)->is_me (user);
+}
+
+
+
+
+typedef struct _ThunarVfsLocalGroupClass ThunarVfsLocalGroupClass;
+typedef struct _ThunarVfsLocalGroup      ThunarVfsLocalGroup;
+
+
+
+#define THUNAR_VFS_TYPE_LOCAL_GROUP             (thunar_vfs_local_group_get_type ())
+#define THUNAR_VFS_LOCAL_GROUP(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_LOCAL_GROUP, ThunarVfsLocalGroup))
+#define THUNAR_VFS_LOCAL_GROUP_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_LOCAL_GROUP, ThunarVfsLocalGroupClass))
+#define THUNAR_VFS_IS_LOCAL_GROUP(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_LOCAL_GROUP))
+#define THUNAR_VFS_IS_LOCAL_GROUP_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_LOCAL_GROUP))
+#define THUNAR_VFS_LOCAL_GROUP_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_LOCAL_GROUP, ThunarVfsLocalGroupClass))
+
+
+
+static GType            thunar_vfs_local_group_get_type   (void) G_GNUC_CONST;
+static void             thunar_vfs_local_group_class_init (ThunarVfsLocalGroupClass *klass);
+static void             thunar_vfs_local_group_finalize   (GObject                  *object);
+static ThunarVfsGroupId thunar_vfs_local_group_get_id     (ThunarVfsGroup           *group);
+static const gchar     *thunar_vfs_local_group_get_name   (ThunarVfsGroup           *group);
+static ThunarVfsGroup  *thunar_vfs_local_group_new        (ThunarVfsGroupId          id);
+
+
+
+struct _ThunarVfsLocalGroupClass
+{
+  ThunarVfsGroupClass __parent__;
+};
+
+struct _ThunarVfsLocalGroup
+{
+  ThunarVfsGroup __parent__;
+
+  ThunarVfsGroupId id;
+  gchar           *name;
+};
+
+
+
+static GObjectClass *thunar_vfs_local_group_parent_class;
+
+
+
+static GType
+thunar_vfs_local_group_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GTypeInfo info =
+      {
+        sizeof (ThunarVfsLocalGroupClass),
+        NULL,
+        NULL,
+        (GClassInitFunc) thunar_vfs_local_group_class_init,
+        NULL,
+        NULL,
+        sizeof (ThunarVfsLocalGroup),
+        0,
+        NULL,
+        NULL,
+      };
+
+      type = g_type_register_static (THUNAR_VFS_TYPE_GROUP,
+                                     "ThunarVfsLocalGroup",
+                                     &info, 0);
+    }
+
+  return type;
+}
+
+
+
+static void
+thunar_vfs_local_group_class_init (ThunarVfsLocalGroupClass *klass)
+{
+  ThunarVfsGroupClass *thunarvfs_group_class;
+  GObjectClass        *gobject_class;
+
+  thunar_vfs_local_group_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = thunar_vfs_local_group_finalize;
+
+  thunarvfs_group_class = THUNAR_VFS_GROUP_CLASS (klass);
+  thunarvfs_group_class->get_id = thunar_vfs_local_group_get_id;
+  thunarvfs_group_class->get_name = thunar_vfs_local_group_get_name;
+}
+
+
+
+static void
+thunar_vfs_local_group_finalize (GObject *object)
+{
+  ThunarVfsLocalGroup *local_group = THUNAR_VFS_LOCAL_GROUP (object);
+
+  /* free the group name */
+  g_free (local_group->name);
+
+  G_OBJECT_CLASS (thunar_vfs_local_group_parent_class)->finalize (object);
+}
+
+
+
+static ThunarVfsGroupId
+thunar_vfs_local_group_get_id (ThunarVfsGroup *group)
+{
+  return THUNAR_VFS_LOCAL_GROUP (group)->id;
+}
+
+
+
+static const gchar*
+thunar_vfs_local_group_get_name (ThunarVfsGroup *group)
+{
+  ThunarVfsLocalGroup *local_group = THUNAR_VFS_LOCAL_GROUP (group);
+  struct group        *grp;
+
+  /* determine the name on-demand */
+  if (G_UNLIKELY (local_group->name == NULL))
+    {
+      grp = getgrgid (local_group->id);
+      if (G_LIKELY (grp != NULL))
+        local_group->name = g_strdup (grp->gr_name);
+      else
+        local_group->name = g_strdup_printf ("%u", (guint) local_group->id);
+    }
+
+  return local_group->name;
+}
+
+
+
+static ThunarVfsGroup*
+thunar_vfs_local_group_new (ThunarVfsGroupId id)
+{
+  ThunarVfsLocalGroup *local_group;
+
+  local_group = g_object_new (THUNAR_VFS_TYPE_LOCAL_GROUP, NULL);
+  local_group->id = id;
+
+  return THUNAR_VFS_GROUP (local_group);
+}
+
+
+
+
+typedef struct _ThunarVfsLocalUserClass ThunarVfsLocalUserClass;
+typedef struct _ThunarVfsLocalUser      ThunarVfsLocalUser;
+
+
+
+#define THUNAR_VFS_TYPE_LOCAL_USER            (thunar_vfs_local_user_get_type ())
+#define THUNAR_VFS_LOCAL_USER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_LOCAL_USER, ThunarVfsLocalUser))
+#define THUNAR_VFS_LOCAL_USER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_LOCAL_USER, ThunarVfsLocalUserClass))
+#define THUNAR_VFS_IS_LOCAL_USER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_LOCAL_USER))
+#define THUNAR_VFS_IS_LOCAL_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_LOCAL_USER))
+#define THUNAR_VFS_LOCAL_USER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_LOCAL_USER, ThunarVfsLocalUserClass))
+
+
+
+static GType           thunar_vfs_local_user_get_type          (void) G_GNUC_CONST;
+static void            thunar_vfs_local_user_class_init        (ThunarVfsLocalUserClass *klass);
+static void            thunar_vfs_local_user_finalize          (GObject                 *object);
+static GList          *thunar_vfs_local_user_get_groups        (ThunarVfsUser           *user);
+static ThunarVfsGroup *thunar_vfs_local_user_get_primary_group (ThunarVfsUser           *user);
+static ThunarVfsUserId thunar_vfs_local_user_get_id            (ThunarVfsUser           *user);
+static const gchar    *thunar_vfs_local_user_get_name          (ThunarVfsUser           *user);
+static const gchar    *thunar_vfs_local_user_get_real_name     (ThunarVfsUser           *user);
+static gboolean        thunar_vfs_local_user_is_me             (ThunarVfsUser           *user);
+static void            thunar_vfs_local_user_load              (ThunarVfsLocalUser      *local_user);
+static ThunarVfsUser  *thunar_vfs_local_user_new               (ThunarVfsUserId          id);
+
+
+
+struct _ThunarVfsLocalUserClass
+{
+  ThunarVfsUserClass __parent__;
+
+  ThunarVfsUserId effective_uid;
+};
+
+struct _ThunarVfsLocalUser
+{
+  ThunarVfsUser __parent__;
+
+  GList          *groups;
+  ThunarVfsGroup *primary_group;
+  ThunarVfsUserId id;
+  gchar          *name;
+  gchar          *real_name;
+};
+
+
+
+static GObjectClass *thunar_vfs_local_user_parent_class;
+
+
+
+static GType
+thunar_vfs_local_user_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GTypeInfo info =
+      {
+        sizeof (ThunarVfsLocalUserClass),
+        NULL,
+        NULL,
+        (GClassInitFunc) thunar_vfs_local_user_class_init,
+        NULL,
+        NULL,
+        sizeof (ThunarVfsLocalUser),
+        0,
+        NULL,
+        NULL,
+      };
+
+      type = g_type_register_static (THUNAR_VFS_TYPE_USER,
+                                     "ThunarVfsLocalUser",
+                                     &info, 0);
+    }
+
+  return type;
+}
+
+
+
+static void
+thunar_vfs_local_user_class_init (ThunarVfsLocalUserClass *klass)
+{
+  ThunarVfsUserClass *thunarvfs_user_class;
+  GObjectClass       *gobject_class;
+
+  /* determine the current process' effective user id, we do
+   * this only once to avoid the syscall overhead on every
+   * is_me() invokation.
+   */
+  klass->effective_uid = geteuid ();
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = thunar_vfs_local_user_finalize;
+
+  thunarvfs_user_class = THUNAR_VFS_USER_CLASS (klass);
+  thunarvfs_user_class->get_groups = thunar_vfs_local_user_get_groups;
+  thunarvfs_user_class->get_primary_group = thunar_vfs_local_user_get_primary_group;
+  thunarvfs_user_class->get_id = thunar_vfs_local_user_get_id;
+  thunarvfs_user_class->get_name = thunar_vfs_local_user_get_name;
+  thunarvfs_user_class->get_real_name = thunar_vfs_local_user_get_real_name;
+  thunarvfs_user_class->is_me = thunar_vfs_local_user_is_me;
+}
+
+
+
+static void
+thunar_vfs_local_user_finalize (GObject *object)
+{
+  ThunarVfsLocalUser *local_user = THUNAR_VFS_LOCAL_USER (object);
+  GList              *lp;
+
+  /* unref the associated groups */
+  for (lp = local_user->groups; lp != NULL; lp = lp->next)
+    g_object_unref (G_OBJECT (lp->data));
+  g_list_free (local_user->groups);
+
+  /* drop the ref on the primary group */
+  if (G_LIKELY (local_user->primary_group != NULL))
+    g_object_unref (G_OBJECT (local_user->primary_group));
+
+  /* free the names */
+  g_free (local_user->real_name);
+  g_free (local_user->name);
+
+  G_OBJECT_CLASS (thunar_vfs_local_user_parent_class)->finalize (object);
+}
+
+
+
+static GList*
+thunar_vfs_local_user_get_groups (ThunarVfsUser *user)
+{
+  ThunarVfsUserManager *manager;
+  ThunarVfsLocalUser   *local_user = THUNAR_VFS_LOCAL_USER (user);
+  ThunarVfsGroup       *primary_group;
+  ThunarVfsGroup       *group;
+  gid_t                 gidset[NGROUPS_MAX];
+  gint                  gidsetlen;
+  gint                  n;
+
+  /* load the groups on-demand */
+  if (G_UNLIKELY (local_user->groups == NULL))
+    {
+      primary_group = thunar_vfs_local_user_get_primary_group (user);
+
+      /* we can only determine the groups list for the current
+       * process owner in a portable fashion, and in fact, we
+       * only need the list for the current user.
+       */
+      if (thunar_vfs_local_user_is_me (user))
+        {
+          manager = thunar_vfs_user_manager_get_default ();
+
+          /* add all supplementary groups */
+          gidsetlen = getgroups (G_N_ELEMENTS (gidset), gidset);
+          for (n = 0; n < gidsetlen; ++n)
+            if (primary_group == NULL || thunar_vfs_group_get_id (primary_group) != gidset[n])
+              {
+                group = thunar_vfs_user_manager_get_group_by_id (manager, gidset[n]);
+                if (G_LIKELY (group != NULL))
+                  local_user->groups = g_list_append (local_user->groups, group);
+              }
+
+          g_object_unref (G_OBJECT (manager));
+        }
+
+      /* prepend the primary group (if any) */
+      if (G_LIKELY (primary_group != NULL))
+        {
+          local_user->groups = g_list_prepend (local_user->groups, primary_group);
+          g_object_ref (G_OBJECT (primary_group));
+        }
+    }
+
+  return local_user->groups;
+}
+
+
+
+static ThunarVfsGroup*
+thunar_vfs_local_user_get_primary_group (ThunarVfsUser *user)
+{
+  ThunarVfsLocalUser *local_user = THUNAR_VFS_LOCAL_USER (user);
+
+  if (G_UNLIKELY (local_user->name == NULL))
+    thunar_vfs_local_user_load (local_user);
+
+  return local_user->primary_group;
+}
+
+
+
+static ThunarVfsUserId
+thunar_vfs_local_user_get_id (ThunarVfsUser *user)
+{
+  return THUNAR_VFS_LOCAL_USER (user)->id;
+}
+
+
+
+static const gchar*
+thunar_vfs_local_user_get_name (ThunarVfsUser *user)
+{
+  ThunarVfsLocalUser *local_user = THUNAR_VFS_LOCAL_USER (user);
+
+  if (G_UNLIKELY (local_user->name == NULL))
+    thunar_vfs_local_user_load (local_user);
+
+  return local_user->name;
+}
+
+
+
+static const gchar*
+thunar_vfs_local_user_get_real_name (ThunarVfsUser *user)
+{
+  ThunarVfsLocalUser *local_user = THUNAR_VFS_LOCAL_USER (user);
+
+  if (G_UNLIKELY (local_user->name == NULL))
+    thunar_vfs_local_user_load (local_user);
+
+  return local_user->real_name;
+}
+
+
+
+static gboolean
+thunar_vfs_local_user_is_me (ThunarVfsUser *user)
+{
+  return (THUNAR_VFS_LOCAL_USER (user)->id == THUNAR_VFS_LOCAL_USER_GET_CLASS (user)->effective_uid);
+}
+
+
+
+static void
+thunar_vfs_local_user_load (ThunarVfsLocalUser *local_user)
+{
+  ThunarVfsUserManager *manager;
+  struct passwd        *pw;
+  const gchar          *s;
+
+  g_return_if_fail (local_user->name == NULL);
+
+  pw = getpwuid (local_user->id);
+  if (G_LIKELY (pw != NULL))
+    {
+      manager = thunar_vfs_user_manager_get_default ();
+
+      /* query name and primary group */
+      local_user->name = g_strdup (pw->pw_name);
+      local_user->primary_group = thunar_vfs_user_manager_get_group_by_id (manager, pw->pw_gid);
+
+      /* try to figure out the real name */
+      s = strchr (pw->pw_gecos, ',');
+      if (s != NULL)
+        local_user->real_name = g_strndup (pw->pw_gecos, s - pw->pw_gecos);
+      else if (pw->pw_gecos[0] != '\0')
+        local_user->real_name = g_strdup (pw->pw_gecos);
+
+      g_object_unref (G_OBJECT (manager));
+    }
+  else
+    {
+      local_user->name = g_strdup_printf ("%u", (guint) local_user->id);
+    }
+}
+
+
+
+static ThunarVfsUser*
+thunar_vfs_local_user_new (ThunarVfsUserId id)
+{
+  ThunarVfsLocalUser *local_user;
+
+  local_user = g_object_new (THUNAR_VFS_TYPE_LOCAL_USER, NULL);
+  local_user->id = id;
+
+  return THUNAR_VFS_USER (local_user);
+}
+
+
+
+
+static void     thunar_vfs_user_manager_class_init          (ThunarVfsUserManagerClass *klass);
+static void     thunar_vfs_user_manager_init                (ThunarVfsUserManager      *manager);
+static void     thunar_vfs_user_manager_finalize            (GObject                   *object);
+static gboolean thunar_vfs_user_manager_flush_timer         (gpointer                   user_data);
+static void     thunar_vfs_user_manager_flush_timer_destroy (gpointer                   user_data);
+
+
+
+struct _ThunarVfsUserManagerClass
+{
+  GObjectClass __parent__;
+};
+
+struct _ThunarVfsUserManager
+{
+  GObject __parent__;
+
+  GHashTable *groups;
+  GHashTable *users;
+
+  gint        flush_timer_id;
+};
+
+
+
+G_DEFINE_TYPE (ThunarVfsUserManager, thunar_vfs_user_manager, G_TYPE_OBJECT);
+
+
+
+static void
+thunar_vfs_user_manager_class_init (ThunarVfsUserManagerClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = thunar_vfs_user_manager_finalize;
+}
+
+
+
+static void
+thunar_vfs_user_manager_init (ThunarVfsUserManager *manager)
+{
+  manager->groups = g_hash_table_new_full (g_int_hash, g_int_equal, NULL, g_object_unref);
+  manager->users = g_hash_table_new_full (g_int_hash, g_int_equal, NULL, g_object_unref);
+
+  /* keep the groups file in memory if possible */
+#ifdef HAVE_SETGROUPENT
+  setgroupent (TRUE);
+#endif
+
+  /* keep the passwd file in memory if possible */
+#ifdef HAVE_SETPASSENT
+  setpassent (TRUE);
+#endif
+
+  /* start the flush timer */
+  manager->flush_timer_id = g_timeout_add_full (G_PRIORITY_LOW, THUNAR_VFS_USER_MANAGER_FLUSH_INTERVAL,
+                                                thunar_vfs_user_manager_flush_timer, manager,
+                                                thunar_vfs_user_manager_flush_timer_destroy);
+}
+
+
+
+static void
+thunar_vfs_user_manager_finalize (GObject *object)
+{
+  ThunarVfsUserManager *manager = THUNAR_VFS_USER_MANAGER (object);
+
+  /* stop the flush timer */
+  if (G_LIKELY (manager->flush_timer_id >= 0))
+    g_source_remove (manager->flush_timer_id);
+
+  /* destroy the hash tables */
+  g_hash_table_destroy (manager->groups);
+  g_hash_table_destroy (manager->users);
+
+  /* unload the groups file */
+  endgrent ();
+
+  /* unload the passwd file */
+  endpwent ();
+
+  G_OBJECT_CLASS (thunar_vfs_user_manager_parent_class)->finalize (object);
+}
+
+
+
+static gboolean
+thunar_vfs_user_manager_flush_timer (gpointer user_data)
+{
+  ThunarVfsUserManager *manager = THUNAR_VFS_USER_MANAGER (user_data);
+  guint                 size = 0;
+
+  GDK_THREADS_ENTER ();
+
+  /* drop all cached groups */
+  size += g_hash_table_foreach_remove (manager->groups, (GHRFunc) gtk_true, NULL);
+
+  /* drop all cached users */
+  size += g_hash_table_foreach_remove (manager->users, (GHRFunc) gtk_true, NULL);
+
+  /* reload groups and passwd files if we had cached entities */
+  if (G_LIKELY (size > 0))
+    {
+      endgrent ();
+      endpwent ();
+
+#ifdef HAVE_SETGROUPENT
+      setgroupent (TRUE);
+#endif
+
+#ifdef HAVE_SETPASSENT
+      setpassent (TRUE);
+#endif
+    }
+
+  GDK_THREADS_LEAVE ();
+
+  return TRUE;
+}
+
+
+
+static void
+thunar_vfs_user_manager_flush_timer_destroy (gpointer user_data)
+{
+  GDK_THREADS_ENTER ();
+  THUNAR_VFS_USER_MANAGER (user_data)->flush_timer_id = -1;
+  GDK_THREADS_LEAVE ();
+}
+
+
+
+/**
+ * thunar_vfs_user_manager_get_default:
+ *
+ * Returns the default #ThunarVfsUserManager instance, which is shared
+ * by all modules using the user module. Call #g_object_unref() on the
+ * returned object when you are done with it.
+ *
+ * Return value: the default #ThunarVfsUserManager instance.
+ **/
+ThunarVfsUserManager*
+thunar_vfs_user_manager_get_default (void)
+{
+  static ThunarVfsUserManager *manager = NULL;
+
+  if (G_UNLIKELY (manager == NULL))
+    {
+      manager = g_object_new (THUNAR_VFS_TYPE_USER_MANAGER, NULL);
+      g_object_add_weak_pointer (G_OBJECT (manager), (gpointer) &manager);
+    }
+  else
+    {
+      g_object_ref (G_OBJECT (manager));
+    }
+
+  return manager;
+}
+
+
+
+/**
+ * thunar_vfs_user_manager_get_group_by_id:
+ * @manager : a #ThunarVfsUserManager.
+ * @id      : the group id.
+ *
+ * Looks up the #ThunarVfsGroup corresponding to @id in @manager. Returns
+ * %NULL if @manager is unable to determine the #ThunarVfsGroup for @id,
+ * else a pointer to the corresponding #ThunarVfsGroup. The caller is
+ * responsible for freeing the returned object using #g_object_unref().
+ *
+ * Return value: the #ThunarVfsGroup corresponding to @id or %NULL.
+ **/
+ThunarVfsGroup*
+thunar_vfs_user_manager_get_group_by_id (ThunarVfsUserManager *manager,
+                                         ThunarVfsGroupId      id)
+{
+  ThunarVfsGroup *group;
+
+  g_return_val_if_fail (THUNAR_VFS_IS_USER_MANAGER (manager), NULL);
+
+  /* lookup/load the group corresponding to id */
+  group = g_hash_table_lookup (manager->groups, GINT_TO_POINTER (id));
+  if (group == NULL)
+    {
+      group = thunar_vfs_local_group_new (id);
+      g_hash_table_insert (manager->groups, GINT_TO_POINTER (id), group);
+    }
+
+  /* take a reference for the caller */
+  g_object_ref (G_OBJECT (group));
+
+  return group;
+}
+
+
+
+/**
+ * thunar_vfs_user_manager_get_user_by_id:
+ * @manager : a #ThunarVfsUserManager.
+ * @id      : the user id.
+ *
+ * Looks up the #ThunarVfsUser corresponding to @id in @manager. Returns
+ * %NULL if @manager is unable to determine the #ThunarVfsUser for @id,
+ * else a pointer to the corresponding #ThunarVfsUser. The caller is
+ * responsible for freeing the returned object using #g_object_unref().
+ *
+ * Return value: the #ThunarVfsUser corresponding to @id or %NULL.
+ **/
+ThunarVfsUser*
+thunar_vfs_user_manager_get_user_by_id (ThunarVfsUserManager *manager,
+                                        ThunarVfsUserId       id)
+{
+  ThunarVfsUser *user;
+
+  g_return_val_if_fail (THUNAR_VFS_IS_USER_MANAGER (manager), NULL);
+
+  /* lookup/load the user corresponding to id */
+  user = g_hash_table_lookup (manager->users, GINT_TO_POINTER (id));
+  if (user == NULL)
+    {
+      user = thunar_vfs_local_user_new (id);
+      g_hash_table_insert (manager->users, GINT_TO_POINTER (id), user);
+    }
+
+  /* take a reference for the caller */
+  g_object_ref (G_OBJECT (user));
+
+  return user;
+}
diff --git a/thunar-vfs/thunar-vfs-user.h b/thunar-vfs/thunar-vfs-user.h
new file mode 100644
index 000000000..6a30c6448
--- /dev/null
+++ b/thunar-vfs/thunar-vfs-user.h
@@ -0,0 +1,129 @@
+/* $Id$ */
+/*-
+ * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __THUNAR_VFS_USER_H__
+#define __THUNAR_VFS_USER_H__
+
+#include <thunar-vfs/thunar-vfs-info.h>
+
+G_BEGIN_DECLS;
+
+typedef struct _ThunarVfsGroupClass ThunarVfsGroupClass;
+typedef struct _ThunarVfsGroup      ThunarVfsGroup;
+
+#define THUNAR_VFS_TYPE_GROUP             (thunar_vfs_group_get_type ())
+#define THUNAR_VFS_GROUP(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_GROUP, ThunarVfsGroup))
+#define THUNAR_VFS_GROUP_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_GROUP, ThunarVfsGroupClass))
+#define THUNAR_VFS_IS_GROUP(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_GROUP))
+#define THUNAR_VFS_IS_GROUP_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_GROUP))
+#define THUNAR_VFS_GROUP_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_GROUP, ThunarVfsGroupClass))
+
+struct _ThunarVfsGroupClass
+{
+  GObjectClass __parent__;
+
+  /* virtual methods */
+  ThunarVfsGroupId (*get_id)   (ThunarVfsGroup *group);
+  const gchar     *(*get_name) (ThunarVfsGroup *group);
+
+  /*< private >*/
+  void (*reserved1) (void);
+  void (*reserved2) (void);
+  void (*reserved3) (void);
+  void (*reserved4) (void);
+};
+
+struct _ThunarVfsGroup
+{
+  GObject __parent__;
+};
+
+GType            thunar_vfs_group_get_type  (void) G_GNUC_CONST;
+
+ThunarVfsGroupId thunar_vfs_group_get_id    (ThunarVfsGroup *group);
+const gchar     *thunar_vfs_group_get_name  (ThunarVfsGroup *group);
+
+
+typedef struct _ThunarVfsUserClass ThunarVfsUserClass;
+typedef struct _ThunarVfsUser      ThunarVfsUser;
+
+#define THUNAR_VFS_TYPE_USER            (thunar_vfs_user_get_type ())
+#define THUNAR_VFS_USER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_USER, ThunarVfsUser))
+#define THUNAR_VFS_USER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_USER, ThunarVfsUserClass))
+#define THUNAR_VFS_IS_USER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_USER))
+#define THUNAR_VFS_IS_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_USER))
+#define THUNAR_VFS_USER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_USER, ThunarVfsUserClass))
+
+struct _ThunarVfsUserClass
+{
+  GObjectClass __parent__;
+
+  /* virtual methods */
+  GList          *(*get_groups)        (ThunarVfsUser *user);
+  ThunarVfsGroup *(*get_primary_group) (ThunarVfsUser *user);
+  ThunarVfsUserId (*get_id)            (ThunarVfsUser *user);
+  const gchar    *(*get_name)          (ThunarVfsUser *user);
+  const gchar    *(*get_real_name)     (ThunarVfsUser *user);
+  gboolean        (*is_me)             (ThunarVfsUser *user);
+
+  /*< private >*/
+  void (*reserved1) (void);
+  void (*reserved2) (void);
+  void (*reserved3) (void);
+  void (*reserved4) (void);
+};
+
+struct _ThunarVfsUser
+{
+  GObject __parent__;
+};
+
+GType            thunar_vfs_user_get_type          (void) G_GNUC_CONST;
+
+GList           *thunar_vfs_user_get_groups        (ThunarVfsUser *user);
+ThunarVfsGroup  *thunar_vfs_user_get_primary_group (ThunarVfsUser *user);
+ThunarVfsUserId  thunar_vfs_user_get_id            (ThunarVfsUser *user);
+const gchar     *thunar_vfs_user_get_name          (ThunarVfsUser *user);
+const gchar     *thunar_vfs_user_get_real_name     (ThunarVfsUser *user);
+gboolean         thunar_vfs_user_is_me             (ThunarVfsUser *user);
+
+
+typedef struct _ThunarVfsUserManagerClass ThunarVfsUserManagerClass;
+typedef struct _ThunarVfsUserManager      ThunarVfsUserManager;
+
+#define THUNAR_VFS_TYPE_USER_MANAGER            (thunar_vfs_user_manager_get_type ())
+#define THUNAR_VFS_USER_MANAGER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_USER_MANAGER, ThunarVfsUserManager))
+#define THUNAR_VFS_USER_MANAGER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_USER_MANAGER, ThunarVfsUserManagerClass))
+#define THUNAR_VFS_IS_USER_MANAGER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_USER_MANAGER))
+#define THUNAR_VFS_IS_USER_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_USER_MANAGER))
+#define THUNAR_VFS_USER_MANAGER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_USER_MANAGER, ThunarVfsUserManagerClass))
+
+GType                 thunar_vfs_user_manager_get_type        (void) G_GNUC_CONST;
+
+ThunarVfsUserManager *thunar_vfs_user_manager_get_default     (void);
+
+ThunarVfsGroup       *thunar_vfs_user_manager_get_group_by_id (ThunarVfsUserManager *manager,
+                                                               ThunarVfsGroupId      id);
+ThunarVfsUser        *thunar_vfs_user_manager_get_user_by_id  (ThunarVfsUserManager *manager,
+                                                               ThunarVfsUserId       id);
+
+G_END_DECLS;
+
+#endif /* !__THUNAR_VFS_USER_H__ */
diff --git a/thunar-vfs/thunar-vfs.h b/thunar-vfs/thunar-vfs.h
index 31170a9db..24c597b17 100644
--- a/thunar-vfs/thunar-vfs.h
+++ b/thunar-vfs/thunar-vfs.h
@@ -26,6 +26,7 @@
 #include <thunar-vfs/thunar-vfs-monitor.h>
 #include <thunar-vfs/thunar-vfs-trash.h>
 #include <thunar-vfs/thunar-vfs-uri.h>
+#include <thunar-vfs/thunar-vfs-user.h>
 #include <thunar-vfs/thunar-vfs-util.h>
 #include <thunar-vfs/thunar-vfs-volume.h>
 
diff --git a/thunar/thunar-file.c b/thunar/thunar-file.c
index 5099da20d..7aa4e25d7 100644
--- a/thunar/thunar-file.c
+++ b/thunar/thunar-file.c
@@ -43,24 +43,26 @@ enum
 
 
 
-static void         thunar_file_class_init            (ThunarFileClass   *klass);
-static void         thunar_file_finalize              (GObject           *object);
-static gboolean     thunar_file_real_has_parent       (ThunarFile        *file);
-static ThunarFile  *thunar_file_real_get_parent       (ThunarFile        *file,
-                                                       GError           **error);
-static ThunarFolder*thunar_file_real_open_as_folder   (ThunarFile        *file,
-                                                       GError           **error);
-static ExoMimeInfo *thunar_file_real_get_mime_info    (ThunarFile        *file);
-static const gchar *thunar_file_real_get_special_name (ThunarFile        *file);
-static gboolean     thunar_file_real_get_date         (ThunarFile        *file,
-                                                       ThunarFileDateType date_type,
-                                                       ThunarVfsFileTime *date_return);
-static gboolean     thunar_file_real_get_size         (ThunarFile        *file,
-                                                       ThunarVfsFileSize *size_return);
-static GList       *thunar_file_real_get_emblem_names (ThunarFile        *file);
-static void         thunar_file_real_changed          (ThunarFile        *file);
-static void         thunar_file_destroyed             (gpointer           data,
-                                                       GObject           *object);
+static void            thunar_file_class_init            (ThunarFileClass   *klass);
+static void            thunar_file_finalize              (GObject           *object);
+static gboolean        thunar_file_real_has_parent       (ThunarFile        *file);
+static ThunarFile     *thunar_file_real_get_parent       (ThunarFile        *file,
+                                                          GError           **error);
+static ThunarFolder   *thunar_file_real_open_as_folder   (ThunarFile        *file,
+                                                          GError           **error);
+static ExoMimeInfo    *thunar_file_real_get_mime_info    (ThunarFile        *file);
+static const gchar    *thunar_file_real_get_special_name (ThunarFile        *file);
+static gboolean        thunar_file_real_get_date         (ThunarFile        *file,
+                                                          ThunarFileDateType date_type,
+                                                          ThunarVfsFileTime *date_return);
+static gboolean        thunar_file_real_get_size         (ThunarFile        *file,
+                                                          ThunarVfsFileSize *size_return);
+static ThunarVfsGroup *thunar_file_real_get_group        (ThunarFile        *file);
+static ThunarVfsUser  *thunar_file_real_get_user         (ThunarFile        *file);
+static GList          *thunar_file_real_get_emblem_names (ThunarFile        *file);
+static void            thunar_file_real_changed          (ThunarFile        *file);
+static void            thunar_file_destroyed             (gpointer           data,
+                                                          GObject           *object);
 
 
 
@@ -158,6 +160,8 @@ thunar_file_class_init (ThunarFileClass *klass)
   klass->get_special_name = thunar_file_real_get_special_name;
   klass->get_date = thunar_file_real_get_date;
   klass->get_size = thunar_file_real_get_size;
+  klass->get_group = thunar_file_real_get_group;
+  klass->get_user = thunar_file_real_get_user;
   klass->get_emblem_names = thunar_file_real_get_emblem_names;
   klass->changed = thunar_file_real_changed;
 
@@ -284,6 +288,22 @@ thunar_file_real_get_size (ThunarFile        *file,
 
 
 
+static ThunarVfsGroup*
+thunar_file_real_get_group (ThunarFile *file)
+{
+  return NULL;
+}
+
+
+
+static ThunarVfsUser*
+thunar_file_real_get_user (ThunarFile *file)
+{
+  return NULL;
+}
+
+
+
 static GList*
 thunar_file_real_get_emblem_names (ThunarFile *file)
 {
@@ -794,6 +814,50 @@ thunar_file_get_size_string (ThunarFile *file)
 
 
 
+/**
+ * thunar_file_get_group:
+ * @file : a #ThunarFile instance.
+ *
+ * Determines the #ThunarVfsGroup for @file. If there's no
+ * group associated with @file or if the system is unable to
+ * determine the group, %NULL will be returned.
+ *
+ * The caller is responsible for freeing the returned object
+ * using #g_object_unref().
+ *
+ * Return value: the #ThunarVfsGroup for @file or %NULL.
+ **/
+ThunarVfsGroup*
+thunar_file_get_group (ThunarFile *file)
+{
+  g_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
+  return THUNAR_FILE_GET_CLASS (file)->get_group (file);
+}
+
+
+
+/**
+ * thunar_file_get_user:
+ * @file : a #ThunarFile instance.
+ *
+ * Determines the #ThunarVfsUser for @file. If there's no
+ * user associated with @file or if the system is unable
+ * to determine the user, %NULL will be returned.
+ *
+ * The caller is responsible for freeing the returned object
+ * using #g_object_unref().
+ *
+ * Return value: the #ThunarVfsUser for @file or %NULL.
+ **/
+ThunarVfsUser*
+thunar_file_get_user (ThunarFile *file)
+{
+  g_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
+  return THUNAR_FILE_GET_CLASS (file)->get_user (file);
+}
+
+
+
 /**
  * thunar_file_get_emblem_names:
  * @file : a #ThunarFile instance.
diff --git a/thunar/thunar-file.h b/thunar/thunar-file.h
index 9b86d149c..3d99ffbf1 100644
--- a/thunar/thunar-file.h
+++ b/thunar/thunar-file.h
@@ -85,6 +85,9 @@ struct _ThunarFileClass
   gboolean             (*get_size)            (ThunarFile        *file,
                                                ThunarVfsFileSize *size_return);
 
+  ThunarVfsGroup      *(*get_group)           (ThunarFile        *file);
+  ThunarVfsUser       *(*get_user)            (ThunarFile        *file);
+
   GList               *(*get_emblem_names)    (ThunarFile        *file);
   const gchar         *(*get_icon_name)       (ThunarFile        *file,
                                                GtkIconTheme      *icon_theme);
@@ -139,6 +142,9 @@ gchar             *thunar_file_get_date_string  (ThunarFile        *file,
 gchar             *thunar_file_get_mode_string  (ThunarFile        *file);
 gchar             *thunar_file_get_size_string  (ThunarFile        *file);
 
+ThunarVfsGroup    *thunar_file_get_group        (ThunarFile        *file);
+ThunarVfsUser     *thunar_file_get_user         (ThunarFile        *file);
+
 GList             *thunar_file_get_emblem_names (ThunarFile        *file);
 GdkPixbuf         *thunar_file_load_icon        (ThunarFile        *file,
                                                  gint               size);
diff --git a/thunar/thunar-local-file.c b/thunar/thunar-local-file.c
index e3cf3bce7..e71c8a020 100644
--- a/thunar/thunar-local-file.c
+++ b/thunar/thunar-local-file.c
@@ -44,6 +44,8 @@ static ThunarVfsFileType  thunar_local_file_get_kind          (ThunarFile
 static ThunarVfsFileMode  thunar_local_file_get_mode          (ThunarFile           *file);
 static gboolean           thunar_local_file_get_size          (ThunarFile           *file,
                                                                ThunarVfsFileSize    *size_return);
+static ThunarVfsGroup    *thunar_local_file_get_group         (ThunarFile           *file);
+static ThunarVfsUser     *thunar_local_file_get_user          (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);
@@ -60,6 +62,8 @@ static void               thunar_local_file_monitor           (ThunarVfsMonitor
 struct _ThunarLocalFileClass
 {
   ThunarFileClass __parent__;
+
+  ThunarVfsUserManager *user_manager;
 };
 
 struct _ThunarLocalFile
@@ -87,6 +91,9 @@ thunar_local_file_class_init (ThunarLocalFileClass *klass)
   ThunarFileClass *thunarfile_class;
   GObjectClass    *gobject_class;
 
+  /* query the user manager instance */
+  klass->user_manager = thunar_vfs_user_manager_get_default ();
+
   gobject_class = G_OBJECT_CLASS (klass);
   gobject_class->finalize = thunar_local_file_finalize;
 
@@ -101,6 +108,8 @@ thunar_local_file_class_init (ThunarLocalFileClass *klass)
   thunarfile_class->get_kind = thunar_local_file_get_kind;
   thunarfile_class->get_mode = thunar_local_file_get_mode;
   thunarfile_class->get_size = thunar_local_file_get_size;
+  thunarfile_class->get_group = thunar_local_file_get_group;
+  thunarfile_class->get_user = thunar_local_file_get_user;
   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;
@@ -304,6 +313,24 @@ thunar_local_file_get_kind (ThunarFile *file)
 
 
 
+static ThunarVfsGroup*
+thunar_local_file_get_group (ThunarFile *file)
+{
+  return thunar_vfs_user_manager_get_group_by_id (THUNAR_LOCAL_FILE_GET_CLASS (file)->user_manager,
+                                                  THUNAR_LOCAL_FILE (file)->info.gid);
+}
+
+
+
+static ThunarVfsUser*
+thunar_local_file_get_user (ThunarFile *file)
+{
+  return thunar_vfs_user_manager_get_user_by_id (THUNAR_LOCAL_FILE_GET_CLASS (file)->user_manager,
+                                                 THUNAR_LOCAL_FILE (file)->info.uid);
+}
+
+
+
 static GList*
 thunar_local_file_get_emblem_names (ThunarFile *file)
 {
diff --git a/thunar/thunar-trash-file.c b/thunar/thunar-trash-file.c
index 04481c3eb..e6a34fac1 100644
--- a/thunar/thunar-trash-file.c
+++ b/thunar/thunar-trash-file.c
@@ -47,6 +47,8 @@ static ThunarVfsFileType thunar_trash_file_get_kind         (ThunarFile
 static ThunarVfsFileMode thunar_trash_file_get_mode         (ThunarFile           *file);
 static gboolean          thunar_trash_file_get_size         (ThunarFile           *file,
                                                              ThunarVfsFileSize    *size_return);
+static ThunarVfsGroup   *thunar_trash_file_get_group        (ThunarFile           *file);
+static ThunarVfsUser    *thunar_trash_file_get_user         (ThunarFile           *file);
 static const gchar      *thunar_trash_file_get_icon_name    (ThunarFile           *file,
                                                              GtkIconTheme         *icon_theme);
 
@@ -92,6 +94,8 @@ thunar_trash_file_class_init (ThunarTrashFileClass *klass)
   thunarfile_class->get_kind = thunar_trash_file_get_kind;
   thunarfile_class->get_mode = thunar_trash_file_get_mode;
   thunarfile_class->get_size = thunar_trash_file_get_size;
+  thunarfile_class->get_group = thunar_trash_file_get_group;
+  thunarfile_class->get_user = thunar_trash_file_get_user;
   thunarfile_class->get_icon_name = thunar_trash_file_get_icon_name;
 }
 
@@ -200,6 +204,22 @@ thunar_trash_file_get_size (ThunarFile        *file,
 
 
 
+static ThunarVfsGroup*
+thunar_trash_file_get_group (ThunarFile *file)
+{
+  return thunar_file_get_group (THUNAR_TRASH_FILE (file)->real_file);
+}
+
+
+
+static ThunarVfsUser*
+thunar_trash_file_get_user (ThunarFile *file)
+{
+  return thunar_file_get_user (THUNAR_TRASH_FILE (file)->real_file);
+}
+
+
+
 static const gchar*
 thunar_trash_file_get_icon_name (ThunarFile   *file,
                                  GtkIconTheme *icon_theme)
-- 
GitLab