summaryrefslogtreecommitdiff
path: root/defaults/gconf-defaults.c
diff options
context:
space:
mode:
Diffstat (limited to 'defaults/gconf-defaults.c')
-rw-r--r--defaults/gconf-defaults.c1119
1 files changed, 722 insertions, 397 deletions
diff --git a/defaults/gconf-defaults.c b/defaults/gconf-defaults.c
index e477435c..11a38ad4 100644
--- a/defaults/gconf-defaults.c
+++ b/defaults/gconf-defaults.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
- * Copyright (C) 2008 Matthias Clasen <mclasen@redhat.com>
+ * Copyright (C) 2008, 2009 Matthias Clasen <mclasen@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
@@ -37,7 +37,6 @@
#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
@@ -50,34 +49,61 @@
static gboolean
do_exit (gpointer user_data)
{
- g_debug ("Exiting due to inactivity");
- exit (1);
- return FALSE;
+ g_debug ("Exiting due to inactivity");
+ exit (1);
+ return FALSE;
}
static guint timer_id = 0;
+gboolean disable_killtimer = FALSE;
static void
stop_killtimer (void)
{
- if (timer_id > 0) {
- g_source_remove (timer_id);
+ if (disable_killtimer)
+ return;
+
+ 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);
+ if (disable_killtimer)
+ return;
+
+ if (timer_id == 0) {
+ g_debug ("Setting killtimer to 30 seconds...");
+ timer_id = g_timeout_add_seconds (30, do_exit, NULL);
+ }
+}
+
+static gint operations = 0;
+
+static void
+start_operation (void)
+{
+ if (operations == 0)
+ stop_killtimer ();
+ operations++;
+}
+
+static void
+stop_operation (void)
+{
+ if (operations == 1)
+ start_killtimer ();
+ operations --;
}
struct GConfDefaultsPrivate
{
- DBusGConnection *system_bus_connection;
- DBusGProxy *system_bus_proxy;
- PolKitContext *pol_ctx;
+ DBusGConnection *system_bus_connection;
+ DBusGProxy *system_bus_proxy;
+ PolkitAuthority *auth;
};
static void gconf_defaults_finalize (GObject *object);
@@ -89,13 +115,13 @@ G_DEFINE_TYPE (GConfDefaults, gconf_defaults, G_TYPE_OBJECT)
GQuark
gconf_defaults_error_quark (void)
{
- static GQuark ret = 0;
+ static GQuark ret = 0;
- if (ret == 0) {
- ret = g_quark_from_static_string ("gconf_defaults_error");
- }
+ if (ret == 0) {
+ ret = g_quark_from_static_string ("gconf_defaults_error");
+ }
- return ret;
+ return ret;
}
@@ -104,21 +130,23 @@ gconf_defaults_error_quark (void)
GType
gconf_defaults_error_get_type (void)
{
- static GType etype = 0;
+ 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 }
- };
+ 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);
+ g_assert (GCONF_DEFAULTS_NUM_ERRORS == G_N_ELEMENTS (values) - 1);
- etype = g_enum_register_static ("GConfDefaultsError", values);
- }
+ etype = g_enum_register_static ("GConfDefaultsError", values);
+ }
- return etype;
+ return etype;
}
@@ -127,17 +155,17 @@ gconf_defaults_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
- GConfDefaults *mechanism;
- GConfDefaultsClass *klass;
+ GConfDefaults *mechanism;
+ GConfDefaultsClass *klass;
- klass = GCONF_DEFAULTS_CLASS (g_type_class_peek (GCONF_TYPE_DEFAULTS));
+ 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));
+ mechanism = GCONF_DEFAULTS (G_OBJECT_CLASS (gconf_defaults_parent_class)->constructor (
+ type,
+ n_construct_properties,
+ construct_properties));
- return G_OBJECT (mechanism);
+ return G_OBJECT (mechanism);
}
enum {
@@ -150,10 +178,10 @@ static guint signals[LAST_SIGNAL] = { 0 };
static void
gconf_defaults_class_init (GConfDefaultsClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
- object_class->constructor = gconf_defaults_constructor;
- object_class->finalize = gconf_defaults_finalize;
+ object_class->constructor = gconf_defaults_constructor;
+ object_class->finalize = gconf_defaults_finalize;
signals[SYSTEM_SET] = g_signal_new ("system-set",
G_OBJECT_CLASS_TYPE (object_class),
@@ -162,149 +190,114 @@ gconf_defaults_class_init (GConfDefaultsClass *klass)
NULL, NULL,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE, 1, G_TYPE_STRV);
+
+ g_type_class_add_private (klass, sizeof (GConfDefaultsPrivate));
- 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_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);
- 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);
+ mechanism->priv = GCONF_DEFAULTS_GET_PRIVATE (mechanism);
}
static void
gconf_defaults_finalize (GObject *object)
{
- GConfDefaults *mechanism;
+ GConfDefaults *mechanism;
- g_return_if_fail (object != NULL);
- g_return_if_fail (GCONF_IS_DEFAULTS (object));
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GCONF_IS_DEFAULTS (object));
- mechanism = GCONF_DEFAULTS (object);
+ mechanism = GCONF_DEFAULTS (object);
- g_return_if_fail (mechanism->priv != NULL);
+ g_return_if_fail (mechanism->priv != NULL);
- g_object_unref (mechanism->priv->system_bus_proxy);
+ g_object_unref (mechanism->priv->auth);
+ 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);
+ G_OBJECT_CLASS (gconf_defaults_parent_class)->finalize (object);
}
static gboolean
register_mechanism (GConfDefaults *mechanism)
{
- GError *error = NULL;
+ 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;
- }
+ mechanism->priv->auth = polkit_authority_get ();
- 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;
- }
+ 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));
+ 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);
+ 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 ();
+ start_killtimer ();
- return TRUE;
+ return TRUE;
error:
- return FALSE;
+ return FALSE;
}
GConfDefaults *
gconf_defaults_new (void)
{
- GObject *object;
- gboolean res;
+ GObject *object;
+ gboolean res;
- object = g_object_new (GCONF_TYPE_DEFAULTS, NULL);
+ object = g_object_new (GCONF_TYPE_DEFAULTS, NULL);
- res = register_mechanism (GCONF_DEFAULTS (object));
- if (! res) {
- g_object_unref (object);
- return NULL;
- }
+ res = register_mechanism (GCONF_DEFAULTS (object));
+ if (! res) {
+ g_object_unref (object);
+ return NULL;
+ }
- return GCONF_DEFAULTS (object);
+ return GCONF_DEFAULTS (object);
}
static const char *
polkit_action_for_gconf_path (GConfDefaults *mechanism,
+ GList *action_descriptions,
const char *annotation_key,
const char *path)
{
- PolKitPolicyCache *cache;
- PolKitPolicyFileEntry *entry;
char *prefix, *p;
const char *action;
+ GList *l;
+ PolkitActionDescription *action_description;
+ const gchar *annotation;
- 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;
+ for (l = action_descriptions; l; l = l->next) {
+ action_description = l->data;
+
+ annotation = polkit_action_description_get_annotation (action_description, annotation_key);
+ if (g_strcmp0 (prefix, annotation) == 0) {
+ action = polkit_action_description_get_action_id (action_description);
+ g_debug ("action for path '%s': '%s'\n", action, path);
+ break;
+ }
}
p = strrchr (prefix, '/');
@@ -322,56 +315,160 @@ polkit_action_for_gconf_path (GConfDefaults *mechanism,
return action;
}
-static gboolean
-check_polkit_for_action (GConfDefaults *mechanism,
- DBusGMethodInvocation *context,
- const char *action)
+static void
+throw_error (DBusGMethodInvocation *context,
+ gint error_code,
+ const gchar *format,
+ ...)
{
- const char *sender;
GError *error;
- DBusError dbus_error;
- PolKitCaller *pk_caller;
- PolKitAction *pk_action;
- PolKitResult pk_result;
+ va_list args;
+ gchar *message;
+
+ va_start (args, format);
+ message = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ error = g_error_new (GCONF_DEFAULTS_ERROR,
+ error_code,
+ "%s", message);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ g_free (message);
+}
- error = NULL;
+typedef void (*AuthObtainedCallback) (GConfDefaults *mechanism,
+ DBusGMethodInvocation *context,
+ gpointer user_data);
+
+typedef struct
+{
+ GConfDefaults *mechanism;
+ DBusGMethodInvocation *context;
+ gchar **actions;
+ gint id;
+ gint flags;
+ AuthObtainedCallback auth_obtained_callback;
+ GAsyncReadyCallback check_auth_callback;
+ gpointer user_data;
+ GDestroyNotify destroy;
+ PolkitSubject *subject;
+ gboolean challenge;
+} CheckAuthData;
+
+static void
+check_auth_data_free (CheckAuthData *data)
+{
+ g_object_unref (data->mechanism);
+ g_strfreev (data->actions);
+ if (data->destroy)
+ data->destroy (data->user_data);
+ g_object_unref (data->subject);
+ g_free (data);
+}
+
+static void check_next_action (CheckAuthData *data);
+
+static void
+check_authorization_callback (PolkitAuthority *authority,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CheckAuthData *data = user_data;
+ PolkitAuthorizationResult *result;
+ GError *error;
+ gboolean is_authorized;
+
+ is_authorized = FALSE;
- /* 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);
+ error = NULL;
+ result = polkit_authority_check_authorization_finish (authority,
+ res,
+ &error);
+ if (error != NULL) {
+ g_debug ("error checking action '%s'\n", error->message);
+ throw_error (data->context,
+ GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED,
+ "Not Authorized: %s", error->message);
g_error_free (error);
- return FALSE;
+ }
+ else {
+ if (polkit_authorization_result_get_is_authorized (result)) {
+ g_debug ("result for '%s': authorized\n",
+ data->actions[data->id]);
+ is_authorized = TRUE;
+ }
+ else if (polkit_authorization_result_get_is_challenge (result)) {
+ g_debug ("result for '%s': challenge\n",
+ data->actions[data->id]);
+ throw_error (data->context,
+ GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED,
+ "Authorization is required");
+ }
+ else {
+ g_debug ("result for '%s': not authorized\n",
+ data->actions[data->id]);
+ throw_error (data->context,
+ GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED,
+ "Not Authorized");
+ }
}
- 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;
+ if (is_authorized) {
+ data->id++;
+ if (data->actions[data->id] == NULL)
+ data->auth_obtained_callback (data->mechanism,
+ data->context,
+ data->user_data);
+ else {
+ check_next_action (data);
+ return; /* continue operation */
+ }
}
- polkit_action_unref (pk_action);
- return TRUE;
+ check_auth_data_free (data);
+ g_object_unref (result);
+ stop_operation ();
+}
+
+static void
+check_next_action (CheckAuthData *data)
+{
+ g_debug ("checking action '%s'\n", data->actions[data->id]);
+ polkit_authority_check_authorization (data->mechanism->priv->auth,
+ data->subject,
+ data->actions[data->id],
+ NULL,
+ data->flags,
+ NULL,
+ data->check_auth_callback,
+ data);
+}
+
+static void
+check_polkit_for_actions (GConfDefaults *mechanism,
+ DBusGMethodInvocation *context,
+ gchar **actions,
+ AuthObtainedCallback auth_obtained_callback,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+ CheckAuthData *data;
+
+ data = g_new0 (CheckAuthData, 1);
+ data->mechanism = g_object_ref (mechanism);
+ data->context = context;
+ data->actions = actions;
+ data->flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION;
+ data->id = 0;
+ data->auth_obtained_callback = auth_obtained_callback;
+ data->check_auth_callback = (GAsyncReadyCallback)check_authorization_callback;
+ data->user_data = user_data;
+ data->destroy = destroy;
+ data->subject = polkit_system_bus_name_new (dbus_g_method_get_sender (context));
+ data->challenge = FALSE;
+
+ check_next_action (data);
}
static char *
@@ -379,7 +476,7 @@ gconf_address_for_caller (GConfDefaults *mechanism,
DBusGMethodInvocation *context,
GError **gerror)
{
- char *sender;
+ char *sender;
DBusConnection *conn;
uid_t uid;
struct passwd *pwd;
@@ -387,7 +484,7 @@ gconf_address_for_caller (GConfDefaults *mechanism,
DBusError error;
conn = dbus_g_connection_get_connection (mechanism->priv->system_bus_connection);
- sender = dbus_g_method_get_sender (context);
+ sender = dbus_g_method_get_sender (context);
dbus_error_init (&error);
uid = dbus_bus_get_unix_user (conn, sender, &error);
@@ -470,56 +567,56 @@ copy_entry (GConfClient *src,
}
}
+typedef void (*ChangeSetCallback) (GConfDefaults *mechanism,
+ GConfChangeSet *changes,
+ gpointer data);
+
+typedef struct
+{
+ GConfDefaults *mechanism;
+ DBusGMethodInvocation *context;
+ const char *dest_address;
+ char **actions;
+ char **includes;
+ char **excludes;
+ GConfValue *value;
+ ChangeSetCallback changeset_callback;
+ gpointer user_data;
+ GDestroyNotify destroy;
+} CopyData;
static void
-do_copy (GConfDefaults *mechanism,
- gboolean mandatory,
- const char **includes,
- const char **excludes,
- DBusGMethodInvocation *context,
- GConfChangeSet **changeset_out)
+copy_data_free (gpointer user_data)
{
- char *address = NULL;
+ CopyData *data = user_data;
+
+ g_object_unref (data->mechanism);
+ g_strfreev (data->includes);
+ g_strfreev (data->excludes);
+ g_strfreev (data->actions);
+ if (data->value)
+ gconf_value_free (data->value);
+ if (data->destroy)
+ data->destroy (data->user_data);
+ g_free (data);
+}
+
+static void
+do_copy_authorized (GConfDefaults *mechanism,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ CopyData *data = user_data;
GConfClient *source = NULL;
GConfClient *dest = NULL;
GConfChangeSet *changes = NULL;
GConfEngine *engine;
+ char *address = NULL;
+ gint i;
GError *error;
- GError *error2;
- const char *action;
- const char *annotation_key;
- const char *default_action;
- const char *dest_address;
- int i;
-
- if (changeset_out)
- *changeset_out = NULL;
-
- 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:" SYSGCONFDIR "/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:" SYSGCONFDIR "/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);
+ engine = gconf_engine_get_local (data->dest_address, &error);
if (error)
goto cleanup;
@@ -527,7 +624,7 @@ do_copy (GConfDefaults *mechanism,
gconf_engine_unref (engine);
/* find the address to from the caller id */
- address = gconf_address_for_caller (mechanism, context, &error);
+ address = gconf_address_for_caller (data->mechanism, data->context, &error);
if (error)
goto cleanup;
@@ -540,20 +637,27 @@ do_copy (GConfDefaults *mechanism,
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);
+ if (data->value) {
+ g_assert (data->includes[1] == NULL);
+ g_assert (data->excludes == NULL);
+
+ gconf_change_set_set (changes, data->includes[0], data->value);
+ }
+ else {
+ /* recursively copy each include, leaving out the excludes */
+ for (i = 0; data->includes[i]; i++) {
+ if (gconf_client_dir_exists (source, data->includes[i], NULL))
+ copy_tree (source, data->includes[i], changes, (const char **)data->excludes);
+ else
+ copy_entry (source, data->includes[i], changes, (const char **)data->excludes);
+ }
}
gconf_client_commit_change_set (dest, changes, FALSE, &error);
gconf_client_suggest_sync (dest, NULL);
- if (changeset_out) {
- *changeset_out = changes;
- changes = NULL;
+ if (data->changeset_callback) {
+ data->changeset_callback (data->mechanism, changes, data->user_data);
}
cleanup:
@@ -566,20 +670,153 @@ cleanup:
g_object_unref (source);
if (error) {
- g_print ("failed to set GConf values: %s\n", error->message);
- error2 = g_error_new_literal (GCONF_DEFAULTS_ERROR,
- GCONF_DEFAULTS_ERROR_GENERAL,
- error->message);
+ throw_error (data->context,
+ GCONF_DEFAULTS_ERROR_GENERAL,
+ "%s", error->message);
g_error_free (error);
-
- dbus_g_method_return_error (context, error2);
- g_error_free (error2);
}
else
- dbus_g_method_return (context);
+ dbus_g_method_return (data->context);
+}
-out:
- start_killtimer ();
+typedef void (*ActionsReadyCallback) (GConfDefaults *mechanism,
+ DBusGMethodInvocation *context,
+ gchar **actions,
+ AuthObtainedCallback auth_obtained_callback,
+ gpointer data,
+ GDestroyNotify destroy);
+
+typedef struct
+{
+ GConfDefaults *mechanism;
+ DBusGMethodInvocation *context;
+ char **includes;
+ const char *default_action;
+ const char *annotation_key;
+ ActionsReadyCallback actions_ready_callback;
+ AuthObtainedCallback auth_obtained_callback;
+ gpointer data;
+ GDestroyNotify destroy;
+} ActionData;
+
+static void
+action_data_free (ActionData *data)
+{
+ g_object_unref (data->mechanism);
+ g_strfreev (data->includes);
+ if (data->destroy)
+ data->destroy (data->data);
+ g_free (data);
+}
+
+static void
+actions_ready_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ ActionData *data = user_data;
+ GList *action_descriptions;
+ GError *error = NULL;
+ int i;
+ GHashTable *obtained;
+ GHashTableIter iter;
+ const gchar *action;
+ gchar **actions;
+ gpointer key, value;
+
+ action_descriptions = polkit_authority_enumerate_actions_finish (data->mechanism->priv->auth, res, &error);
+
+ if (error) {
+ throw_error (data->context,
+ GCONF_DEFAULTS_ERROR_GENERAL,
+ "Failed to get action descriptions: %s", error->message);
+ g_error_free (error);
+ action_data_free (data);
+ stop_operation ();
+ return;
+ }
+
+ obtained = g_hash_table_new (g_str_hash, g_str_equal);
+
+ for (i = 0; data->includes[i]; i++) {
+ action = polkit_action_for_gconf_path (data->mechanism, action_descriptions, data->annotation_key, data->includes[i]);
+ if (action == NULL) {
+ g_debug ("using default action '%s' for path '%s'",
+ data->default_action, data->includes[i]);
+ action = data->default_action;
+ }
+
+ g_hash_table_insert (obtained, (gpointer)action, (gpointer)action);
+ }
+ actions = g_new0 (char *, g_hash_table_size (obtained) + 1);
+ g_hash_table_iter_init (&iter, obtained);
+ i = 0;
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ actions[i] = g_strdup ((char *)key);
+ i++;
+ }
+ g_hash_table_destroy (obtained);
+ g_list_foreach (action_descriptions, (GFunc)g_object_unref, NULL);
+ g_list_free (action_descriptions);
+
+ data->actions_ready_callback (data->mechanism, data->context, actions, data->auth_obtained_callback, data->data, data->destroy);
+
+ data->destroy = NULL;
+ action_data_free (data);
+}
+
+static void
+do_copy (GConfDefaults *mechanism,
+ gboolean mandatory,
+ const gchar **includes,
+ const gchar **excludes,
+ GConfValue *value,
+ DBusGMethodInvocation *context,
+ ChangeSetCallback changeset_callback,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+ CopyData *cdata;
+ ActionData *adata;
+
+ start_operation ();
+
+ cdata = g_new0 (CopyData, 1);
+ cdata->mechanism = g_object_ref (mechanism);
+ cdata->context = context;
+ cdata->includes = g_strdupv ((gchar **)includes);
+ cdata->excludes = g_strdupv ((gchar **)excludes);
+ cdata->value = value;
+ cdata->actions = NULL;
+ cdata->changeset_callback = changeset_callback;
+ cdata->user_data = user_data;
+ cdata->destroy = destroy;
+
+ adata = g_new0 (ActionData, 1);
+ adata->mechanism = g_object_ref (mechanism);
+ adata->context = context;
+ adata->includes = g_strdupv ((gchar **)includes);
+ adata->actions_ready_callback = check_polkit_for_actions;
+ adata->auth_obtained_callback = do_copy_authorized;
+ adata->data = cdata;
+ adata->destroy = copy_data_free;
+
+ /* check privileges for each include */
+ if (mandatory) {
+ adata->annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix";
+ adata->default_action = "org.gnome.gconf.defaults.set-mandatory";
+ cdata->dest_address = "xml:merged:" SYSGCONFDIR "/gconf.xml.mandatory";
+ }
+ else {
+ adata->annotation_key = "org.gnome.gconf.defaults.set-system.prefix";
+ adata->default_action = "org.gnome.gconf.defaults.set-system";
+ cdata->dest_address = "xml:merged:" SYSGCONFDIR "/gconf.xml.system";
+ }
+
+ polkit_authority_enumerate_actions (mechanism->priv->auth,
+ NULL,
+ actions_ready_cb,
+ adata);
}
static void
@@ -594,14 +831,12 @@ append_key (GConfChangeSet *cs,
}
static void
-emit_system_set_signal (GConfDefaults *mechanism,
- GConfChangeSet *changes)
+set_system_changes (GConfDefaults *mechanism,
+ GConfChangeSet *changes,
+ gpointer data)
{
GPtrArray *keys;
- if (!changes)
- return;
-
keys = g_ptr_array_new ();
gconf_change_set_foreach (changes, append_key, keys);
g_ptr_array_add (keys, NULL);
@@ -617,12 +852,7 @@ gconf_defaults_set_system (GConfDefaults *mechanism,
const char **excludes,
DBusGMethodInvocation *context)
{
- GConfChangeSet *changes = NULL;
-
- do_copy (mechanism, FALSE, includes, excludes, context, &changes);
-
- emit_system_set_signal (mechanism, changes);
- gconf_change_set_unref (changes);
+ do_copy (mechanism, FALSE, includes, excludes, NULL, context, set_system_changes, NULL, NULL);
}
void
@@ -631,120 +861,7 @@ gconf_defaults_set_mandatory (GConfDefaults *mechanism,
const char **excludes,
DBusGMethodInvocation *context)
{
- do_copy (mechanism, FALSE, includes, excludes, context, NULL);
-}
-
-static void
-do_set_value (GConfDefaults *mechanism,
- gboolean mandatory,
- const char *path,
- const char *value,
- DBusGMethodInvocation *context,
- GConfChangeSet **changeset_out)
-{
- GConfClient *dest = NULL;
- GConfChangeSet *changes = NULL;
- GConfEngine *engine;
- GConfValue *gvalue;
- GError *error;
- GError *error2;
- const char *action;
- const char *annotation_key;
- const char *default_action;
- const char *dest_address;
-
- if (changeset_out)
- *changeset_out = NULL;
-
- stop_killtimer ();
-
- 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";
- }
-
- action = polkit_action_for_gconf_path (mechanism, annotation_key, path);
- 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);
-
- changes = gconf_change_set_new ();
-
- gvalue = gconf_value_decode (value);
- if (!gvalue)
- goto cleanup;
-
- gconf_change_set_set (changes, path, gvalue);
- gconf_value_free (gvalue);
-
- gconf_client_commit_change_set (dest, changes, FALSE, &error);
- gconf_client_suggest_sync (dest, NULL);
-
- if (changeset_out) {
- *changeset_out = changes;
- changes = NULL;
- }
-
-cleanup:
- if (changes)
- gconf_change_set_unref (changes);
- if (dest)
- g_object_unref (dest);
-
- if (error) {
- g_print ("failed to set GConf values: %s\n", error->message);
- error2 = g_error_new_literal (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_value (GConfDefaults *mechanism,
- const char *path,
- const char *value,
- DBusGMethodInvocation *context)
-{
- GConfChangeSet *changes = NULL;
-
- do_set_value (mechanism, FALSE, path, value, context, &changes);
-
- emit_system_set_signal (mechanism, changes);
- gconf_change_set_unref (changes);
-}
-
-void
-gconf_defaults_set_mandatory_value (GConfDefaults *mechanism,
- const char *path,
- const char *value,
- DBusGMethodInvocation *context)
-{
- do_set_value (mechanism, TRUE, path, value, context, NULL);
+ do_copy (mechanism, TRUE, includes, excludes, NULL, context, NULL, NULL, NULL);
}
static void
@@ -756,13 +873,13 @@ unset_tree (GConfClient *dest,
GSList *list, *l;
GConfEntry *entry;
- if (path_is_excluded (path, excludes))
+ 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))
+ if (!path_is_excluded (entry->key, excludes))
gconf_change_set_unset (changes, entry->key);
}
g_slist_foreach (list, (GFunc)gconf_entry_free, NULL);
@@ -774,25 +891,25 @@ unset_tree (GConfClient *dest,
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))
+ 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)
+unset_in_db (GConfDefaults *mechanism,
+ const gchar *address,
+ const gchar **includes,
+ const gchar **excludes,
+ GError **error)
{
GConfEngine *engine;
GConfClient *dest = NULL;
@@ -800,7 +917,7 @@ unset_in_db (GConfDefaults *mechanism,
int i;
engine = gconf_engine_get_local (address, error);
- if (*error)
+ if (*error)
goto out;
dest = gconf_client_get_for_engine (engine);
@@ -826,48 +943,256 @@ out:
gconf_change_set_unref (changes);
}
+typedef struct
+{
+ GConfDefaults *mechanism;
+ DBusGMethodInvocation *context;
+ char **includes;
+ char **excludes;
+} UnsetData;
+
+static void
+unset_data_free (gpointer user_data)
+{
+ UnsetData *data = user_data;
+
+ g_object_unref (data->mechanism);
+ g_strfreev (data->includes);
+ g_strfreev (data->excludes);
+ g_free (data);
+}
+
+static void
+do_unset_authorized (GConfDefaults *mechanism,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ UnsetData *data = user_data;
+ GError *error;
+
+ error = NULL;
+ unset_in_db (mechanism, "xml:merged:" SYSGCONFDIR "/gconf.xml.mandatory",
+ (const gchar **)data->includes,
+ (const gchar **)data->excludes, &error);
+
+ if (error) {
+ throw_error (data->context,
+ GCONF_DEFAULTS_ERROR,
+ GCONF_DEFAULTS_ERROR_GENERAL,
+ "%s", error->message);
+ g_error_free (error);
+ }
+ else
+ dbus_g_method_return (data->context);
+}
+
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;
+ UnsetData *udata;
+ ActionData *adata;
+
+ start_operation ();
+
+ udata = g_new0 (UnsetData, 1);
+ udata->mechanism = g_object_ref (mechanism);
+ udata->context = context;
+ udata->includes = g_strdupv ((gchar **)includes);
+ udata->excludes = g_strdupv ((gchar **)excludes);
+
+ adata = g_new0 (ActionData, 1);
+ adata->mechanism = g_object_ref (mechanism);
+ adata->context = context;
+ adata->includes = g_strdupv ((gchar **)includes);
+ adata->auth_obtained_callback = do_unset_authorized;
+ adata->data = udata;
+ adata->destroy = unset_data_free;
+
+ adata->annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix";
+ adata->default_action = "org.gnome.gconf.defaults.set-mandatory";
+
+ polkit_authority_enumerate_actions (mechanism->priv->auth,
+ NULL,
+ actions_ready_cb,
+ adata);
+}
+
+static void
+check_authorization_only_callback (PolkitAuthority *authority,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CheckAuthData *data = user_data;
+ PolkitAuthorizationResult *result;
GError *error;
- GError *error2;
+ gboolean is_authorized;
- stop_killtimer ();
+ is_authorized = FALSE;
- annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix";
- default_action = "org.gnome.gconf.defaults.set-mandatory";
+ error = NULL;
+ result = polkit_authority_check_authorization_finish (authority,
+ res,
+ &error);
+ if (error != NULL) {
+ g_debug ("error checking action '%s'\n", error->message);
+ throw_error (data->context,
+ GCONF_DEFAULTS_ERROR_NOT_PRIVILEGED,
+ "Not Authorized: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+ else {
+ if (polkit_authorization_result_get_is_authorized (result)) {
+ g_debug ("result for '%s': authorized\n",
+ data->actions[data->id]);
+ is_authorized = TRUE;
+ }
+ else if (polkit_authorization_result_get_is_challenge (result)) {
+ g_debug ("result for '%s': challenge\n",
+ data->actions[data->id]);
+ is_authorized = TRUE;
+ data->challenge = TRUE;
+ }
+ else {
+ g_debug ("result for '%s': not authorized\n",
+ data->actions[data->id]);
+ is_authorized = FALSE;
+ }
+ }
- for (i = 0; includes[i]; i++) {
- action = polkit_action_for_gconf_path (mechanism, annotation_key, includes[i]);
- if (action == NULL)
- action = default_action;
+ if (is_authorized) {
+ data->id++;
+ if (data->actions[data->id] == NULL) {
+ gint result;
- if (!check_polkit_for_action (mechanism, context, action))
- goto out;
+ result = data->challenge ? 1 : 2;
+ g_debug ("return %d\n", result);
+ dbus_g_method_return (data->context, result);
+ }
+ else {
+ check_next_action (data);
+ return; /* continue operation */
+ }
+ }
+ else {
+ g_debug ("return 0\n");
+ dbus_g_method_return (data->context, 0);
}
- error = NULL;
- unset_in_db (mechanism, "xml:merged:" SYSGCONFDIR "/gconf.xml.mandatory",
- includes, excludes, &error);
+out:
+ check_auth_data_free (data);
+ g_object_unref (result);
+ stop_operation ();
+}
- if (error) {
- error2 = g_error_new_literal (GCONF_DEFAULTS_ERROR,
- GCONF_DEFAULTS_ERROR_GENERAL,
- error->message);
- g_error_free (error);
+static void
+check_permissions_only (GConfDefaults *mechanism,
+ DBusGMethodInvocation *context,
+ gchar **actions,
+ AuthObtainedCallback auth_obtained_callback,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+ CheckAuthData *data;
+
+ data = g_new0 (CheckAuthData, 1);
+ data->mechanism = g_object_ref (mechanism);
+ data->context = context;
+ data->actions = actions;
+ data->flags = 0;
+ data->id = 0;
+ data->check_auth_callback = (GAsyncReadyCallback)check_authorization_only_callback;
+ data->auth_obtained_callback = NULL;
+ data->user_data = NULL;
+ data->destroy = NULL;
+ data->subject = polkit_system_bus_name_new (dbus_g_method_get_sender (context));
+ data->challenge = FALSE;
+
+ check_next_action (data);
+}
+
+static void
+do_check (GConfDefaults *mechanism,
+ gboolean mandatory,
+ const gchar **includes,
+ DBusGMethodInvocation *context)
+{
+ ActionData *adata;
+
+ start_operation ();
- dbus_g_method_return_error (context, error2);
- g_error_free (error2);
+ adata = g_new0 (ActionData, 1);
+ adata->mechanism = g_object_ref (mechanism);
+ adata->context = context;
+ adata->includes = g_strdupv ((gchar **)includes);
+ adata->actions_ready_callback = check_permissions_only;
+ adata->auth_obtained_callback = NULL;
+ adata->data = NULL;
+ adata->destroy = NULL;
+
+ if (mandatory) {
+ adata->annotation_key = "org.gnome.gconf.defaults.set-mandatory.prefix";
+ adata->default_action = "org.gnome.gconf.defaults.set-mandatory";
+ }
+ else {
+ adata->annotation_key = "org.gnome.gconf.defaults.set-system.prefix";
+ adata->default_action = "org.gnome.gconf.defaults.set-system";
+ }
+
+ polkit_authority_enumerate_actions (mechanism->priv->auth,
+ NULL,
+ actions_ready_cb,
+ adata);
+}
+
+void
+gconf_defaults_can_set_system (GConfDefaults *mechanism,
+ const char **includes,
+ DBusGMethodInvocation *context)
+{
+ do_check (mechanism, FALSE, includes, context);
+}
+
+void
+gconf_defaults_can_set_mandatory (GConfDefaults *mechanism,
+ const char **includes,
+ DBusGMethodInvocation *context)
+{
+ do_check (mechanism, TRUE, includes, context);
+}
+
+void
+gconf_defaults_set_system_value (GConfDefaults *mechanism,
+ const char *path,
+ const char *value,
+ DBusGMethodInvocation *context)
+{
+ GConfValue *gvalue;
+ const char *includes[] = { NULL, NULL };
+
+ gvalue = gconf_value_decode (value);
+ if (gvalue) {
+ includes[0] = path;
+ do_copy (mechanism, FALSE, includes, NULL, gvalue, context, set_system_changes, NULL, NULL);
+ }
+}
+
+void
+gconf_defaults_set_mandatory_value (GConfDefaults *mechanism,
+ const char *path,
+ const char *value,
+ DBusGMethodInvocation *context)
+{
+ GConfValue *gvalue;
+ const char *includes[] = { NULL, NULL };
+
+ gvalue = gconf_value_decode (value);
+ if (gvalue) {
+ includes[0] = path;
+ do_copy (mechanism, TRUE, includes, NULL, gvalue, context, NULL, NULL, NULL);
}
- else
- dbus_g_method_return (context);
-out:
- start_killtimer();
}
+