[liboobs] Update to new users protocol



commit f578bedf10dfd289b36ddfd36c0a4770db272380
Author: Milan Bouchet-Valat <nalimilan club fr>
Date:   Mon Jan 4 22:49:55 2010 +0100

    Update to new users protocol
    
    New SystemToolsBackends protocol since the 2.9 series. Users are now only added and deleted individually via methods oobs_users_config_add/delete_user(). OobsUser is now an OobsObject implementing commit(), only working on existing users, and add()/delete(), which are called by previously cited UsersConfig convenience methods. oobs_users_config_commit() now only commits default parameters.
    
    New fields in the D-Bus protocol have their accessors and variables too, which required adding glib-mkenum code (for home flags), cleaning a few files around. Passwords are now sent to in clear text to the bus, so that the backends can encrypt them as needed via the tools for the platform.
    
    SelfConfig changes version too, and follows the same rules as standard users. Password is no longer allowed to be set that way, instead PAM should be used for that.

 configure.in               |    5 +-
 oobs/Makefile.am           |   35 ++++-
 oobs/oobs-enum-types.c.in  |   40 ++++
 oobs/oobs-enum-types.h.in  |   26 +++
 oobs/oobs-iface-ppp.c      |   42 ----
 oobs/oobs-iface-ppp.h      |    4 +-
 oobs/oobs-ifacesconfig.c   |   23 ---
 oobs/oobs-ifacesconfig.h   |    2 -
 oobs/oobs-object-private.h |    2 +
 oobs/oobs-selfconfig.c     |   11 +-
 oobs/oobs-share-smb.c      |   22 --
 oobs/oobs-user.c           |  455 ++++++++++++++++++++++++++++++++++++++------
 oobs/oobs-user.h           |   28 +++-
 oobs/oobs-usersconfig.c    |  346 +++++++++++++++++----------------
 oobs/oobs-usersconfig.h    |   10 +-
 oobs/oobs.h                |    1 +
 oobs/utils.c               |   15 ++
 oobs/utils.h               |    6 +-
 18 files changed, 737 insertions(+), 336 deletions(-)
---
diff --git a/configure.in b/configure.in
index 7a60648..0222274 100644
--- a/configure.in
+++ b/configure.in
@@ -10,6 +10,9 @@ AM_MAINTAINER_MODE
 
 AM_PROG_LIBTOOL
 
+# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
+AM_PATH_GLIB_2_0()
+
 AC_ISC_POSIX
 AC_PROG_CC
 AM_PROG_CC_STDC
@@ -30,7 +33,7 @@ AC_SUBST(LT_AGE)
 
 GLIB_REQUIRED=2.14.0
 DBUS_REQUIRED=0.70
-STB_REQUIRED=2.5.4
+STB_REQUIRED=2.9
 HAL_REQUIRED=0.5.9
 
 dnl set gettext stuff
diff --git a/oobs/Makefile.am b/oobs/Makefile.am
index 8f691bf..b0c2271 100644
--- a/oobs/Makefile.am
+++ b/oobs/Makefile.am
@@ -12,7 +12,7 @@ oobsincludedir=$(includedir)/liboobs-1.0/oobs/
 
 lib_LTLIBRARIES= liboobs-1.la
 
-oobsinclude_HEADERS= 	\
+oobs_public_headers = 	\
 	oobs.h			\
 	oobs-session.h		\
 	oobs-object.h		\
@@ -44,6 +44,9 @@ oobsinclude_HEADERS= 	\
 	oobs-service.h		\
 	oobs-result.h
 
+oobsinclude_HEADERS = $(oobs_public_headers) \
+	oobs-enum-types.h
+
 oobs_private_headers = 	\
 	iface-state-monitor.h		\
 	oobs-defines.h			\
@@ -52,6 +55,10 @@ oobs_private_headers = 	\
 	oobs-session-private.h	\
 	utils.h
 
+oobs_built_sources = \
+       oobs-enum-types.h \
+       oobs-enum-types.c
+
 liboobs_1_la_SOURCES = \
 	utils.c				\
 	oobs-session.c			\
@@ -80,7 +87,8 @@ liboobs_1_la_SOURCES = \
 	oobs-iface-ppp.c		\
 	oobs-ifacesconfig.c		\
 	oobs-service.c			\
-	oobs-servicesconfig.c
+	oobs-servicesconfig.c		\
+	$(oobs_built_sources)
 
 if HAVE_RTNETLINK
 liboobs_1_la_SOURCES += iface-state-monitor-linux.c
@@ -93,3 +101,26 @@ liboobs_1_la_LDFLAGS= $(libtool_opts)
 
 EXTRA_DIST= $(oobs_private_headers)
 
+BUILT_SOURCES = $(oobs_built_sources)
+OOBS_STAMP_FILES = stamp-oobs-enum-types.h
+CLEANFILES = $(OOBS_STAMP_FILES)
+
+
+oobs-enum-types.h: stamp-oobs-enum-types.h Makefile
+	@true
+stamp-oobs-enum-types.h: $(oobs_public_headers) oobs-enum-types.h.in
+	$(AM_V_GEN) ( cd $(srcdir) && \
+	  $(GLIB_MKENUMS) \
+	    --template $(srcdir)/oobs-enum-types.h.in \
+	  $(oobs_public_headers) ) >> xgen-teth && \
+	(cmp -s xgen-teth oobs-enum-types.h || cp xgen-teth oobs-enum-types.h) && \
+	rm -f xgen-teth && \
+	echo timestamp > $(@F)
+
+oobs-enum-types.c: stamp-oobs-enum-types.h oobs-enum-types.c.in
+	  $(AM_V_GEN) ( cd $(srcdir) && \
+	  $(GLIB_MKENUMS) \
+	    --template $(srcdir)/oobs-enum-types.c.in \
+	  $(oobs_public_headers) ) >> xgen-tetc && \
+	cp xgen-tetc oobs-enum-types.c && \
+	rm -f xgen-tetc
diff --git a/oobs/oobs-enum-types.c.in b/oobs/oobs-enum-types.c.in
new file mode 100644
index 0000000..354b85f
--- /dev/null
+++ b/oobs/oobs-enum-types.c.in
@@ -0,0 +1,40 @@
+/*** BEGIN file-header ***/
+#include "oobs-enum-types.h"
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+
+/* enumerations from "@filename@" */
+#include "@filename@"
+
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType
+ enum_name@_get_type (void)
+{
+  static volatile gsize g_enum_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_enum_type_id__volatile))
+    {
+      static const G Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+        { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+        { 0, NULL, NULL }
+      };
+      GType g_enum_type_id;
+
+      g_enum_type_id =
+        g_ type@_register_static (g_intern_static_string ("@EnumName@"), values);
+
+      g_once_init_leave (&g_enum_type_id__volatile, g_enum_type_id);
+    }
+
+  return g_enum_type_id__volatile;
+}
+/*** END value-tail ***/
diff --git a/oobs/oobs-enum-types.h.in b/oobs/oobs-enum-types.h.in
new file mode 100644
index 0000000..5b258cd
--- /dev/null
+++ b/oobs/oobs-enum-types.h.in
@@ -0,0 +1,26 @@
+/*** BEGIN file-header ***/
+#ifndef __OOBS_ENUM_TYPES_H__
+#define __OOBS_ENUM_TYPES_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+/* enumerations from "@filename@" */
+/*** END file-production ***/
+
+/*** BEGIN file-tail ***/
+G_END_DECLS
+
+#endif /* !__MUTTER_ENUM_TYPES_H__ */
+/*** END file-tail ***/
+
+/*** BEGIN value-header ***/
+GType @enum_name _get_type (void) G_GNUC_CONST;
+#define OOBS_TYPE_ ENUMSHORT@ (@enum_name _get_type())
+
+/*** END value-header ***/
+
diff --git a/oobs/oobs-iface-ppp.c b/oobs/oobs-iface-ppp.c
index cea861f..06d629c 100644
--- a/oobs/oobs-iface-ppp.c
+++ b/oobs/oobs-iface-ppp.c
@@ -94,48 +94,6 @@ enum {
 
 G_DEFINE_TYPE (OobsIfacePPP, oobs_iface_ppp, OOBS_TYPE_IFACE);
 
-GType
-oobs_modem_volume_get_type (void)
-{
-  static GType etype = 0;
-
-  if (!etype)
-    {
-      static const GEnumValue values[] =
-        {
-          { OOBS_MODEM_VOLUME_SILENT, "OOBS_MODEM_VOLUME_SILENT", "silent" },
-          { OOBS_MODEM_VOLUME_LOW,    "OOBS_MODEM_VOLUME_LOW",    "low" },
-          { OOBS_MODEM_VOLUME_MEDIUM, "OOBS_MODEM_VOLUME_MEDIUM", "medium" },
-          { OOBS_MODEM_VOLUME_LOUD,   "OOBS_MODEM_VOLUME_LOUD",   "loud" },
-          { 0, NULL, NULL }
-        };
-
-      etype = g_enum_register_static ("OobsModemVolume", values);
-    }
-
-  return etype;
-}
-
-GType
-oobs_dial_type_get_type (void)
-{
-  static GType etype = 0;
-
-  if (!etype)
-    {
-      static const GEnumValue values[] =
-        {
-	  { OOBS_DIAL_TYPE_TONES,  "OOBS_DIAL_TYPE_TONES",  "tones" },
-	  { OOBS_DIAL_TYPE_PULSES, "OOBS_DIAL_TYPE_PULSES", "pulses" },
- 	  { 0, NULL, NULL }
-        };
-
-      etype = g_enum_register_static ("OobsDialType", values);
-    }
-
-  return etype;
-}
-
 static void
 oobs_iface_ppp_class_init (OobsIfacePPPClass *class)
 {
diff --git a/oobs/oobs-iface-ppp.h b/oobs/oobs-iface-ppp.h
index b73acf2..c6c1b25 100644
--- a/oobs/oobs-iface-ppp.h
+++ b/oobs/oobs-iface-ppp.h
@@ -25,6 +25,7 @@ G_BEGIN_DECLS
 
 #include "oobs-iface.h"
 #include "oobs-iface-ethernet.h"
+#include "oobs-enum-types.h"
 
 typedef enum {
   OOBS_MODEM_VOLUME_SILENT,
@@ -38,9 +39,6 @@ typedef enum {
   OOBS_DIAL_TYPE_PULSES
 } OobsDialType;
 
-#define OOBS_TYPE_MODEM_VOLUME          (oobs_modem_volume_get_type ())
-#define OOBS_TYPE_DIAL_TYPE             (oobs_dial_type_get_type ())
-
 #define OOBS_TYPE_IFACE_PPP           (oobs_iface_ppp_get_type ())
 #define OOBS_IFACE_PPP(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), OOBS_TYPE_IFACE_PPP, OobsIfacePPP))
 #define OOBS_IFACE_PPP_CLASS(obj)     (G_TYPE_CHECK_CLASS_CAST ((obj),    OOBS_TYPE_IFACE_PPP, OobsIfacePPPClass))
diff --git a/oobs/oobs-ifacesconfig.c b/oobs/oobs-ifacesconfig.c
index f910b93..45902d2 100644
--- a/oobs/oobs-ifacesconfig.c
+++ b/oobs/oobs-ifacesconfig.c
@@ -78,29 +78,6 @@ static void oobs_ifaces_config_commit     (OobsObject   *object);
 
 G_DEFINE_TYPE (OobsIfacesConfig, oobs_ifaces_config, OOBS_TYPE_OBJECT);
 
-GType
-oobs_iface_type_get_type (void)
-{
-  static GType etype = 0;
-
-  if (!etype)
-    {
-      static const GEnumValue values[] =
-	{
-	  { OOBS_IFACE_TYPE_ETHERNET, "OOBS_IFACE_TYPE_ETHERNET", "ethernet" },
-	  { OOBS_IFACE_TYPE_WIRELESS, "OOBS_IFACE_TYPE_WIRELESS", "wireless" },
-	  { OOBS_IFACE_TYPE_IRLAN,    "OOBS_IFACE_TYPE_IRLAN",    "infrared" },
-	  { OOBS_IFACE_TYPE_PLIP,     "OOBS_IFACE_TYPE_PLIP",     "parallel" },
-	  { OOBS_IFACE_TYPE_PPP,      "OOBS_IFACE_TYPE_PPP",      "ppp" },
- 	  { 0, NULL, NULL }
-	};
-
-      etype = g_enum_register_static ("OobsIfaceType", values);
-    }
-
-  return etype;
-}
-
 static void
 oobs_ifaces_config_class_init (OobsIfacesConfigClass *class)
 {
diff --git a/oobs/oobs-ifacesconfig.h b/oobs/oobs-ifacesconfig.h
index 0822103..d3b5711 100644
--- a/oobs/oobs-ifacesconfig.h
+++ b/oobs/oobs-ifacesconfig.h
@@ -35,8 +35,6 @@ typedef enum {
   OOBS_IFACE_TYPE_PPP
 } OobsIfaceType;
 
-#define OOBS_TYPE_IFACE_TYPE (oobs_iface_type_get_type ())
-
 #define OOBS_TYPE_IFACES_CONFIG         (oobs_ifaces_config_get_type ())
 #define OOBS_IFACES_CONFIG(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), OOBS_TYPE_IFACES_CONFIG, OobsIfacesConfig))
 #define OOBS_IFACES_CONFIG_CLASS(c)     (G_TYPE_CHECK_CLASS_CAST ((c),    OOBS_TYPE_IFACES_CONFIG, OobsIfacesConfigClass))
diff --git a/oobs/oobs-object-private.h b/oobs/oobs-object-private.h
index acac41b..bd282fc 100644
--- a/oobs/oobs-object-private.h
+++ b/oobs/oobs-object-private.h
@@ -23,6 +23,8 @@
 
 G_BEGIN_DECLS
 
+#include <dbus/dbus.h>
+
 #include "oobs-object.h"
 
 DBusMessage *_oobs_object_get_dbus_message (OobsObject *object);
diff --git a/oobs/oobs-selfconfig.c b/oobs/oobs-selfconfig.c
index 3c74bb8..33239f0 100644
--- a/oobs/oobs-selfconfig.c
+++ b/oobs/oobs-selfconfig.c
@@ -35,7 +35,7 @@
  * @short_description: Object that represents the current user
  **/
 
-#define SELF_CONFIG_REMOTE_OBJECT "SelfConfig"
+#define SELF_CONFIG_REMOTE_OBJECT "SelfConfig2"
 #define OOBS_SELF_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), OOBS_TYPE_SELF_CONFIG, OobsSelfConfigPrivate))
 #define POLICY_KIT_SELF_ACTION "org.freedesktop.systemtoolsbackends.self.set"
 
@@ -168,7 +168,6 @@ oobs_self_config_commit (OobsObject *object)
   OobsSelfConfigPrivate *priv;
   DBusMessageIter iter, array_iter;
   DBusMessage *message;
-  gchar *passwd;
 
   priv = OOBS_SELF_CONFIG (object)->_priv;
 
@@ -180,10 +179,6 @@ oobs_self_config_commit (OobsObject *object)
 
   utils_append_uint (&iter, oobs_user_get_uid (priv->user));
 
-  g_object_get (priv->user, "crypted-password", &passwd, NULL);
-  utils_append_string (&iter, passwd);
-  g_free (passwd);
-
   /* GECOS fields */
   dbus_message_iter_open_container (&iter,
 				    DBUS_TYPE_ARRAY,
@@ -197,6 +192,10 @@ oobs_self_config_commit (OobsObject *object)
   utils_append_string (&array_iter, oobs_user_get_other_data (priv->user));
 
   dbus_message_iter_close_container (&iter, &array_iter);
+
+  utils_append_string (&iter, oobs_user_get_locale (priv->user));
+  /* TODO: use location when the backends support it */
+  utils_append_string (&iter, "");
 }
 
 static const gchar *
diff --git a/oobs/oobs-share-smb.c b/oobs/oobs-share-smb.c
index c479daf..2b2828a 100644
--- a/oobs/oobs-share-smb.c
+++ b/oobs/oobs-share-smb.c
@@ -62,28 +62,6 @@ enum {
 
 G_DEFINE_TYPE (OobsShareSMB, oobs_share_smb, OOBS_TYPE_SHARE);
 
-GType
-oobs_share_smb_flags_get_type (void)
-{
-  static GType type = 0;
-
-  if (!type)
-    {
-      static const GFlagsValue values[] =
-	{
-	  { OOBS_SHARE_SMB_ENABLED,   "OOBS_SHARE_SMB_ENABLED",   "smb-enabled" },
-	  { OOBS_SHARE_SMB_BROWSABLE, "OOBS_SHARE_SMB_BROWSABLE", "smb-browsable" },
-	  { OOBS_SHARE_SMB_PUBLIC,    "OOBS_SHARE_SMB_PUBLIC",    "smb-public" },
-	  { OOBS_SHARE_SMB_WRITABLE,  "OOBS_SHARE_SMB_WRITABLE",  "smb-writable" },
-	  { 0, NULL, NULL }
-	};
-
-      type = g_flags_register_static ("OobsShareSMBFlags", values);
-    }
-
-  return type;
-}
-
 static void
 oobs_share_smb_class_init (OobsShareSMBClass *class)
 {
diff --git a/oobs/oobs-user.c b/oobs/oobs-user.c
index d3e4b61..fd15923 100644
--- a/oobs/oobs-user.c
+++ b/oobs/oobs-user.c
@@ -15,7 +15,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  *
- * Authors: Carlos Garnacho Parro  <carlosg gnome org>
+ * Authors: Carlos Garnacho Parro  <carlosg gnome org>,
+ *          Milan Bouchet-Valat <nalimilan club fr>.
  */
 
 #include <glib-object.h>
@@ -26,6 +27,7 @@
 #include <crypt.h>
 #include <utmp.h>
 
+#include "oobs-object-private.h"
 #include "oobs-usersconfig.h"
 #include "oobs-user.h"
 #include "oobs-group.h"
@@ -39,6 +41,7 @@
  * @see_also: #OobsUsersConfig
  **/
 
+#define USER_REMOTE_OBJECT "UserConfig2"
 #define OOBS_USER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), OOBS_TYPE_USER, OobsUserPrivate))
 
 typedef struct _OobsUserPrivate OobsUserPrivate;
@@ -60,6 +63,14 @@ struct _OobsUserPrivate {
   gchar *work_phone_no;
   gchar *home_phone_no;
   gchar *other_data;
+
+  /* filled from the password flags */
+  gboolean passwd_empty;
+  gboolean passwd_disabled;
+
+  gboolean           encrypted_home;
+  gchar             *locale;
+  OobsUserHomeFlags  home_flags;
 };
 
 static void oobs_user_class_init (OobsUserClass *class);
@@ -75,12 +86,13 @@ static void oobs_user_get_property (GObject      *object,
 				    GValue       *value,
 				    GParamSpec   *pspec);
 
+static void oobs_user_commit (OobsObject *object);
+
 enum
 {
   PROP_0,
   PROP_USERNAME,
   PROP_PASSWORD,
-  PROP_CRYPTED_PASSWORD,
   PROP_UID,
   PROP_HOMEDIR,
   PROP_SHELL,
@@ -89,20 +101,31 @@ enum
   PROP_WORK_PHONE_NO,
   PROP_HOME_PHONE_NO,
   PROP_OTHER_DATA,
+  PROP_PASSWD_EMPTY,
+  PROP_PASSWD_DISABLED,
+  PROP_ENCRYPTED_HOME,
+  PROP_LOCALE,
+  PROP_HOME_FLAGS,
   PROP_ACTIVE
 };
 
-G_DEFINE_TYPE (OobsUser, oobs_user, G_TYPE_OBJECT);
+G_DEFINE_TYPE (OobsUser, oobs_user, OOBS_TYPE_OBJECT);
 
 static void
 oobs_user_class_init (OobsUserClass *class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (class);
+  OobsObjectClass *oobs_class = OOBS_OBJECT_CLASS (class);
 
   object_class->set_property = oobs_user_set_property;
   object_class->get_property = oobs_user_get_property;
   object_class->finalize     = oobs_user_finalize;
 
+  oobs_class->commit = oobs_user_commit;
+
+  /* override the singleton check */
+  oobs_class->singleton = FALSE;
+
   g_object_class_install_property (object_class,
 				   PROP_USERNAME,
 				   g_param_spec_string ("name",
@@ -116,21 +139,14 @@ oobs_user_class_init (OobsUserClass *class)
 							"Password",
 							"Password for the user",
 							NULL,
-							G_PARAM_WRITABLE));
-  g_object_class_install_property (object_class,
-				   PROP_CRYPTED_PASSWORD,
-				   g_param_spec_string ("crypted-password",
-							"Crypted password",
-							"Crypted password for the user",
-							NULL,
 							G_PARAM_READWRITE));
   g_object_class_install_property (object_class,
 				   PROP_UID,
-				   g_param_spec_int ("uid",
-						     "UID",
-						     "UID for the user",
-						     0, OOBS_MAX_UID, OOBS_MAX_UID,
-						     G_PARAM_READWRITE));
+				   g_param_spec_uint ("uid",
+				                      "UID",
+				                      "UID for the user",
+				                      0, OOBS_MAX_UID, OOBS_MAX_UID,
+				                      G_PARAM_READWRITE));
   g_object_class_install_property (object_class,
 				   PROP_HOMEDIR,
 				   g_param_spec_string ("home-directory",
@@ -181,6 +197,42 @@ oobs_user_class_init (OobsUserClass *class)
 							NULL,
 							G_PARAM_READWRITE));
   g_object_class_install_property (object_class,
+				   PROP_PASSWD_EMPTY,
+				   g_param_spec_boolean ("password-empty",
+							 "Empty password",
+							 "Whether user password is empty",
+							 FALSE,
+							 G_PARAM_READWRITE));
+  g_object_class_install_property (object_class,
+				   PROP_PASSWD_DISABLED,
+				   g_param_spec_boolean ("password-disabled",
+							 "Disabled account",
+							 "Whether user is allowed to log in",
+							 TRUE,
+							 G_PARAM_READWRITE));
+  g_object_class_install_property (object_class,
+                                   PROP_ENCRYPTED_HOME,
+                                   g_param_spec_boolean ("encrypted-home",
+                                                         "Encrypted home",
+                                                         "Whether user's home is encrypted",
+                                                         FALSE,
+                                                         G_PARAM_READWRITE));
+  g_object_class_install_property (object_class,
+				   PROP_HOME_FLAGS,
+				   g_param_spec_flags ("home-flags",
+				                       "Home flags",
+				                       "Flags affecting home directory treatment",
+				                       OOBS_TYPE_USER_HOME_FLAGS,
+				                       0,
+				                       G_PARAM_READWRITE));
+  g_object_class_install_property (object_class,
+                                   PROP_LOCALE,
+                                   g_param_spec_string ("locale",
+                                                        "Locale",
+                                                        "Preferred locale for the user",
+                                                        NULL,
+                                                        G_PARAM_READWRITE));
+  g_object_class_install_property (object_class,
 				   PROP_OTHER_DATA,
 				   g_param_spec_boolean ("active",
 							 "Active",
@@ -209,6 +261,17 @@ oobs_user_init (OobsUser *user)
   priv->work_phone_no = NULL;
   priv->home_phone_no = NULL;
   priv->other_data    = NULL;
+  priv->locale        = NULL;
+
+  /* This value ensures the backends will use the system default
+   * if UID were not changed manually. */
+  priv->uid = G_MAXUINT32;
+
+  priv->passwd_empty    = FALSE;
+  priv->passwd_disabled = FALSE;
+  priv->encrypted_home  = FALSE;
+  priv->home_flags      = 0;
+
   user->_priv         = priv;
 }
 
@@ -220,8 +283,6 @@ oobs_user_set_property (GObject      *object,
 {
   OobsUser *user;
   OobsUserPrivate *priv;
-  gboolean use_md5;
-  gchar *salt, *str;
 
   g_return_if_fail (OOBS_IS_USER (object));
 
@@ -236,30 +297,10 @@ oobs_user_set_property (GObject      *object,
       break;
     case PROP_PASSWORD:
       g_free (priv->password);
-      g_object_get (priv->config, "use-md5", &use_md5, NULL);
-
-      if (use_md5)
-	{
-	  salt = utils_get_random_string (5);
-	  str = g_strdup_printf ("$1$%s", salt);
-	  priv->password = g_strdup ((gchar *) crypt (g_value_get_string (value), str));
-
-	  g_free (str);
-	}
-      else
-	{
-	  salt = utils_get_random_string (2);
-	  priv->password = g_strdup ((gchar *) crypt (g_value_get_string (value), salt));
-	}
-
-      g_free (salt);
-      break;
-    case PROP_CRYPTED_PASSWORD:
-      g_free (priv->password);
       priv->password = g_value_dup_string (value);
       break;
     case PROP_UID:
-      priv->uid = g_value_get_int (value);
+      priv->uid = g_value_get_uint (value);
       break;
     case PROP_HOMEDIR:
       g_free (priv->homedir);
@@ -289,6 +330,22 @@ oobs_user_set_property (GObject      *object,
       g_free (priv->other_data);
       priv->other_data = g_value_dup_string (value);
       break;
+    case PROP_PASSWD_EMPTY:
+      priv->passwd_empty = g_value_get_boolean (value);
+      break;
+    case PROP_PASSWD_DISABLED:
+      priv->passwd_disabled = g_value_get_boolean (value);
+      break;
+    case PROP_ENCRYPTED_HOME:
+      priv->encrypted_home = g_value_get_boolean (value);
+      break;
+    case PROP_HOME_FLAGS:
+      priv->home_flags = g_value_get_flags (value);
+      break;
+    case PROP_LOCALE:
+      g_free (priv->locale);
+      priv->locale = g_value_dup_string (value);
+      break;
     }
 }
 
@@ -311,11 +368,11 @@ oobs_user_get_property (GObject      *object,
     case PROP_USERNAME:
       g_value_set_string (value, priv->username);
       break;
-    case PROP_CRYPTED_PASSWORD:
+    case PROP_PASSWORD:
       g_value_set_string (value, priv->password);
       break;
     case PROP_UID:
-      g_value_set_int (value, priv->uid);
+      g_value_set_uint (value, priv->uid);
       break;
     case PROP_HOMEDIR:
       g_value_set_string (value, priv->homedir);
@@ -338,6 +395,21 @@ oobs_user_get_property (GObject      *object,
     case PROP_OTHER_DATA:
       g_value_set_string (value, priv->other_data);
       break;
+    case PROP_PASSWD_EMPTY:
+      g_value_set_boolean (value, priv->passwd_empty);
+      break;
+    case PROP_PASSWD_DISABLED:
+      g_value_set_boolean (value, priv->passwd_disabled);
+      break;
+    case PROP_ENCRYPTED_HOME:
+	g_value_set_boolean (value, priv->encrypted_home);
+      break;
+    case PROP_HOME_FLAGS:
+      g_value_set_flags (value, priv->home_flags);
+      break;
+    case PROP_LOCALE:
+      g_value_set_string (value, priv->locale);
+      break;
     case PROP_ACTIVE:
       g_value_set_boolean (value, oobs_user_get_active (user));
       break;
@@ -366,6 +438,7 @@ oobs_user_finalize (GObject *object)
       g_free (priv->work_phone_no);
       g_free (priv->home_phone_no);
       g_free (priv->other_data);
+      g_free (priv->locale);
 
       if (priv->main_group)
 	g_object_unref (priv->main_group);
@@ -375,6 +448,106 @@ oobs_user_finalize (GObject *object)
     (* G_OBJECT_CLASS (oobs_user_parent_class)->finalize) (object);
 }
 
+static gboolean
+create_dbus_struct_from_user (OobsUser        *user,
+			      DBusMessage     *message,
+			      DBusMessageIter *iter)
+{
+  OobsGroup *group;
+  guint32 uid, gid;
+  gchar *login, *password, *shell, *homedir;
+  gchar *name, *room_number, *work_phone, *home_phone, *other_data;
+  gchar *locale;
+  gboolean enc_home;
+  gboolean passwd_empty, passwd_disabled;
+  gint passwd_flags, home_flags;
+  DBusMessageIter data_iter;
+
+  g_object_get (user,
+		"name", &login,
+		"password", &password,
+		"uid", &uid,
+		"home-directory", &homedir,
+		"shell", &shell,
+		"full-name", &name,
+		"room-number", &room_number,
+		"work-phone", &work_phone,
+		"home-phone", &home_phone,
+		"other-data", &other_data,
+                "encrypted-home", &enc_home,
+                "home-flags", &home_flags,
+                "locale", &locale,
+                "password-empty", &passwd_empty,
+                "password-disabled", &passwd_disabled,
+		NULL);
+
+  /* Login is the only required field,
+   * since home dir, password and shell are allowed to be empty (see man 5 passwd) */
+  g_return_val_if_fail (login, FALSE);
+
+  group = oobs_user_get_main_group (user);
+
+  /* G_MAXUINT32 is used to mean no main group */
+  if (group)
+    gid = oobs_group_get_gid (group);
+  else
+    gid = G_MAXUINT32;
+
+  passwd_flags = passwd_empty | (passwd_disabled << 1);
+
+  utils_append_string (iter, login);
+  utils_append_string (iter, password);
+  utils_append_uint (iter, uid);
+  utils_append_uint (iter, gid);
+
+  dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &data_iter);
+
+  /* GECOS fields */
+  utils_append_string (&data_iter, name);
+  utils_append_string (&data_iter, room_number);
+  utils_append_string (&data_iter, work_phone);
+  utils_append_string (&data_iter, home_phone);
+  utils_append_string (&data_iter, other_data);
+
+  dbus_message_iter_close_container (iter, &data_iter);
+
+  utils_append_string (iter, homedir);
+  utils_append_string (iter, shell);
+  utils_append_int (iter, passwd_flags);
+  utils_append_boolean (iter, enc_home);
+  utils_append_boolean (iter, home_flags);
+  utils_append_string (iter, locale);
+  /* TODO: use location when the backends support it */
+  utils_append_string (iter, "");
+
+  g_free (login);
+  g_free (password);
+  g_free (shell);
+  g_free (homedir);
+  g_free (name);
+  g_free (room_number);
+  g_free (work_phone);
+  g_free (home_phone);
+  g_free (other_data);
+  g_free (locale);
+
+  return TRUE;
+}
+
+static void
+oobs_user_commit (OobsObject *object)
+{
+  DBusMessage *message;
+  DBusMessageIter iter, struct_iter;
+
+  message = _oobs_object_get_dbus_message (object);
+
+  dbus_message_iter_init_append (message, &iter);
+  dbus_message_iter_open_container (&iter, DBUS_TYPE_STRUCT, NULL, &struct_iter);
+  create_dbus_struct_from_user (OOBS_USER (object), message, &struct_iter);
+  dbus_message_iter_close_container (&iter, &struct_iter);
+}
+
 /**
  * oobs_user_new:
  * @name: login name for the new user.
@@ -390,6 +563,7 @@ oobs_user_new (const gchar *name)
 
   return g_object_new (OOBS_TYPE_USER,
 		       "name", name,
+		       "remote-object", USER_REMOTE_OBJECT,
 		       NULL);
 }
 
@@ -421,8 +595,8 @@ oobs_user_get_login_name (OobsUser *user)
  * @password: a new password for the user.
  * 
  * Sets a new password for the user. This password will be
- * interpreted as clean text and encrypted internally, be careful
- * deleting the passed string after using this function.
+ * interpreted as clean text and encrypted by the backends using PAM.
+ * Be careful deleting the passed string after using this function.
  **/
 void
 oobs_user_set_password (OobsUser *user, const gchar *password)
@@ -434,23 +608,6 @@ oobs_user_set_password (OobsUser *user, const gchar *password)
 }
 
 /**
- * oobs_user_set_crypted_password:
- * @user: An #OobsUser.
- * @crypted_password: a new crypted password.
- * 
- * Sets a new password for the user. This password will be
- * considered to be already crypted.
- **/
-void
-oobs_user_set_crypted_password (OobsUser *user, const gchar *crypted_password)
-{
-  g_return_if_fail (user != NULL);
-  g_return_if_fail (OOBS_IS_USER (user));
-
-  g_object_set (G_OBJECT (user), "crypted-password", crypted_password, NULL);
-}
-
-/**
  * oobs_user_get_uid:
  * @user: An #OobsUser.
  * 
@@ -801,6 +958,186 @@ oobs_user_set_other_data (OobsUser *user, const gchar *data)
 }
 
 /**
+ * oobs_user_get_password_empty:
+ * @user: An #OobsUser.
+ *
+ * Returns whether the current password for @user is empty.
+ *
+ * Return Value: %TRUE if @user is using an empty password, %FALSE otherwise.
+ **/
+gboolean
+oobs_user_get_password_empty (OobsUser *user)
+{
+  OobsUserPrivate *priv;
+
+  g_return_val_if_fail (user != NULL, FALSE);
+  g_return_val_if_fail (OOBS_IS_USER (user), FALSE);
+
+  priv = user->_priv;
+
+  return priv->passwd_empty;
+}
+
+/**
+ * oobs_user_set_password_empty:
+ * @user: An #OobsUser.
+ * @empty: whether password for @user should be set to empty.
+ *
+ * Forces an empty password for @user. (Setting the 'password' property
+ * to the empty string is used to keep the current password.)
+ **/
+void
+oobs_user_set_password_empty (OobsUser *user, gboolean empty)
+{
+  OobsUserPrivate *priv;
+
+  g_return_if_fail (user != NULL);
+  g_return_if_fail (OOBS_IS_USER (user));
+
+  priv = user->_priv;
+
+  priv->passwd_empty = empty;
+}
+
+/**
+ * oobs_user_get_password_disabled:
+ * @user: An #OobsUser.
+ *
+ * Returns whether account for @user is currently disabled,
+ * i.e. user is not allowed to log in.
+ *
+ * Return Value: %TRUE if account is disabled, %FALSE otherwise.
+ **/
+gboolean
+oobs_user_get_password_disabled (OobsUser *user)
+{
+  OobsUserPrivate *priv;
+
+  g_return_val_if_fail (user != NULL, FALSE);
+  g_return_val_if_fail (OOBS_IS_USER (user), FALSE);
+
+  priv = user->_priv;
+
+  return priv->passwd_disabled;
+}
+
+/**
+ * oobs_user_set_password_disabled:
+ * @user: An #OobsUser.
+ * @disabled: whether account for @user should be disabled.
+ *
+ * Disable or enable account, allowing or preventing @user from logging in.
+ **/
+void
+oobs_user_set_password_disabled (OobsUser *user, gboolean disabled)
+{
+  OobsUserPrivate *priv;
+
+  g_return_if_fail (user != NULL);
+  g_return_if_fail (OOBS_IS_USER (user));
+
+  priv = user->_priv;
+
+  priv->passwd_disabled = disabled;
+}
+
+/**
+ * oobs_user_get_encrypted_home:
+ * @user: An #OobsUser.
+ *
+ * Returns whether home directory for @user is encrypted (e.g. using eCryptfs).
+ *
+ * Return Value: %TRUE if home is encrypted, %FALSE otherwise.
+ **/
+gboolean
+oobs_user_get_encrypted_home (OobsUser *user)
+{
+  OobsUserPrivate *priv;
+
+  g_return_val_if_fail (user != NULL, FALSE);
+  g_return_val_if_fail (OOBS_IS_USER (user), FALSE);
+
+  priv = user->_priv;
+
+  return priv->encrypted_home;
+}
+
+/**
+ * oobs_user_set_encrypted_home:
+ * @user: An #OobsUser.
+ * @encrypted_home: whether home directory for @user should be encrypted.
+ *
+ * Set whether home directory for @user should be encrypted.
+ * This function should only be used on new users before committing them,
+ * and when the system supports it for the change to take effect.
+ **/
+void
+oobs_user_set_encrypted_home (OobsUser *user, gboolean encrypted_home)
+{
+  OobsUserPrivate *priv;
+
+  g_return_if_fail (user != NULL);
+  g_return_if_fail (OOBS_IS_USER (user));
+
+  priv = user->_priv;
+
+  priv->encrypted_home = encrypted_home;
+}
+
+/**
+ * oobs_user_set_home_flags:
+ * @user: An #OobsUser.
+ * @home_flags: how home directory for @user should be treated.
+ *
+ * Set the flags affecting treatment of the user's home directory (remove home
+ * when deleting user, chown directory to user...).
+ **/
+void
+oobs_user_set_home_flags (OobsUser *user, OobsUserHomeFlags home_flags)
+{
+  g_return_if_fail (user != NULL);
+  g_return_if_fail (OOBS_IS_USER (user));
+
+  g_object_set (G_OBJECT (user), "home-flags", home_flags, NULL);
+}
+
+/**
+ * oobs_user_set_locale:
+ * @user: An #OobsUser.
+ * @locale: Preferred locale for @user.
+ *
+ * Get the ISO 639 code representing the current locale for @user.
+ **/
+G_CONST_RETURN gchar*
+oobs_user_get_locale (OobsUser *user)
+{
+  OobsUserPrivate *priv;
+
+  g_return_val_if_fail (user != NULL, NULL);
+  g_return_val_if_fail (OOBS_IS_USER (user), NULL);
+
+  priv = user->_priv;
+
+  return priv->locale;
+}
+
+/**
+ * oobs_user_set_locale:
+ * @user: An #OobsUser.
+ * @locale: Preferred locale for @user.
+ *
+ * Sets the ISO 639 code representing the current locale for @user.
+ **/
+void
+oobs_user_set_locale (OobsUser *user, const gchar *locale)
+{
+  g_return_if_fail (user != NULL);
+  g_return_if_fail (OOBS_IS_USER (user));
+
+  g_object_set (G_OBJECT (user), "locale", locale, NULL);
+}
+
+/**
  * oobs_user_get_active:
  * @user: An #OobsUser
  *
diff --git a/oobs/oobs-user.h b/oobs/oobs-user.h
index f399f7c..25a75d6 100644
--- a/oobs/oobs-user.h
+++ b/oobs/oobs-user.h
@@ -36,22 +36,31 @@ G_BEGIN_DECLS
 typedef struct _OobsUser        OobsUser;
 typedef struct _OobsUserClass   OobsUserClass;
 
+#include "oobs-object.h"
 #include "oobs-group.h"
+#include "oobs-enum-types.h"
 	
 struct _OobsUser {
-  GObject parent;
+  OobsObject parent;
 
   /*<private>*/
   gpointer _priv;
 };
 
 struct _OobsUserClass {
-  GObjectClass parent_class;
+  OobsObjectClass parent_class;
 
   void (*_oobs_padding1) (void);
   void (*_oobs_padding2) (void);
+  void (*_oobs_padding3) (void);
+  void (*_oobs_padding4) (void);
 };
 
+typedef enum {
+  OOBS_USER_REMOVE_HOME = 1,
+  OOBS_USER_CHOWN_HOME  = 1 << 1
+} OobsUserHomeFlags;
+
 GType oobs_user_get_type (void);
 
 OobsUser* oobs_user_new (const gchar *name);
@@ -59,7 +68,6 @@ OobsUser* oobs_user_new (const gchar *name);
 G_CONST_RETURN gchar* oobs_user_get_login_name (OobsUser *user);
 
 void  oobs_user_set_password (OobsUser *user, const gchar *password);
-void  oobs_user_set_crypted_password (OobsUser *user, const gchar *crypted_password);
 
 uid_t oobs_user_get_uid (OobsUser *user);
 void  oobs_user_set_uid (OobsUser *user, uid_t uid);
@@ -88,6 +96,20 @@ void oobs_user_set_home_phone_number (OobsUser *user, const gchar *phone_number)
 G_CONST_RETURN gchar* oobs_user_get_other_data (OobsUser *user);
 void oobs_user_set_other_data (OobsUser *user, const gchar *data);
 
+gboolean oobs_user_get_password_empty (OobsUser *user);
+void     oobs_user_set_password_empty (OobsUser *user, gboolean empty);
+
+gboolean oobs_user_get_password_disabled (OobsUser *user);
+void     oobs_user_set_password_disabled (OobsUser *user, gboolean disabled);
+
+gboolean oobs_user_get_encrypted_home (OobsUser *user);
+void     oobs_user_set_encrypted_home (OobsUser *user, gboolean encrypted_home);
+
+void     oobs_user_set_home_flags (OobsUser *user, OobsUserHomeFlags home_flags);
+
+G_CONST_RETURN gchar* oobs_user_get_locale (OobsUser *user);
+void                  oobs_user_set_locale (OobsUser *user, const gchar *locale);
+
 gboolean oobs_user_get_active  (OobsUser *user);
 gboolean oobs_user_is_root     (OobsUser *user);
 gboolean oobs_user_is_in_group (OobsUser *user, OobsGroup *group);
diff --git a/oobs/oobs-usersconfig.c b/oobs/oobs-usersconfig.c
index 23696b5..4fe4177 100644
--- a/oobs/oobs-usersconfig.c
+++ b/oobs/oobs-usersconfig.c
@@ -41,7 +41,7 @@
  * @see_also: #OobsUser
  **/
 
-#define USERS_CONFIG_REMOTE_OBJECT "UsersConfig"
+#define USERS_CONFIG_REMOTE_OBJECT "UsersConfig2"
 #define OOBS_USERS_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), OOBS_TYPE_USERS_CONFIG, OobsUsersConfigPrivate))
 
 typedef struct _OobsUsersConfigPrivate OobsUsersConfigPrivate;
@@ -52,14 +52,15 @@ struct _OobsUsersConfigPrivate
 
   GList    *shells;
 
-  gboolean  use_md5;
   uid_t     minimum_uid;
   uid_t     maximum_uid;
   gchar    *default_shell;
   gchar    *default_home;
 
   GHashTable *groups;
-  gint        default_gid;
+  gid_t       default_gid;
+
+  gboolean  encrypted_home;
 
   OobsGroup *default_group;
 };
@@ -87,12 +88,12 @@ static void oobs_users_config_commit     (OobsObject   *object);
 enum
 {
   PROP_0,
-  PROP_USE_MD5,
   PROP_MINIMUM_UID,
   PROP_MAXIMUM_UID,
   PROP_DEFAULT_SHELL,
   PROP_DEFAULT_HOME,
-  PROP_DEFAULT_GROUP
+  PROP_DEFAULT_GROUP,
+  PROP_ENCRYPTED_HOME,
 };
 
 G_DEFINE_TYPE (OobsUsersConfig, oobs_users_config, OOBS_TYPE_OBJECT);
@@ -113,26 +114,19 @@ oobs_users_config_class_init (OobsUsersConfigClass *class)
   oobs_object_class->update  = oobs_users_config_update;
 
   g_object_class_install_property (object_class,
-				   PROP_USE_MD5,
-				   g_param_spec_boolean ("use-md5",
-							 "Use MD5",
-							 "Whether users' passwords are stored in MD5",
-							 FALSE,
-							 G_PARAM_READABLE));
-  g_object_class_install_property (object_class,
 				   PROP_MINIMUM_UID,
-				   g_param_spec_int ("minimum-uid",
-						     "Minimum UID",
-						     "Minimum UID for non-system users",
-						     0, OOBS_MAX_UID, OOBS_MAX_UID,
-						     G_PARAM_READWRITE));
+				   g_param_spec_uint ("minimum-uid",
+						      "Minimum UID",
+				                      "Minimum UID for non-system users",
+						      0, OOBS_MAX_UID, OOBS_MAX_UID,
+						      G_PARAM_READWRITE));
   g_object_class_install_property (object_class,
 				   PROP_MAXIMUM_UID,
-				   g_param_spec_int ("maximum-uid",
-						     "Maximum UID",
-						     "Maximum UID for non-system users",
-						     0, OOBS_MAX_UID, OOBS_MAX_UID,
-						     G_PARAM_READWRITE));
+				   g_param_spec_uint ("maximum-uid",
+				                      "Maximum UID",
+				                      "Maximum UID for non-system users",
+				                      0, OOBS_MAX_UID, OOBS_MAX_UID,
+				                      G_PARAM_READWRITE));
   g_object_class_install_property (object_class,
 				   PROP_DEFAULT_SHELL,
 				   g_param_spec_string ("default-shell",
@@ -154,6 +148,14 @@ oobs_users_config_class_init (OobsUsersConfigClass *class)
 							"Default group for new users",
 							OOBS_TYPE_GROUP,
 							G_PARAM_READABLE));
+  g_object_class_install_property (object_class,
+				   PROP_ENCRYPTED_HOME,
+				   g_param_spec_boolean ("encrypted-home",
+				                         "Encrypted home support",
+				                         "Whether encrypted home dirs are supported",
+				                         FALSE,
+				                         G_PARAM_READABLE));
+
   g_type_class_add_private (object_class,
 			    sizeof (OobsUsersConfigPrivate));
 }
@@ -238,10 +240,10 @@ oobs_users_config_set_property (GObject      *object,
   switch (prop_id)
     {
     case PROP_MINIMUM_UID:
-      priv->minimum_uid = g_value_get_int (value);
+      priv->minimum_uid = g_value_get_uint (value);
       break;
     case PROP_MAXIMUM_UID:
-      priv->maximum_uid = g_value_get_int (value);
+      priv->maximum_uid = g_value_get_uint (value);
       break;
     case PROP_DEFAULT_SHELL:
       g_free (priv->default_shell);
@@ -268,14 +270,11 @@ oobs_users_config_get_property (GObject      *object,
 
   switch (prop_id)
     {
-    case PROP_USE_MD5:
-      g_value_set_boolean (value, priv->use_md5);
-      break;
     case PROP_MINIMUM_UID:
-      g_value_set_int (value, priv->minimum_uid);
+      g_value_set_uint (value, priv->minimum_uid);
       break;
     case PROP_MAXIMUM_UID:
-      g_value_set_int (value, priv->maximum_uid);
+      g_value_set_uint (value, priv->maximum_uid);
       break;
     case PROP_DEFAULT_SHELL:
       g_value_set_string (value, priv->default_shell);
@@ -283,6 +282,8 @@ oobs_users_config_get_property (GObject      *object,
     case PROP_DEFAULT_HOME:
       g_value_set_string (value, priv->default_home);
       break;
+    case PROP_ENCRYPTED_HOME:
+      g_value_set_boolean (value, priv->encrypted_home);
     }
 }
 
@@ -294,17 +295,20 @@ create_user_from_dbus_reply (OobsObject      *object,
   OobsUsersConfigPrivate *priv;
   OobsUser *user;
   DBusMessageIter iter, gecos_iter;
-  int    uid, gid;
+  guint32 uid, gid;
   const gchar *login, *passwd, *home, *shell;
   const gchar *name, *room_number, *work_phone, *home_phone, *other_data;
+  const gchar *locale;
+  gint passwd_flags, home_flags;
+  gboolean enc_home, passwd_empty, passwd_disabled;
 
   priv = OOBS_USERS_CONFIG (object)->_priv;
   dbus_message_iter_recurse (&struct_iter, &iter);
 
   login = utils_get_string (&iter);
   passwd = utils_get_string (&iter);
-  uid = utils_get_int (&iter);
-  gid = utils_get_int (&iter);
+  uid = utils_get_uint (&iter);
+  gid = utils_get_uint (&iter);
 
   /* GECOS fields */
   dbus_message_iter_recurse (&iter, &gecos_iter);
@@ -321,20 +325,32 @@ create_user_from_dbus_reply (OobsObject      *object,
   home = utils_get_string (&iter);
   shell = utils_get_string (&iter);
 
-  user = g_object_new (OOBS_TYPE_USER,
-		       "name", login,
-		       "crypted-password", passwd,
-		       "uid", uid,
-		       "home-directory", home,
-		       "shell", shell,
-		       "full-name", name,
-		       "room-number", room_number,
-		       "work-phone", work_phone,
-		       "home-phone", home_phone,
-		       "other-data", other_data,
-		       NULL);
-
-  /* keep the GID in a hashtable, this will be needed
+  passwd_flags = utils_get_int (&iter);
+  passwd_empty = passwd_flags & 1;
+  passwd_disabled = passwd_flags & (1 << 1);
+
+  enc_home = utils_get_boolean (&iter);
+  home_flags = utils_get_int (&iter);
+  locale = utils_get_string (&iter);
+
+  user = oobs_user_new (login);
+  g_object_set (user,
+                "uid", uid,
+                "home-directory", home,
+                "shell", shell,
+                "full-name", name,
+                "room-number", room_number,
+                "work-phone", work_phone,
+                "home-phone", home_phone,
+                "other-data", other_data,
+                "encrypted-home", enc_home,
+                "home-flags", home_flags,
+                "password-empty", passwd_empty,
+                "password-disabled", passwd_disabled,
+                "locale", locale,
+                NULL);
+
+  /* keep the group name in a hashtable, this will be needed
    * each time the groups configuration changes
    */
   g_hash_table_insert (priv->groups,
@@ -343,75 +359,9 @@ create_user_from_dbus_reply (OobsObject      *object,
   return user;
 }
 
-static gboolean
-create_dbus_struct_from_user (OobsUser        *user,
-			      DBusMessage     *message,
-			      DBusMessageIter *array_iter)
-{
-  OobsGroup *group;
-  gint uid, gid;
-  gchar *login, *password, *shell, *homedir;
-  gchar *name, *room_number, *work_phone, *home_phone, *other_data;
-  DBusMessageIter struct_iter, data_iter;
-
-  g_object_get (user,
-		"name", &login,
-		"crypted-password", &password,
-		"uid", &uid,
-		"home-directory", &homedir,
-		"shell", &shell,
-		"full-name", &name,
-		"room-number", &room_number,
-		"work-phone", &work_phone,
-		"home-phone", &home_phone,
-		"other-data", &other_data,
-		NULL);
-
-  /* Login is the only required field,
-   * since home dir, password and shell are allowed to be empty (see man 5 passwd) */
-  g_return_val_if_fail (login, FALSE);
-
-  group = oobs_user_get_main_group (user);
-  gid = oobs_group_get_gid (group);
-
-  dbus_message_iter_open_container (array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter);
-
-  utils_append_string (&struct_iter, login);
-  utils_append_string (&struct_iter, password);
-  utils_append_int (&struct_iter, uid);
-  utils_append_int (&struct_iter, gid);
-
-  dbus_message_iter_open_container (&struct_iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &data_iter);
-
-  /* GECOS fields */
-  utils_append_string (&data_iter, name);
-  utils_append_string (&data_iter, room_number);
-  utils_append_string (&data_iter, work_phone);
-  utils_append_string (&data_iter, home_phone);
-  utils_append_string (&data_iter, other_data);
-
-  dbus_message_iter_close_container (&struct_iter, &data_iter);
-
-  utils_append_string (&struct_iter, homedir);
-  utils_append_string (&struct_iter, shell);
-  dbus_message_iter_close_container (array_iter, &struct_iter);
-
-  g_free (login);
-  g_free (password);
-  g_free (shell);
-  g_free (homedir);
-  g_free (name);
-  g_free (room_number);
-  g_free (work_phone);
-  g_free (home_phone);
-  g_free (other_data);
-
-  return TRUE;
-}
-
 static void
 query_groups_foreach (OobsUser *user,
-		      uid_t     gid,
+		      gid_t     gid,
 		      gpointer  data)
 {
   OobsGroupsConfig *groups_config = OOBS_GROUPS_CONFIG (data);
@@ -478,13 +428,13 @@ oobs_users_config_update (OobsObject *object)
   dbus_message_iter_next (&iter);
   priv->shells = utils_get_string_list_from_dbus_reply (reply, &iter);
 
-  priv->use_md5 = utils_get_int (&iter);
-  priv->minimum_uid = utils_get_int (&iter);
-  priv->maximum_uid = utils_get_int (&iter);
+  priv->minimum_uid = utils_get_uint (&iter);
+  priv->maximum_uid = utils_get_uint (&iter);
 
   priv->default_home = g_strdup (utils_get_string (&iter));
   priv->default_shell = g_strdup (utils_get_string (&iter));
-  priv->default_gid = utils_get_int (&iter);
+  priv->default_gid = utils_get_uint (&iter);
+  priv->encrypted_home = utils_get_boolean (&iter);
 
   groups_config = oobs_groups_config_get ();
 
@@ -501,69 +451,24 @@ oobs_users_config_commit (OobsObject *object)
 {
   OobsUsersConfigPrivate *priv;
   DBusMessage *message;
-  DBusMessageIter iter, array_iter;
-  OobsListIter list_iter;
-  GObject *user;
-  gboolean valid, correct;
-  gint default_gid;
+  DBusMessageIter iter;
+  guint32 default_gid;
 
   priv = OOBS_USERS_CONFIG (object)->_priv;
   message = _oobs_object_get_dbus_message (object);
 
   dbus_message_iter_init_append (message, &iter);
-  dbus_message_iter_open_container (&iter,
-				    DBUS_TYPE_ARRAY,
-				    DBUS_STRUCT_BEGIN_CHAR_AS_STRING
-				    DBUS_TYPE_STRING_AS_STRING
-				    DBUS_TYPE_STRING_AS_STRING
-				    DBUS_TYPE_INT32_AS_STRING
-				    DBUS_TYPE_INT32_AS_STRING
-				    DBUS_TYPE_ARRAY_AS_STRING
-				    DBUS_TYPE_STRING_AS_STRING
-				    DBUS_TYPE_STRING_AS_STRING
-				    DBUS_TYPE_STRING_AS_STRING
-				    DBUS_STRUCT_END_CHAR_AS_STRING
-				    DBUS_TYPE_INT32_AS_STRING
-				    DBUS_TYPE_INT32_AS_STRING
-				    DBUS_TYPE_INT32_AS_STRING
-				    DBUS_TYPE_STRING_AS_STRING
-				    DBUS_TYPE_STRING_AS_STRING,
-				    &array_iter);
-  valid = oobs_list_get_iter_first (priv->users_list, &list_iter);
-  correct = TRUE;
-
-  while (valid && correct)
-    {
-      user = oobs_list_get (priv->users_list, &list_iter);
-      correct = create_dbus_struct_from_user (OOBS_USER (user), message, &array_iter);
-
-      g_object_unref (user);
-      valid = oobs_list_iter_next (priv->users_list, &list_iter);
-    }
-
-  dbus_message_iter_close_container (&iter, &array_iter);
 
   utils_create_dbus_array_from_string_list (priv->shells, message, &iter);
-  utils_append_int (&iter, priv->use_md5);
-  utils_append_int (&iter, priv->minimum_uid);
-  utils_append_int (&iter, priv->maximum_uid);
+  utils_append_uint (&iter, priv->minimum_uid);
+  utils_append_uint (&iter, priv->maximum_uid);
   utils_append_string (&iter, priv->default_home);
   utils_append_string (&iter, priv->default_shell);
 
-  default_gid = (priv->default_group) ? oobs_group_get_gid (priv->default_group) : -1;
-  utils_append_int (&iter, default_gid);
-
-  if (!correct)
-    {
-      /* malformed data, unset the message */
-      _oobs_object_set_dbus_message (object, NULL);
-    }
-}
-
-static void
-oobs_users_config_add (OobsObject *object)
-{
+  default_gid = (priv->default_group) ? oobs_group_get_gid (priv->default_group) : G_MAXUINT32;
+  utils_append_uint (&iter, default_gid);
 
+  utils_append_boolean (&iter, priv->encrypted_home);
 }
 
 /**
@@ -605,6 +510,88 @@ oobs_users_config_get_users (OobsUsersConfig *config)
 }
 
 /**
+ * oobs_users_config_add_user:
+ * @config: An #OobsUsersConfig.
+ * @user: An #OobsUser.
+ *
+ * Add an user to the configuration, immediately committing changes to the system.
+ * On success, @user will be appended to the users list.
+ *
+ * Return value: an #OobsResult enum with the error code.
+ **/
+OobsResult
+oobs_users_config_add_user (OobsUsersConfig *config, OobsUser *user)
+{
+  OobsUsersConfigPrivate *priv;
+  OobsListIter list_iter;
+  OobsResult result;
+
+  g_return_val_if_fail (config != NULL, OOBS_RESULT_MALFORMED_DATA);
+  g_return_val_if_fail (user != NULL, OOBS_RESULT_MALFORMED_DATA);
+  g_return_val_if_fail (OOBS_IS_USERS_CONFIG (config), OOBS_RESULT_MALFORMED_DATA);
+  g_return_val_if_fail (OOBS_IS_USER (user), OOBS_RESULT_MALFORMED_DATA);
+
+  result = oobs_object_add (OOBS_OBJECT (user));
+
+  if (result != OOBS_RESULT_OK)
+    return result;
+
+  priv = config->_priv;
+
+  oobs_list_append (priv->users_list, &list_iter);
+  oobs_list_set (priv->users_list, &list_iter, G_OBJECT (user));
+
+  return OOBS_RESULT_OK;
+}
+
+/**
+ * oobs_users_config_delete_user:
+ * @config: An #OobsUsersConfig.
+ * @user: An #OobsUser.
+ *
+ * Delete an user from the configuration, immediately committing changes to the system.
+ * On success, @user will be removed from the users list.
+ *
+ * Return value: an #OobsResult enum with the error code.
+ **/
+OobsResult
+oobs_users_config_delete_user (OobsUsersConfig *config, OobsUser *user)
+{
+  OobsUsersConfigPrivate *priv;
+  OobsUser *list_user;
+  OobsListIter list_iter;
+  gboolean valid;
+  OobsResult result;
+
+  g_return_val_if_fail (config != NULL, OOBS_RESULT_MALFORMED_DATA);
+  g_return_val_if_fail (user != NULL, OOBS_RESULT_MALFORMED_DATA);
+  g_return_val_if_fail (OOBS_IS_USERS_CONFIG (config), OOBS_RESULT_MALFORMED_DATA);
+  g_return_val_if_fail (OOBS_IS_USER (user), OOBS_RESULT_MALFORMED_DATA);
+
+  result = oobs_object_delete (OOBS_OBJECT (user));
+
+  if (result != OOBS_RESULT_OK)
+    return result;
+
+  priv = config->_priv;
+
+  valid = oobs_list_get_iter_first (priv->users_list, &list_iter);
+
+  while (valid) {
+    list_user = OOBS_USER (oobs_list_get (priv->users_list, &list_iter));
+
+    if (list_user == user)
+      break;
+
+    valid = oobs_list_iter_next (priv->users_list, &list_iter);
+  }
+
+  oobs_list_remove (priv->users_list, &list_iter);
+
+  return OOBS_RESULT_OK;
+}
+
+/**
  * oobs_users_config_get_minimum_users_uid:
  * @config: An #OobsUsersConfig.
  * 
@@ -799,6 +786,27 @@ oobs_users_config_get_available_shells (OobsUsersConfig *config)
   return priv->shells;
 }
 
+/**
+ * oobs_users_config_get_encrypted_home_support:
+ * @config: An #OobsUsersConfig
+ *
+ * Returns whether encrypted home directories are supported by the platform
+ * (e.g. using eCryptfs).
+ *
+ * Return Value: %TRUE if encrypted home dirs are supported, %FALSE otherwise.
+ **/
+gboolean
+oobs_users_config_get_encrypted_home_support (OobsUsersConfig *config)
+{
+  OobsUsersConfigPrivate *priv;
+
+  g_return_val_if_fail (config != NULL, FALSE);
+  g_return_val_if_fail (OOBS_IS_USERS_CONFIG (config), FALSE);
+
+  priv = config->_priv;
+
+  return priv->encrypted_home;
+}
 
 /*
  * Convenience functions to make working with the users list easier.
diff --git a/oobs/oobs-usersconfig.h b/oobs/oobs-usersconfig.h
index 53dfdd4..d1c09f6 100644
--- a/oobs/oobs-usersconfig.h
+++ b/oobs/oobs-usersconfig.h
@@ -62,6 +62,9 @@ GType       oobs_users_config_get_type     (void);
 OobsObject* oobs_users_config_get          (void);
 OobsList*   oobs_users_config_get_users    (OobsUsersConfig *config);
 
+OobsResult  oobs_users_config_add_user    (OobsUsersConfig *config, OobsUser *user);
+OobsResult  oobs_users_config_delete_user (OobsUsersConfig *config, OobsUser *user);
+
 uid_t       oobs_users_config_get_minimum_users_uid (OobsUsersConfig *config);
 void        oobs_users_config_set_minimum_users_uid (OobsUsersConfig *config, uid_t uid);
 
@@ -74,8 +77,11 @@ void                  oobs_users_config_set_default_shell (OobsUsersConfig *conf
 G_CONST_RETURN gchar* oobs_users_config_get_default_home_dir (OobsUsersConfig *config);
 void                  oobs_users_config_set_default_home_dir (OobsUsersConfig *config, const gchar *home_dir);
 
-OobsGroup*  oobs_users_config_get_default_group    (OobsUsersConfig *config);
-GList*      oobs_users_config_get_available_shells (OobsUsersConfig *config);
+OobsGroup*  oobs_users_config_get_default_group          (OobsUsersConfig *config);
+GList*      oobs_users_config_get_available_shells       (OobsUsersConfig *config);
+
+gboolean    oobs_users_config_get_encrypted_home_support (OobsUsersConfig *config);
+GList*      oobs_users_config_get_available_locales      (OobsUsersConfig *config);
 
 OobsUser*   oobs_users_config_get_from_login       (OobsUsersConfig *config,
                                                     const gchar     *login);
diff --git a/oobs/oobs.h b/oobs/oobs.h
index 31f676a..349bc29 100644
--- a/oobs/oobs.h
+++ b/oobs/oobs.h
@@ -23,6 +23,7 @@
 
 #include <glib-object.h>
 #include <oobs/oobs-object.h>
+#include <oobs/oobs-enum-types.h>
 #include <oobs/oobs-session.h>
 #include <oobs/oobs-list.h>
 #include <oobs/oobs-defines.h>
diff --git a/oobs/utils.c b/oobs/utils.c
index 7d5855f..de568a6 100644
--- a/oobs/utils.c
+++ b/oobs/utils.c
@@ -102,6 +102,12 @@ utils_append_uint (DBusMessageIter *iter, guint value)
   dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &value);
 }
 
+void
+utils_append_boolean (DBusMessageIter *iter, gboolean value)
+{
+  dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &value);
+}
+
 static void
 utils_get_basic (DBusMessageIter *iter,
 		 gint             type,
@@ -154,3 +160,12 @@ utils_get_uint (DBusMessageIter *iter)
   utils_get_basic (iter, DBUS_TYPE_UINT32, &value);
   return value;
 }
+
+gboolean
+utils_get_boolean (DBusMessageIter *iter)
+{
+  gboolean value = FALSE;
+
+  utils_get_basic (iter, DBUS_TYPE_BOOLEAN, &value);
+  return value;
+}
diff --git a/oobs/utils.h b/oobs/utils.h
index 176fb80..3d3ae8e 100644
--- a/oobs/utils.h
+++ b/oobs/utils.h
@@ -33,11 +33,13 @@ gchar *utils_get_random_string                  (gint len);
 void   utils_append_string                      (DBusMessageIter *iter, const gchar *str);
 void   utils_append_int                         (DBusMessageIter *iter, gint value);
 void   utils_append_uint                        (DBusMessageIter *iter, guint value);
+void   utils_append_boolean                     (DBusMessageIter *iter, gboolean value);
 
 G_CONST_RETURN gchar* utils_get_string          (DBusMessageIter *iter);
 gchar *               utils_dup_string          (DBusMessageIter *iter);
-gint  utils_get_int                             (DBusMessageIter *iter);
-guint utils_get_uint                            (DBusMessageIter *iter);
+gint     utils_get_int                          (DBusMessageIter *iter);
+guint    utils_get_uint                         (DBusMessageIter *iter);
+gboolean utils_get_boolean                      (DBusMessageIter *iter);
 
 G_END_DECLS
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]