rpms/GConf2/devel gconf-defaults.patch, NONE, 1.1 GConf2.spec, 1.78, 1.79

Matthias Clasen (mclasen) fedora-extras-commits at redhat.com
Sat May 3 03:24:04 UTC 2008


Author: mclasen

Update of /cvs/extras/rpms/GConf2/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv19181

Modified Files:
	GConf2.spec 
Added Files:
	gconf-defaults.patch 
Log Message:
Add a dbus service for setting default values


gconf-defaults.patch:

--- NEW FILE gconf-defaults.patch ---
diff -u -r GConf-2.22.0/configure.in hacked/configure.in
--- GConf-2.22.0/configure.in	2008-03-10 10:52:28.000000000 -0400
+++ hacked/configure.in	2008-05-02 00:05:01.000000000 -0400
@@ -166,6 +166,7 @@
 AC_SUBST(DEPENDENT_WITH_XML_AND_GTK_LIBS)
 AC_SUBST(DEPENDENT_WITH_XML_AND_GTK_CFLAGS)
 
+PKG_CHECK_MODULES(DEFAULTS, glib-2.0 gobject-2.0 gconf-2.0 dbus-1 dbus-glib-1 polkit-dbus)
 
 ORBIT_IDL="`$PKG_CONFIG --variable=orbit_idl ORBit-2.0`"
 AC_SUBST(ORBIT_IDL)
@@ -261,6 +262,7 @@
 doc/gconf/Makefile
 examples/Makefile
 tests/Makefile
+defaults/Makefile
 gconf-2.0.pc
 ])
 
diff -u -r GConf-2.22.0/defaults/gconf-defaults.c hacked/defaults/gconf-defaults.c
--- GConf-2.22.0/defaults/gconf-defaults.c	2008-05-02 23:07:19.000000000 -0400
+++ hacked/defaults/gconf-defaults.c	2008-05-02 22:12:17.000000000 -0400
@@ -0,0 +1,704 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Matthias Clasen <mclasen at redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <pwd.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <polkit-dbus/polkit-dbus.h>
+#include <polkit/polkit.h>
+
+#define GCONF_ENABLE_INTERNALS
+#include <gconf/gconf-client.h>
+#include <gconf/gconf-engine.h>
+
+#include "gconf-defaults.h"
+#include "gconf-defaults-glue.h"
+
+static gboolean
+do_exit (gpointer user_data)
+{
+        g_debug ("Exiting due to inactivity");
+        exit (1);
+        return FALSE;
+}
+
+static guint timer_id = 0;
+
+static void
+stop_killtimer (void)
+{
+        if (timer_id > 0) {
+                g_source_remove (timer_id);
+		timer_id = 0;
+        }
+}
+
+static void
+start_killtimer (void)
+{
+        g_debug ("Setting killtimer to 30 seconds...");
+        timer_id = g_timeout_add_seconds (30, do_exit, NULL);
+}
+
+struct GConfDefaultsPrivate
+{
+        DBusGConnection *system_bus_connection;
+        DBusGProxy      *system_bus_proxy;
+        PolKitContext   *pol_ctx;
+};
+
+static void gconf_defaults_finalize (GObject *object);
+
+G_DEFINE_TYPE (GConfDefaults, gconf_defaults, G_TYPE_OBJECT)
+
+#define GCONF_DEFAULTS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GCONF_TYPE_DEFAULTS, GConfDefaultsPrivate))
+
+GQuark
+gconf_defaults_error_quark (void)
+{
+        static GQuark ret = 0;
+
+        if (ret == 0) {
+                ret = g_quark_from_static_string ("gconf_defaults_error");
+        }
+
+        return ret;
+}
+
+
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+
+GType
+gconf_defaults_error_get_type (void)
+{
+        static GType etype = 0;
+        
+        if (etype == 0)
+        {
+                static const GEnumValue values[] =
+                        {
+                                ENUM_ENTRY (GCONF_DEFAULTS_ERROR_GENERAL, "GeneralError"),
+                                ENUM_ENTRY (GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED, "NotPrivileged"),
+                                { 0, 0, 0 }
+                        };
+                
+                g_assert (GCONF_DEFAULTS_NUM_ERRORS == G_N_ELEMENTS (values) - 1);
+                
+                etype = g_enum_register_static ("GConfDefaultsError", values);
+        }
+        
+        return etype;
+}
+
+
+static GObject *
+gconf_defaults_constructor (GType                  type,
+                            guint                  n_construct_properties,
+                            GObjectConstructParam *construct_properties)
+{
+        GConfDefaults      *mechanism;
+        GConfDefaultsClass *klass;
+
+        klass = GCONF_DEFAULTS_CLASS (g_type_class_peek (GCONF_TYPE_DEFAULTS));
+
+        mechanism = GCONF_DEFAULTS (G_OBJECT_CLASS (gconf_defaults_parent_class)->constructor (
+                                                type,
+                                                n_construct_properties,
+                                                construct_properties));
+
+        return G_OBJECT (mechanism);
+}
+
+static void
+gconf_defaults_class_init (GConfDefaultsClass *klass)
+{
+        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->constructor = gconf_defaults_constructor;
+        object_class->finalize = gconf_defaults_finalize;
+
+        g_type_class_add_private (klass, sizeof (GConfDefaultsPrivate));
+
+        dbus_g_object_type_install_info (GCONF_TYPE_DEFAULTS, &dbus_glib_gconf_defaults_object_info);
+
+        dbus_g_error_domain_register (GCONF_DEFAULTS_ERROR, NULL, GCONF_DEFAULTS_TYPE_ERROR);
+
+}
+
+static void
+gconf_defaults_init (GConfDefaults *mechanism)
+{
+        mechanism->priv = GCONF_DEFAULTS_GET_PRIVATE (mechanism);
+}
+
+static void
+gconf_defaults_finalize (GObject *object)
+{
+        GConfDefaults *mechanism;
+
+        g_return_if_fail (object != NULL);
+        g_return_if_fail (GCONF_IS_DEFAULTS (object));
+
+        mechanism = GCONF_DEFAULTS (object);
+
+        g_return_if_fail (mechanism->priv != NULL);
+
+        g_object_unref (mechanism->priv->system_bus_proxy);
+
+        G_OBJECT_CLASS (gconf_defaults_parent_class)->finalize (object);
+}
+
+static gboolean
+pk_io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data)
+{
+        int fd;
+        PolKitContext *pk_context = user_data;
+        fd = g_io_channel_unix_get_fd (channel);
+        polkit_context_io_func (pk_context, fd);
+        return TRUE;
+}
+
+static int 
+pk_io_add_watch (PolKitContext *pk_context, int fd)
+{
+        guint id = 0;
+        GIOChannel *channel;
+        channel = g_io_channel_unix_new (fd);
+        if (channel == NULL)
+                goto out;
+        id = g_io_add_watch (channel, G_IO_IN, pk_io_watch_have_data, pk_context);
+        if (id == 0) {
+                g_io_channel_unref (channel);
+                goto out;
+        }
+        g_io_channel_unref (channel);
+out:
+        return id;
+}
+
+static void 
+pk_io_remove_watch (PolKitContext *pk_context, int watch_id)
+{
+        g_source_remove (watch_id);
+}
+
+static gboolean
+register_mechanism (GConfDefaults *mechanism)
+{
+        GError *error = NULL;
+
+        mechanism->priv->pol_ctx = polkit_context_new ();
+        polkit_context_set_io_watch_functions (mechanism->priv->pol_ctx, pk_io_add_watch, pk_io_remove_watch);
+        if (!polkit_context_init (mechanism->priv->pol_ctx, NULL)) {
+                g_critical ("cannot initialize libpolkit");
+                goto error;
+        }
+
+        error = NULL;
+        mechanism->priv->system_bus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (mechanism->priv->system_bus_connection == NULL) {
+                if (error != NULL) {
+                        g_critical ("error getting system bus: %s", error->message);
+                        g_error_free (error);
+                }
+                goto error;
+        }
+
+        dbus_g_connection_register_g_object (mechanism->priv->system_bus_connection, "/", 
+                                             G_OBJECT (mechanism));
+
+        mechanism->priv->system_bus_proxy = dbus_g_proxy_new_for_name (mechanism->priv->system_bus_connection,
+                                                                      DBUS_SERVICE_DBUS,
+                                                                      DBUS_PATH_DBUS,
+                                                                      DBUS_INTERFACE_DBUS);
+
+        start_killtimer ();
+
+        return TRUE;
+
+error:
+        return FALSE;
+}
+
+
+GConfDefaults *
+gconf_defaults_new (void)
+{
+        GObject *object;
+        gboolean res;
+
+        object = g_object_new (GCONF_TYPE_DEFAULTS, NULL);
+
+        res = register_mechanism (GCONF_DEFAULTS (object));
+        if (! res) {
+                g_object_unref (object);
+                return NULL;
+        }
+
+        return GCONF_DEFAULTS (object);
+}
+
+static const char *
+polkit_action_for_gconf_path (GConfDefaults *mechanism,
+			      const char    *annotation_key,
+			      const char    *path)
+{
+	PolKitPolicyCache *cache;
+	PolKitPolicyFileEntry *entry;
+	char *prefix, *p;
+	const char *action;
+
+	cache = polkit_context_get_policy_cache (mechanism->priv->pol_ctx);	
+	prefix = g_strdup (path);
+
+	while (1) {
+		entry = polkit_policy_cache_get_entry_by_annotation (cache,
+								     annotation_key,
+								     prefix);
+		if (entry) {
+			action = polkit_policy_file_entry_get_id (entry);
+			break;
+		}
+		
+		p = strrchr (prefix, '/');
+
+		if (p == NULL || p == prefix) {
+			action = NULL;
+			break;
+		}
+	
+		*p = 0;
+	}
+
+	g_free (prefix);
+
+	return action;
+}
+
+static gboolean
+check_polkit_for_action (GConfDefaults         *mechanism,
+                         DBusGMethodInvocation *context,
+                         const char            *action)
+{
+        const char *sender;
+        GError *error;
+        DBusError dbus_error;
+        PolKitCaller *pk_caller;
+        PolKitAction *pk_action;
+        PolKitResult pk_result;
+
+        error = NULL;
+
+        /* Check that caller is privileged */
+        sender = dbus_g_method_get_sender (context);
+        dbus_error_init (&dbus_error);
+        pk_caller = polkit_caller_new_from_dbus_name (
+                dbus_g_connection_get_connection (mechanism->priv->system_bus_connection),
+                sender,
+                &dbus_error);
+        if (pk_caller == NULL) {
+                error = g_error_new (GCONF_DEFAULTS_ERROR,
+                                     GCONF_DEFAULTS_ERROR_GENERAL,
+                                     "Error getting information about caller: %s: %s",
+                                     dbus_error.name, dbus_error.message);
+                dbus_error_free (&dbus_error);
+                dbus_g_method_return_error (context, error);
+                g_error_free (error);
+                return FALSE;
+        }
+
+        pk_action = polkit_action_new ();
+        polkit_action_set_action_id (pk_action, action);
+        pk_result = polkit_context_is_caller_authorized (mechanism->priv->pol_ctx, pk_action, pk_caller, TRUE, NULL);
+        polkit_caller_unref (pk_caller);
+
+        if (pk_result != POLKIT_RESULT_YES) {
+		dbus_error_init (&dbus_error);
+		polkit_dbus_error_generate (pk_action, pk_result, &dbus_error);
+		dbus_set_g_error (&error, &dbus_error);
+                dbus_g_method_return_error (context, error);
+                dbus_error_free (&dbus_error);
+                g_error_free (error);
+        	polkit_action_unref (pk_action);
+                return FALSE;
+        }
+
+        polkit_action_unref (pk_action);
+        return TRUE;
+}
+
+static char *
+gconf_address_for_caller (GConfDefaults          *mechanism,
+			  DBusGMethodInvocation  *context,
+			  GError                **gerror)
+{
+        char *sender;
+	DBusConnection *conn;
+	uid_t uid;
+	struct passwd *pwd;
+	char *result;
+	DBusError error;
+
+	conn = dbus_g_connection_get_connection (mechanism->priv->system_bus_connection);
+        sender = dbus_g_method_get_sender (context);
+
+	dbus_error_init (&error);
+	uid = dbus_bus_get_unix_user (conn, sender, &error);
+	g_free (sender);
+	if (uid == (unsigned)-1) {
+		dbus_set_g_error (gerror, &error);
+		dbus_error_free (&error);
+		return NULL;
+	}
+	
+	pwd = getpwuid (uid);
+	if (pwd == NULL) {
+		g_set_error (gerror, 
+			     0, 0, 
+			     "Failed to get passwd information for uid %d", uid);
+		return NULL;
+	}
+
+	result = g_strconcat ("xml:merged:", pwd->pw_dir, "/.gconf", NULL);
+	return result;
+}
+
+static gboolean
+path_is_excluded (const char  *path,
+		  const char **excludes)
+{
+	int i;
+
+	for (i = 0; excludes && excludes[i]; i++) {
+		if (g_str_has_prefix (path, excludes[i]))
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+static void
+copy_tree (GConfClient     *src,
+	   const char      *path,
+	   GConfChangeSet  *changes,
+	   const char     **excludes)
+{
+	GSList *list, *l;
+	GConfEntry *entry;
+
+	if (path_is_excluded (path, excludes)) 
+		return;
+
+	list = gconf_client_all_entries (src, path, NULL);
+	for (l = list; l; l = l->next) {
+		entry = l->data;
+		if (!path_is_excluded (entry->key, excludes)) 
+			gconf_change_set_set (changes, entry->key, entry->value);
+	}
+	g_slist_foreach (list, (GFunc)gconf_entry_free, NULL);
+	g_slist_free (list);
+
+	list = gconf_client_all_dirs (src, path, NULL);
+	for (l = list; l; l = l->next)
+		copy_tree (src, (const char *)l->data, changes, excludes);
+	g_slist_foreach (list, (GFunc)g_free, NULL);
+	g_slist_free (list);
+}
+
+static void
+copy_entry (GConfClient     *src,
+	    const char      *path,
+	    GConfChangeSet  *changes,
+	    const char     **excludes)
+{
+	GConfValue *value;
+
+	if (path_is_excluded (path, excludes)) 
+		return;
+
+	value = gconf_client_get (src, path, NULL);
+	if (value) {
+		gconf_change_set_set (changes, path, value);
+		gconf_value_free (value);
+	}
+}
+
+
+void
+do_copy (GConfDefaults          *mechanism,
+	 gboolean                mandatory,
+	 const char            **includes,
+	 const char            **excludes,
+	 DBusGMethodInvocation  *context)
+{
+        char *address = NULL;
+	GConfClient *source = NULL; 
+	GConfClient *dest = NULL;
+	GConfChangeSet *changes = NULL;
+	GConfEngine *engine;
+	GError *error;
+	GError *error2;
+	const char *action;
+	const char *annotation_key;
+	const char *default_action;
+	const char *dest_address;
+	int i;
+
+        stop_killtimer ();
+
+	/* check privileges for each include */
+	if (mandatory) {
+		annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix"; 
+		default_action = "org.gnome.gconf.defaults.set-mandatory";
+		dest_address = "xml:merged:/etc/gconf/gconf.xml.mandatory";
+	}
+	else {
+		annotation_key = "org.gnome.gconf.defaults.set-system.prefix"; 
+		default_action = "org.gnome.gconf.defaults.set-system";
+		dest_address = "xml:merged:/etc/gconf/gconf.xml.system";
+	}
+
+	for (i = 0; includes[i]; i++) {
+		action = polkit_action_for_gconf_path (mechanism, annotation_key, includes[i]);
+		if (action == NULL) 
+			action = default_action;
+
+		if (!check_polkit_for_action (mechanism, context, action)) 
+			goto out;
+	}
+
+	error = NULL;
+	engine = gconf_engine_get_local (dest_address, &error);
+	if (error) 
+		goto cleanup;	
+
+	dest = gconf_client_get_for_engine (engine);
+	gconf_engine_unref (engine);
+
+	/* find the address to from the caller id */
+        address = gconf_address_for_caller (mechanism, context, &error);
+	if (error)
+		goto cleanup;
+
+	engine = gconf_engine_get_local (address, &error);
+	if (error) 
+		goto cleanup;
+
+	source = gconf_client_get_for_engine (engine);
+	gconf_engine_unref (engine);
+
+	changes = gconf_change_set_new ();
+
+ 	/* recursively copy each include, leaving out the excludes */
+	for (i = 0; includes[i]; i++) {
+		if (gconf_client_dir_exists (source, includes[i], NULL))
+			copy_tree (source, includes[i], changes, excludes);
+		else
+			copy_entry (source, includes[i], changes, excludes);
+	}
+
+	gconf_client_commit_change_set (dest, changes, TRUE, &error);
+	gconf_client_suggest_sync (dest, NULL);
+
+cleanup:
+	g_free (address);
+	if (changes)
+		gconf_change_set_unref (changes);
+	if (dest) 
+		g_object_unref (dest);
+	if (source)
+		g_object_unref (source);
+
+	if (error) {
+		g_print ("failed to set GConf values:  %s\n", error->message);
+		error2 = g_error_new (GCONF_DEFAULTS_ERROR,
+				      GCONF_DEFAULTS_ERROR_GENERAL,
+				      error->message);
+		g_error_free (error);
+
+		dbus_g_method_return_error (context, error2);
+		g_error_free (error2);
+	}
+	else
+        	dbus_g_method_return (context);
+
+out:
+	start_killtimer ();
+}
+
+void
+gconf_defaults_set_system (GConfDefaults          *mechanism,
+			   const char            **includes,
+			   const char            **excludes,
+			   DBusGMethodInvocation  *context)
+{
+	do_copy (mechanism, FALSE, includes, excludes, context);	
+}
+
+
+void
+gconf_defaults_set_mandatory (GConfDefaults          *mechanism,
+                              const char            **includes,
+                              const char            **excludes,
+                              DBusGMethodInvocation  *context)
+{
+	do_copy (mechanism, TRUE, includes, excludes, context);
+}
+
+static void
+unset_tree (GConfClient     *dest,
+            const char      *path,
+	    GConfChangeSet  *changes,
+            const char     **excludes)
+{
+	GSList *list, *l;
+	GConfEntry *entry;
+
+	if (path_is_excluded (path, excludes)) 
+		return;
+
+	list = gconf_client_all_entries (dest, path, NULL);
+	for (l = list; l; l = l->next) {
+		entry = l->data;
+		if (!path_is_excluded (entry->key, excludes)) 
+			gconf_change_set_unset (changes, entry->key);
+	}
+	g_slist_foreach (list, (GFunc)gconf_entry_free, NULL);
+	g_slist_free (list);
+
+	list = gconf_client_all_dirs (dest, path, NULL);
+	for (l = list; l; l = l->next)
+		unset_tree (dest, (const char *)l->data, changes, excludes);
+	g_slist_foreach (list, (GFunc)g_free, NULL);
+	g_slist_free (list);
+}
+            
+static void
+unset_entry (GConfClient     *dest,
+             const char      *path,
+	     GConfChangeSet  *changes,
+             const char     **excludes)
+{
+	if (path_is_excluded (path, excludes)) 
+		return;
+
+	gconf_change_set_unset (changes, path);
+}
+            
+static void
+unset_in_db (GConfDefaults  *mechanism,
+	     const char     *address,
+             const char    **includes,
+             const char    **excludes,
+	     GError        **error)
+{
+	GConfEngine *engine;
+	GConfClient *dest = NULL;
+	GConfChangeSet *changes = NULL;
+	int i;
+
+	engine = gconf_engine_get_local (address, error);
+	if (*error) 
+		goto out;
+
+	dest = gconf_client_get_for_engine (engine);
+	gconf_engine_unref (engine);
+
+	changes = gconf_change_set_new ();
+
+ 	/* recursively copy each include, leaving out the excludes */
+	for (i = 0; includes[i]; i++) {
+		if (gconf_client_dir_exists (dest, includes[i], NULL))
+			unset_tree (dest, includes[i], changes, excludes);
+		else
+			unset_entry (dest, includes[i], changes, excludes);
+	}
+
+	gconf_client_commit_change_set (dest, changes, TRUE, error);
+	gconf_client_suggest_sync (dest, NULL);
+
+out:
+	if (dest)
+		g_object_unref (dest);
+	if (changes)
+		gconf_change_set_unref (changes);
+}
+
+void
+gconf_defaults_unset_mandatory (GConfDefaults          *mechanism,
+                                const char            **includes,
+                                const char            **excludes,
+                                DBusGMethodInvocation  *context)
+{
+	const char *annotation_key;
+	const char *default_action;
+	int i;
+	const char *action;
+	GError *error;
+	GError *error2;
+
+	stop_killtimer ();
+
+	annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix"; 
+	default_action = "org.gnome.gconf.defaults.set-mandatory";
+
+	for (i = 0; includes[i]; i++) {
+		action = polkit_action_for_gconf_path (mechanism, annotation_key, includes[i]);
+		if (action == NULL) 
+			action = default_action;
+
+		if (!check_polkit_for_action (mechanism, context, action)) 
+			goto out;
+	}
+
+	error = NULL;
+	unset_in_db (mechanism,"xml:merged:/etc/gconf/gconf.xml.mandatory", 
+		     includes, excludes, &error);
+
+	if (error) {
+		error2 = g_error_new (GCONF_DEFAULTS_ERROR,
+				      GCONF_DEFAULTS_ERROR_GENERAL,
+				      error->message);
+		g_error_free (error);
+
+		dbus_g_method_return_error (context, error2);
+		g_error_free (error2);
+	}
+	else
+        	dbus_g_method_return (context);
+out:
+	start_killtimer();
+}
diff -u -r GConf-2.22.0/defaults/gconf-defaults.h hacked/defaults/gconf-defaults.h
--- GConf-2.22.0/defaults/gconf-defaults.h	2008-05-02 23:07:19.000000000 -0400
+++ hacked/defaults/gconf-defaults.h	2008-05-02 14:08:18.000000000 -0400
@@ -0,0 +1,84 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008  Matthias Clasen  <mclasen at redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef GCONF_DEFAULTS_H
+#define GCONF_DEFAULTS_H
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+G_BEGIN_DECLS
+
+#define GCONF_TYPE_DEFAULTS         (gconf_defaults_get_type ())
+#define GCONF_DEFAULTS(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GCONF_TYPE_DEFAULTS, GConfDefaults))
+#define GCONF_DEFAULTS_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GCONF_TYPE_DEFAULTS, GConfDefaultsClass))
+#define GCONF_IS_DEFAULTS(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GCONF_TYPE_DEFAULTS))
+#define GCONF_IS_DEFAULTS_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GCONF_TYPE_DEFAULTS))
+#define GCONF_DEFAULTS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GCONF_TYPE_DEFAULTS, GConfDefaultsClass))
+
+typedef struct GConfDefaultsPrivate GConfDefaultsPrivate;
+
+typedef struct
+{
+        GObject        parent;
+        GConfDefaultsPrivate *priv;
+} GConfDefaults;
+
+typedef struct
+{
+        GObjectClass   parent_class;
+} GConfDefaultsClass;
+
+typedef enum
+{
+        GCONF_DEFAULTS_ERROR_GENERAL,
+        GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED,
+        GCONF_DEFAULTS_NUM_ERRORS
+} GConfDefaultsError;
+
+#define GCONF_DEFAULTS_ERROR gconf_defaults_error_quark ()
+
+GType gconf_defaults_error_get_type (void);
+#define GCONF_DEFAULTS_TYPE_ERROR (gconf_defaults_error_get_type ())
+
+
+GQuark         gconf_defaults_error_quark    (void);
+GType          gconf_defaults_get_type       (void);
+GConfDefaults *gconf_defaults_new            (void);
+
+/* exported methods */
+void           gconf_defaults_set_system        (GConfDefaults          *mechanism,
+                                                 const char            **includes,
+                                                 const char            **excludes,
+                                                 DBusGMethodInvocation  *context);
+
+void           gconf_defaults_set_mandatory     (GConfDefaults          *mechanism,
+                                                 const char            **includes,
+                                                 const char            **excludes,
+                                                 DBusGMethodInvocation  *context);
+
+void           gconf_defaults_unset_mandatory   (GConfDefaults          *mechanism,
+                                                 const char            **includes,
+                                                 const char            **excludes,
+                                                 DBusGMethodInvocation  *context);
+
+G_END_DECLS
+
+#endif /* GCONF_DEFAULTS_H */
diff -u -r GConf-2.22.0/defaults/gconf-defaults-main.c hacked/defaults/gconf-defaults-main.c
--- GConf-2.22.0/defaults/gconf-defaults-main.c	2008-05-02 23:07:19.000000000 -0400
+++ hacked/defaults/gconf-defaults-main.c	2008-05-01 14:41:50.000000000 -0400
@@ -0,0 +1,174 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Matthias Clasen <mclasen at redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+
+#include "gconf-defaults.h"
+
+static DBusGProxy *
+get_bus_proxy (DBusGConnection *connection)
+{
+        DBusGProxy *bus_proxy;
+
+	bus_proxy = dbus_g_proxy_new_for_name (connection,
+                                               DBUS_SERVICE_DBUS,
+                                               DBUS_PATH_DBUS,
+                                               DBUS_INTERFACE_DBUS);
+        return bus_proxy;
+}
+
+#define BUS_NAME "org.gnome.GConf.Defaults"
+
+static gboolean
+acquire_name_on_proxy (DBusGProxy *bus_proxy)
+{
+        GError     *error;
+        guint       result;
+        gboolean    res;
+        gboolean    ret;
+
+        ret = FALSE;
+
+        if (bus_proxy == NULL) {
+                goto out;
+        }
+
+        error = NULL;
+	res = dbus_g_proxy_call (bus_proxy,
+                                 "RequestName",
+                                 &error,
+                                 G_TYPE_STRING, BUS_NAME,
+                                 G_TYPE_UINT, 0,
+                                 G_TYPE_INVALID,
+                                 G_TYPE_UINT, &result,
+                                 G_TYPE_INVALID);
+        if (! res) {
+                if (error != NULL) {
+                        g_warning ("Failed to acquire %s: %s", BUS_NAME, error->message);
+                        g_error_free (error);
+                } else {
+                        g_warning ("Failed to acquire %s", BUS_NAME);
+                }
+                goto out;
+	}
+
+ 	if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+                if (error != NULL) {
+                        g_warning ("Failed to acquire %s: %s", BUS_NAME, error->message);
+                        g_error_free (error);
+                } else {
+                        g_warning ("Failed to acquire %s", BUS_NAME);
+                }
+                goto out;
+        }
+
+        ret = TRUE;
+
+ out:
+        return ret;
+}
+
+static DBusGConnection *
+get_system_bus (void)
+{
+        GError          *error;
+        DBusGConnection *bus;
+        DBusConnection  *connection;
+
+        error = NULL;
+        bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (bus == NULL) {
+                g_warning ("Couldn't connect to system bus: %s", error->message);
+                g_error_free (error);
+                goto out;
+        }
+
+        connection = dbus_g_connection_get_connection (bus);
+ out:
+        return bus;
+}
+
+int
+main (int argc, char **argv)
+{
+        GMainLoop           *loop;
+        GConfDefaults       *mechanism;
+        DBusGProxy          *bus_proxy;
+        DBusGConnection     *connection;
+        int                  ret;
+
+        ret = 1;
+
+        if (! g_thread_supported ()) {
+                g_thread_init (NULL);
+        }
+        dbus_g_thread_init ();
+        g_type_init ();
+
+        connection = get_system_bus ();
+        if (connection == NULL) {
+                goto out;
+        }
+
+        bus_proxy = get_bus_proxy (connection);
+        if (bus_proxy == NULL) {
+                g_warning ("Could not construct bus_proxy object; bailing out");
+                goto out;
+        }
+
+        mechanism = gconf_defaults_new ();
+
+        if (mechanism == NULL) {
+                goto out;
+        }
+
+        if (!acquire_name_on_proxy (bus_proxy)) {
+                g_warning ("Could not acquire name; bailing out");
+                goto out;
+        }
+
+        loop = g_main_loop_new (NULL, FALSE);
+
+        g_main_loop_run (loop);
+
+        g_object_unref (mechanism);
+        g_main_loop_unref (loop);
+        ret = 0;
+
+out:
+        return ret;
+}
diff -u -r GConf-2.22.0/defaults/gconf-defaults.xml hacked/defaults/gconf-defaults.xml
--- GConf-2.22.0/defaults/gconf-defaults.xml	2008-05-02 23:07:19.000000000 -0400
+++ hacked/defaults/gconf-defaults.xml	2008-05-02 22:45:08.000000000 -0400
@@ -0,0 +1,61 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/">
+  <interface name="org.gnome.GConf.Defaults">
+    <!--
+      includes: an array of GConf paths to copy from the 
+                callers GConf database to the system database
+      excludes: an array of GConf paths to omit
+
+      Copies values from the callers GConf database to the system-wide 
+      database. The subtree below each included path is copied recursively, 
+      skipping the excluded subtrees.
+      To decide which PolicyKit privilege to require for the copying of
+      each path in includes, the mechanism looks for a privilege with an
+      annotation with key org.gnome.gconf.defaults.set-system.prefix whose
+      value is a prefix of the path. If no privilege is found this way, the
+      org.gnome.gconf.defaults.set-system privilege is required.
+    -->
+    <method name="SetSystem">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg name="includes" direction="in" type="as"/>
+      <arg name="excludes" direction="in" type="as"/>
+    </method>
+
+    <!--
+      includes: an array of GConf paths to copy from the 
+                callers GConf database to the mandatory database
+      excludes: an array of GConf paths to omit
+
+      Copies values from the callers GConf database to the system-wide 
+      mandatory database. The subtree below each included path is copied 
+      recursively, skipping the excluded subtrees.
+      To decide which PolicyKit privilege to require for the copying of
+      each path in includes, the mechanism looks for a privilege with an
+      annotation with key org.gnome.gconf.defaults.set-mandatory.prefix whose
+      value is a prefix of the path. If no privilege is found this way, the
+      org.gnome.gconf.defaults.set-mandatory privilege is required.
+    -->
+    <method name="SetMandatory">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg name="includes" direction="in" type="as"/>
+      <arg name="excludes" direction="in" type="as"/>
+    </method>
+
+    <!--
+      Unsets keys in the system-wide mandatory GConf database, making the
+      keys writable again. The subtree below each included path is copied 
+      recursively, skipping the excluded subtrees.
+      To decide which PolicyKit privilege to require for the copying of
+      each path in includes, the mechanism looks for a privilege with an
+      annotation with key org.gnome.gconf.defaults.set-mandatory.prefix whose
+      value is a prefix of the path. If no privilege is found this way, the
+      org.gnome.gconf.defaults.set-mandatory privilege is required.
+    -->
+    <method name="UnsetMandatory">
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg name="includes" direction="in" type="as"/>
+      <arg name="excludes" direction="in" type="as"/>
+    </method>
+   
+  </interface>
+</node>
diff -u -r GConf-2.22.0/defaults/Makefile.am hacked/defaults/Makefile.am
--- GConf-2.22.0/defaults/Makefile.am	2008-05-02 23:07:19.000000000 -0400
+++ hacked/defaults/Makefile.am	2008-04-30 23:35:38.000000000 -0400
@@ -0,0 +1,51 @@
+libexec_PROGRAMS = gconf-defaults-mechanism
+
+gconf-defaults-glue.h: $(srcdir)/gconf-defaults.xml
+	dbus-binding-tool --prefix=gconf_defaults --mode=glib-server      \
+			  --output=gconf-defaults-glue.h                  \
+			  $(srcdir)/gconf-defaults.xml
+
+
+gconf_defaults_mechanism_SOURCES = \
+	gconf-defaults.h \
+	gconf-defaults.c \
+	gconf-defaults-glue.h \
+	gconf-defaults-main.c
+
+INCLUDES = $(DEFAULTS_CFLAGS)
+
+gconf_defaults_mechanism_LDADD = $(DEFAULTS_LIBS) 
+
+BUILT_SOURCES = gconf-defaults-glue.h
+
+dbus_servicesdir = $(datadir)/dbus-1/system-services
+dbus_confdir = $(sysconfdir)/dbus-1/system.d
+polkitdir = $(datadir)/PolicyKit/policy
+
+dbus_services_in_files = org.gnome.GConf.Defaults.service.in
+polkit_in_files = org.gnome.gconf.defaults.policy.in
+
+dbus_services_DATA = $(dbus_services_in_files:.service.in=.service)
+
+$(dbus_services_DATA): $(dbus_services_in_files)
+	sed -e "s|\@LIBEXECDIR\@|$(libexecdir)|" $< > $@
+
+dbus_conf_DATA = org.gnome.GConf.Defaults.conf
+
+ at INTLTOOL_POLICY_RULE@
+polkit_DATA = $(polkit_in_files:.policy.in=.policy)
+
+check:
+	$(POLKIT_POLICY_FILE_VALIDATE) $(polkit_DATA)
+
+EXTRA_DIST =					\
+	$(dbus_services_in_files)		\
+	org.gnome.GConf.Defaults.conf		\
+	$(polkit_in_files)			\
+	gconf-defaults.xml
+
+CLEANFILES =			\
+	$(BUILT_SOURCES)	\
+	$(polkit_DATA)		\
+	$(dbus_services_DATA)
+
diff -u -r GConf-2.22.0/defaults/org.gnome.GConf.Defaults.conf hacked/defaults/org.gnome.GConf.Defaults.conf
--- GConf-2.22.0/defaults/org.gnome.GConf.Defaults.conf	2008-05-02 23:07:19.000000000 -0400
+++ hacked/defaults/org.gnome.GConf.Defaults.conf	2008-05-02 14:09:10.000000000 -0400
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
+
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+
+  <!-- Only root can own the service -->
+  <policy user="root">
+    <allow own="org.gnome.GConf.Defaults"/>
+    <allow send_interface="org.gnome.GConf.Defaults.SetSystem"/>
+    <allow send_interface="org.gnome.GConf.Defaults.SetMandatory"/>
+    <allow send_interface="org.gnome.GConf.Defaults.UnsetMandatory"/>
+  </policy>
+
+  <!-- Allow anyone to invoke methods on the interfaces -->
+  <policy context="default">
+    <allow send_interface="org.gnome.GConf.Defaults.SetSystem"/>
+    <allow send_interface="org.gnome.GConf.Defaults.SetMandatory"/>
+    <allow send_interface="org.gnome.GConf.Defaults.UnsetMandatory"/>
+  </policy>
+
+</busconfig>
diff -u -r GConf-2.22.0/defaults/org.gnome.gconf.defaults.policy.in hacked/defaults/org.gnome.gconf.defaults.policy.in
--- GConf-2.22.0/defaults/org.gnome.gconf.defaults.policy.in	2008-05-02 23:07:19.000000000 -0400
+++ hacked/defaults/org.gnome.gconf.defaults.policy.in	2008-05-02 14:09:28.000000000 -0400
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+<policyconfig>
+  <vendor>The GNOME Project</vendor>
+  <vendor_url>http://www.gnome.org/projects/gconf/</vendor_url>
+  <icon_name>gconf-editor</icon_name>
+
+  <action id="org.gnome.gconf.defaults.set-system">
+    <description>Change GConf system values</description>
+    <message>Privileges are required to change GConf system values</message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_admin</allow_active>
+    </defaults>
+  </action>
+
+  <action id="org.gnome.gconf.defaults.set-mandatory">
+    <description>Change GConf mandatory values</description>
+    <message>Privileges are required to change GConf mandatory values</message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_admin</allow_active>
+    </defaults>
+  </action>
+
+</policyconfig>
diff -u -r GConf-2.22.0/defaults/org.gnome.GConf.Defaults.service.in hacked/defaults/org.gnome.GConf.Defaults.service.in
--- GConf-2.22.0/defaults/org.gnome.GConf.Defaults.service.in	2008-05-02 23:07:19.000000000 -0400
+++ hacked/defaults/org.gnome.GConf.Defaults.service.in	2008-05-01 14:39:59.000000000 -0400
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=org.gnome.GConf.Defaults
+Exec=@LIBEXECDIR@/gconf-defaults-mechanism
+User=root
diff -u -r GConf-2.22.0/Makefile.am hacked/Makefile.am
--- GConf-2.22.0/Makefile.am	2007-06-25 07:11:31.000000000 -0400
+++ hacked/Makefile.am	2008-04-30 23:32:45.000000000 -0400
@@ -1,5 +1,5 @@
 
-SUBDIRS = gconf backends po doc examples
+SUBDIRS = gconf backends po doc examples defaults
 DIST_SUBDIRS=tests $(SUBDIRS)
 
 EXTRA_DIST =                \
diff -u -r GConf-2.22.0/po/POTFILES.in hacked/po/POTFILES.in
--- GConf-2.22.0/po/POTFILES.in	2007-06-25 07:11:31.000000000 -0400
+++ hacked/po/POTFILES.in	2008-05-01 22:14:31.000000000 -0400
@@ -9,6 +9,7 @@
 backends/xml-cache.c
 backends/xml-dir.c
 backends/xml-entry.c
+defaults/org.gnome.gconf.defaults.policy.in
 gconf/gconf-backend.c
 gconf/gconf-client.c
 gconf/gconf-database.c


Index: GConf2.spec
===================================================================
RCS file: /cvs/extras/rpms/GConf2/devel/GConf2.spec,v
retrieving revision 1.78
retrieving revision 1.79
diff -u -r1.78 -r1.79
--- GConf2.spec	2 May 2008 14:39:44 -0000	1.78
+++ GConf2.spec	3 May 2008 03:23:20 -0000	1.79
@@ -5,7 +5,7 @@
 Summary: A process-transparent configuration system
 Name: GConf2
 Version: 2.22.0
-Release: 2%{?dist}
+Release: 3%{?dist}
 License: LGPLv2+
 Group: System Environment/Base
 Source: http://download.gnome.org/sources/GConf/2.22/GConf-%{version}.tar.bz2
@@ -23,6 +23,9 @@
 BuildRequires: perl(XML::Parser)
 BuildRequires: libtool, autoconf, automake
 BuildRequires: intltool
+# for patch3
+BuildRequires: PolicyKit-devel >= 0.8
+Requires: dbus
 # for patch0
 Requires: /usr/bin/killall
 
@@ -31,6 +34,8 @@
 Patch1: GConf2-2.14.0-timeout.patch
 # http://bugzilla.gnome.org/show_bug.cgi?id=531063
 Patch2: gconf-timeouts.patch
+# http://bugzilla.gnome.org/show_bug.cgi?id=531169
+Patch3: gconf-defaults.patch
 
 %description
 GConf is a process-transparent configuration database API used to 
@@ -68,6 +73,7 @@
 %patch0 -p1 -b .reload
 %patch1 -p1 -b .timers  
 %patch2 -p1 -b .timeouts
+%patch3 -p1 -b .defaults
 
 %build
 rm -f libtool
@@ -122,6 +128,10 @@
 %{_mandir}/man1/*
 %dir %{_libdir}/GConf
 %dir %{_libdir}/GConf/2
+%{_sysconfdir}/dbus-1/system.d/org.gnome.GConf.Defaults.conf
+%{_libexecdir}/gconf-defaults-mechanism
+%{_datadir}/PolicyKit/policy/org.gnome.gconf.defaults.policy
+%{_datadir}/dbus-1/system-services/org.gnome.GConf.Defaults.service
 
 %files gtk
 %{_libexecdir}/gconf-sanity-check-2
@@ -135,6 +145,9 @@
 %{_libdir}/pkgconfig/*
 
 %changelog
+* Fri May 2 2008 Matthias Clasen <mclasen at redhat.com> - 2.22.0-3
+- Add a dbus service to set defaults
+
 * Fri May 2 2008 Matthias Clasen <mclasen at redhat.com> - 2.22.0-2
 - Use g_timeout_add_seconds for long timeouts
 




More information about the fedora-extras-commits mailing list