diff --git a/library/gsecret-password.c b/library/gsecret-password.c
index d504461..be54069 100644
--- a/library/gsecret-password.c
+++ b/library/gsecret-password.c
@@ -57,82 +57,70 @@ on_sync_result (GObject *source,
g_main_loop_quit (closure->loop);
}
-#if 0
-
typedef struct {
- GVariant *properties;
+ const GSecretSchema *schema;
+ GHashTable *attributes;
gchar *collection_path;
- GSecretValue *secret;
+ gchar *label;
+ GSecretValue *value;
GCancellable *cancellable;
+ gboolean created;
} StoreClosure;
static void
store_closure_free (gpointer data)
{
StoreClosure *closure = data;
- g_variant_unref (closure->properties);
+ g_hash_table_unref (closure->attributes);
g_free (closure->collection_path);
- gsecret_value_unref (closure->secret);
- g_clear_object (closure->cancellable);
- g_free (closure);
+ g_free (closure->label);
+ gsecret_value_unref (closure->value);
+ g_clear_object (&closure->cancellable);
+ g_slice_free (StoreClosure, closure);
}
static void
-on_create_item_reply (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
+on_store_complete (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
{
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ StoreClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
GError *error = NULL;
- retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
- if (error == NULL) {
- g_variant_get (retval, "(&o&o)", &item_path, &prompt_path);
- if (prompt_path xxx)
- gsecret_prompt_perform (self, "", closure->cancellable,
- on_store_prompt_complete, NULL);
-
- if (g_strcmp0 (item_path, "/") != 0)
- xxx complete!
- }
+ closure->created = gsecret_service_store_password_finish (GSECRET_SERVICE (source),
+ result, &error);
+ if (error != NULL)
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete (res);
g_object_unref (res);
}
static void
-on_store_service_connected (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
+on_store_connected (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
{
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
StoreClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
GSecretService *service;
GError *error = NULL;
- GDBusProxy *proxy;
- GVariant *params;
service = _gsecret_service_bare_connect_finish (result, &error);
if (error == NULL) {
- params = g_variant_new ("(&a{sv}&(oayays)b)",
- closure->properties,
- _gsecret_service_encode_secret (service, closure->secret),
- TRUE);
+ gsecret_service_store_passwordv (service, closure->schema,
+ closure->attributes,
+ closure->collection_path,
+ closure->label, closure->value,
+ closure->cancellable,
+ on_store_complete,
+ g_object_ref (res));
+ g_object_unref (service);
- proxy = G_DBUS_PROXY (service);
- g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
- g_dbus_proxy_get_name (proxy),
- closure->collection_path,
- GSECRET_COLLECTION_INTERFACE,
- "CreateItem", params, G_VARIANT_TYPE ("(oo)"),
- G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
- closure->cancellable, on_create_item_reply,
- g_object_ref (res));
} else {
g_simple_async_result_take_error (res, error);
g_simple_async_result_complete (res);
-
-
-
}
g_object_unref (res);
@@ -148,107 +136,332 @@ gsecret_password_store (const GSecretSchema *schema,
gpointer user_data,
...)
{
- GSimpleAsyncResult *res;
- GVariant *attributes;
- StoreClosure *closure;
- GVariantBuilder builder;
+ GHashTable *attributes;
va_list va;
g_return_if_fail (schema != NULL);
+ g_return_if_fail (collection_path != NULL);
g_return_if_fail (label != NULL);
g_return_if_fail (password != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- /* Build up the attributes */
va_start (va, user_data);
- attributes = build_attributes (schema, va);
+ attributes = _gsecret_util_attributes_for_varargs (schema, va);
va_end (va);
- g_return_if_fail (attributes != NULL);
- /* Build up the various properties */
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
- g_variant_builder_add (&builder, "{sv}", GSECRET_SERVICE_INTERFACE "Attributes", attributes);
- g_variant_builder_add (&builder, "{sv}", GSECRET_SERVICE_INTERFACE "Label", g_variant_new_string ("label"));
- g_variant_builder_add (&builder, "{sv}", GSECRET_SERVICE_INTERFACE "Schema", g_variant_new_string (schema->schema_name));
+ gsecret_password_storev (schema, collection_path, label, password, attributes,
+ cancellable, callback, user_data);
+
+ g_hash_table_unref (attributes);
+}
+
+void
+gsecret_password_storev (const GSecretSchema *schema,
+ const gchar *collection_path,
+ const gchar *label,
+ const gchar *password,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+ StoreClosure *closure;
+
+ g_return_if_fail (schema != NULL);
+ g_return_if_fail (collection_path != NULL);
+ g_return_if_fail (label != NULL);
+ g_return_if_fail (password != NULL);
+ g_return_if_fail (attributes != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
res = g_simple_async_result_new (NULL, callback, user_data,
- gsecret_password_store_finish);
- closure = g_new0 (StoreClosure, 1);
- closure->properties = g_variant_ref_sink (g_variant_builder_end (&builder));
+ gsecret_password_storev);
+ closure = g_slice_new0 (StoreClosure);
+ closure->schema = schema;
closure->collection_path = g_strdup (collection_path);
- closure->secret = gsecret_value_new (password, -1, "text/plain");
+ closure->label = g_strdup (label);
+ closure->value = gsecret_value_new (password, -1, "text/plain");
+ closure->attributes = g_hash_table_ref (attributes);
closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
g_simple_async_result_set_op_res_gpointer (res, closure, store_closure_free);
- _gsecret_service_bare_connect_with_session (cancellable, on_store_service_connected,
- g_object_ref (res));
+ _gsecret_service_bare_connect (NULL, TRUE, cancellable,
+ on_store_connected, g_object_ref (res));
g_object_unref (res);
}
-#if 0
gboolean
gsecret_password_store_finish (GAsyncResult *result,
GError **error)
{
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ GSimpleAsyncResult *res;
+ StoreClosure *closure;
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
+ gsecret_password_storev), FALSE);
+
+ res = G_SIMPLE_ASYNC_RESULT (result);
+ if (g_simple_async_result_propagate_error (res, error))
+ return FALSE;
+
+ closure = g_simple_async_result_get_op_res_gpointer (res);
+ return closure->created;
}
gboolean
-gsecret_password_store_sync (const GSecretPasswordSchema *schema,
- const gchar *collection,
+gsecret_password_store_sync (const GSecretSchema *schema,
+ const gchar *collection_path,
const gchar *label,
const gchar *password,
GCancellable *cancellable,
GError **error,
- const gchar *attribute_name,
...)
{
+ GHashTable *attributes;
+ va_list va;
+ gboolean ret;
+
g_return_val_if_fail (schema != NULL, FALSE);
- g_return_val_if_fail (display_name != NULL, FALSE);
+ g_return_val_if_fail (label != NULL, FALSE);
g_return_val_if_fail (password != NULL, FALSE);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ va_start (va, error);
+ attributes = _gsecret_util_attributes_for_varargs (schema, va);
+ va_end (va);
+
+ ret = gsecret_password_storev_sync (schema, collection_path, label, password,
+ attributes, cancellable, error);
+
+ g_hash_table_unref (attributes);
+ return ret;
+}
+
+gboolean
+gsecret_password_storev_sync (const GSecretSchema *schema,
+ const gchar *collection_path,
+ const gchar *label,
+ const gchar *password,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SyncClosure *closure;
+ gboolean ret;
+
+ g_return_val_if_fail (schema != NULL, FALSE);
+ g_return_val_if_fail (collection_path != NULL, FALSE);
+ g_return_val_if_fail (label != NULL, FALSE);
+ g_return_val_if_fail (password != NULL, FALSE);
+ g_return_val_if_fail (attributes != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ closure = sync_closure_new ();
+ g_main_context_push_thread_default (closure->context);
+
+ gsecret_password_storev (schema, collection_path, label, password, attributes,
+ cancellable, on_sync_result, closure);
+
+ g_main_loop_run (closure->loop);
+
+ ret = gsecret_password_store_finish (closure->result, error);
+
+ g_main_context_pop_thread_default (closure->context);
+ sync_closure_free (closure);
+
+ return ret;
+}
+
+typedef struct {
+ GCancellable *cancellable;
+ GHashTable *attributes;
+ GSecretValue *value;
+} LookupClosure;
+
+static void
+lookup_closure_free (gpointer data)
+{
+ LookupClosure *closure = data;
+ g_clear_object (&closure->cancellable);
+ g_hash_table_unref (closure->attributes);
+ if (closure->value)
+ gsecret_value_unref (closure->value);
+ g_slice_free (LookupClosure, closure);
}
void
-gsecret_password_lookup (const GSecretPasswordSchema *schema,
+gsecret_password_lookup (const GSecretSchema *schema,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
- const gchar *attribute_name,
...)
{
+ GHashTable *attributes;
+ va_list va;
+
g_return_if_fail (schema != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ va_start (va, user_data);
+ attributes = _gsecret_util_attributes_for_varargs (schema, va);
+ va_end (va);
+
+ gsecret_password_lookupv (attributes, cancellable, callback, user_data);
+
+ g_hash_table_unref (attributes);
+}
+
+static void
+on_lookup_complete (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ LookupClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ GError *error = NULL;
+
+ closure->value = gsecret_service_lookup_password_finish (GSECRET_SERVICE (source),
+ result, &error);
+
+ if (error != NULL)
+ g_simple_async_result_take_error (res, error);
+
+ g_simple_async_result_complete (res);
+ g_object_unref (res);
+}
+
+static void
+on_lookup_connected (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ LookupClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ GSecretService *service;
+ GError *error = NULL;
+
+ service = _gsecret_service_bare_connect_finish (result, &error);
+ if (error != NULL) {
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete (res);
+
+ } else {
+ gsecret_service_lookup_passwordv (service, closure->attributes, closure->cancellable,
+ on_lookup_complete, g_object_ref (res));
+ g_object_unref (service);
+ }
+
+ g_object_unref (res);
+}
+
+void
+gsecret_password_lookupv (GHashTable *attributes,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+ LookupClosure *closure;
+
+ g_return_if_fail (attributes != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ res = g_simple_async_result_new (NULL, callback, user_data,
+ gsecret_password_lookupv);
+ closure = g_slice_new0 (LookupClosure);
+ closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+ g_simple_async_result_set_op_res_gpointer (res, closure, lookup_closure_free);
+
+ _gsecret_service_bare_connect (NULL, TRUE, cancellable,
+ on_lookup_connected, g_object_ref (res));
+
+ g_object_unref (res);
}
gchar *
gsecret_password_lookup_finish (GAsyncResult *result,
GError **error)
{
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ GSimpleAsyncResult *res;
+ LookupClosure *closure;
+ const gchar *content_type;
+ gchar *password = NULL;
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
+ gsecret_password_lookupv), NULL);
+
+ res = G_SIMPLE_ASYNC_RESULT (result);
+ if (g_simple_async_result_propagate_error (res, error))
+ return NULL;
+
+ closure = g_simple_async_result_get_op_res_gpointer (res);
+ content_type = gsecret_value_get_content_type (closure->value);
+ if (content_type && g_str_equal (content_type, "text/plain")) {
+ password = _gsecret_value_unref_to_password (closure->value);
+ closure->value = NULL;
+ }
+
+ return password;
}
gchar *
-gsecret_password_lookup_sync (const GSecretPasswordSchema *schema,
+gsecret_password_lookup_sync (const GSecretSchema *schema,
GCancellable *cancellable,
GError **error,
- const gchar *attribute_name,
...)
{
+ GHashTable *attributes;
+ gchar *password;
+ va_list va;
+
g_return_val_if_fail (schema != NULL, NULL);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ va_start (va, error);
+ attributes = _gsecret_util_attributes_for_varargs (schema, va);
+ va_end (va);
+
+ password = gsecret_password_lookupv_sync (attributes, cancellable, error);
+
+ g_hash_table_unref (attributes);
+
+ return password;
}
-#endif
-#endif
+gchar *
+gsecret_password_lookupv_sync (GHashTable *attributes,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SyncClosure *closure;
+ gchar *password;
+
+ g_return_val_if_fail (attributes != NULL, NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ closure = sync_closure_new ();
+ g_main_context_push_thread_default (closure->context);
+
+ gsecret_password_deletev (attributes, cancellable,
+ on_sync_result, closure);
+
+ g_main_loop_run (closure->loop);
+
+ password = gsecret_password_lookup_finish (closure->result, error);
+
+ g_main_context_pop_thread_default (closure->context);
+ sync_closure_free (closure);
+
+ return password;
+}
typedef struct {
GCancellable *cancellable;
diff --git a/library/gsecret-password.h b/library/gsecret-password.h
index 9ab2250..b0aefa4 100644
--- a/library/gsecret-password.h
+++ b/library/gsecret-password.h
@@ -19,8 +19,6 @@ G_BEGIN_DECLS
#include "gsecret-types.h"
-#if 0
-
void gsecret_password_store (const GSecretSchema *schema,
const gchar *collection_path,
const gchar *label,
@@ -30,23 +28,45 @@ void gsecret_password_store (const GSecretSchema *sc
gpointer user_data,
...) G_GNUC_NULL_TERMINATED;
+void gsecret_password_storev (const GSecretSchema *schema,
+ const gchar *collection_path,
+ const gchar *label,
+ const gchar *password,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
gboolean gsecret_password_store_finish (GAsyncResult *result,
GError **error);
-void gsecret_password_store_sync (const GSecretSchema *schema,
- const gchar *collection,
- const gchar *display_name,
+gboolean gsecret_password_store_sync (const GSecretSchema *schema,
+ const gchar *collection_path,
+ const gchar *label,
const gchar *password,
GCancellable *cancellable,
GError **error,
...) G_GNUC_NULL_TERMINATED;
+gboolean gsecret_password_storev_sync (const GSecretSchema *schema,
+ const gchar *collection_path,
+ const gchar *display_name,
+ const gchar *password,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ GError **error);
+
void gsecret_password_lookup (const GSecretSchema *schema,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
...) G_GNUC_NULL_TERMINATED;
+void gsecret_password_lookupv (GHashTable *attributes,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
gchar * gsecret_password_lookup_finish (GAsyncResult *result,
GError **error);
@@ -55,7 +75,9 @@ gchar * gsecret_password_lookup_sync (const GSecretSchema *sc
GError **error,
...) G_GNUC_NULL_TERMINATED;
-#endif
+gchar * gsecret_password_lookupv_sync (GHashTable *attributes,
+ GCancellable *cancellable,
+ GError **error);
void gsecret_password_delete (const GSecretSchema *schema,
GCancellable *cancellable,
diff --git a/library/gsecret-private.h b/library/gsecret-private.h
index 15b0b6b..8e5b620 100644
--- a/library/gsecret-private.h
+++ b/library/gsecret-private.h
@@ -51,9 +51,30 @@ gboolean _gsecret_util_empty_path (const gchar *pat
GVariant * _gsecret_util_variant_for_attributes (GHashTable *attributes);
+GHashTable * _gsecret_util_attributes_for_variant (GVariant *variant);
+
GHashTable * _gsecret_util_attributes_for_varargs (const GSecretSchema *schema,
va_list va);
+void _gsecret_util_set_property (GDBusProxy *proxy,
+ const gchar *property,
+ GVariant *value,
+ gpointer result_tag,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean _gsecret_util_set_property_finish (GDBusProxy *proxy,
+ gpointer result_tag,
+ GAsyncResult *result,
+ GError **error);
+
+gboolean _gsecret_util_set_property_sync (GDBusProxy *proxy,
+ const gchar *property,
+ GVariant *value,
+ GCancellable *cancellable,
+ GError **error);
+
void _gsecret_service_set_default_bus_name (const gchar *bus_name);
GSecretService * _gsecret_service_bare_instance (GDBusConnection *connection,
@@ -79,6 +100,8 @@ const gchar * _gsecret_service_ensure_session_finish (GSecretService *
GCancellable **cancellable,
GError **error);
+gchar * _gsecret_value_unref_to_password (GSecretValue *value);
+
G_END_DECLS
#endif /* __G_SERVICE_H___ */
diff --git a/library/gsecret-prompt.c b/library/gsecret-prompt.c
index f1e34c6..60697fb 100644
--- a/library/gsecret-prompt.c
+++ b/library/gsecret-prompt.c
@@ -422,12 +422,23 @@ gsecret_prompt_perform_finish (GSecretPrompt *self,
}
GVariant *
-gsecret_prompt_get_result_value (GSecretPrompt *self)
+gsecret_prompt_get_result_value (GSecretPrompt *self,
+ const GVariantType *expected_type)
{
+ gchar *string;
+
g_return_val_if_fail (GSECRET_IS_PROMPT (self), NULL);
- if (self->pv->last_result)
- return g_variant_ref (self->pv->last_result);
+ if (!self->pv->last_result)
+ return NULL;
- return NULL;
+ if (expected_type && !g_variant_is_of_type (self->pv->last_result, expected_type)) {
+ string = g_variant_type_dup_string (expected_type);
+ g_warning ("received unexpected result type %s from Completed signal instead of expected %s",
+ g_variant_get_type_string (self->pv->last_result), string);
+ g_free (string);
+ return NULL;
+ }
+
+ return g_variant_ref (self->pv->last_result);
}
diff --git a/library/gsecret-prompt.h b/library/gsecret-prompt.h
index 7abfb93..59d2dd9 100644
--- a/library/gsecret-prompt.h
+++ b/library/gsecret-prompt.h
@@ -65,7 +65,8 @@ gboolean gsecret_prompt_perform_finish (GSecretPrompt *sel
GAsyncResult *result,
GError **error);
-GVariant * gsecret_prompt_get_result_value (GSecretPrompt *self);
+GVariant * gsecret_prompt_get_result_value (GSecretPrompt *self,
+ const GVariantType *expected_type);
G_END_DECLS
diff --git a/library/gsecret-service.c b/library/gsecret-service.c
index 44c3e70..63144e5 100644
--- a/library/gsecret-service.c
+++ b/library/gsecret-service.c
@@ -1493,6 +1493,172 @@ gsecret_service_get_secrets_for_paths_sync (GSecretService *self,
return values;
}
+typedef struct {
+ GCancellable *cancellable;
+ GSecretPrompt *prompt;
+ gint unlocked;
+} UnlockClosure;
+
+static void
+unlock_closure_free (gpointer data)
+{
+ UnlockClosure *closure = data;
+ g_clear_object (&closure->cancellable);
+ g_clear_object (&closure->prompt);
+ g_slice_free (UnlockClosure, closure);
+}
+
+gint
+gsecret_service_unlock_paths_sync (GSecretService *self,
+ const gchar **paths,
+ GCancellable *cancellable,
+ gchar ***unlocked,
+ GError **error)
+{
+ SyncClosure *closure;
+ gint count;
+
+ g_return_val_if_fail (GSECRET_IS_SERVICE (self), -1);
+ g_return_val_if_fail (paths != NULL, -1);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
+ g_return_val_if_fail (unlocked != NULL, -1);
+ g_return_val_if_fail (error == NULL || *error == NULL, -1);
+
+ closure = sync_closure_new ();
+ g_main_context_push_thread_default (closure->context);
+
+ gsecret_service_unlock_paths (self, paths, cancellable,
+ on_sync_result, closure);
+
+ g_main_loop_run (closure->loop);
+
+ count = gsecret_service_unlock_paths_finish (self, closure->result,
+ unlocked, error);
+
+ g_main_context_pop_thread_default (closure->context);
+ sync_closure_free (closure);
+
+ return count;
+}
+
+static void
+on_unlock_prompted (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ UnlockClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ GSecretService *self = GSECRET_SERVICE (source);
+ GVariant *retval;
+ GError *error = NULL;
+ gboolean ret;
+
+ ret = gsecret_service_prompt_finish (self, result, &error);
+ if (error != NULL)
+ g_simple_async_result_take_error (res, error);
+
+ if (ret) {
+ retval = gsecret_prompt_get_result_value (closure->prompt, G_VARIANT_TYPE ("ao"));
+ closure->unlocked = g_variant_n_children (retval);
+ g_variant_unref (retval);
+ } else {
+ closure->unlocked = 0;
+ }
+
+ g_simple_async_result_complete (res);
+ g_object_unref (res);
+}
+
+static void
+on_unlock_called (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ UnlockClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ GSecretService *self = GSECRET_SERVICE (g_async_result_get_source_object (user_data));
+ GError *error = NULL;
+ const gchar *prompt = NULL;
+ gchar **unlocked = NULL;
+ GVariant *retval;
+
+ retval = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), result, &error);
+ if (error != NULL) {
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete (res);
+
+ } else {
+ g_variant_get (retval, "(^ao&o)", &unlocked, &prompt);
+
+ if (_gsecret_util_empty_path (prompt)) {
+ closure->unlocked = g_strv_length (unlocked);
+ g_simple_async_result_complete (res);
+
+ } else {
+ closure->prompt = gsecret_prompt_instance (self, prompt);
+ gsecret_service_prompt (self, closure->prompt, closure->cancellable,
+ on_unlock_prompted, g_object_ref (res));
+ }
+
+ g_strfreev (unlocked);
+ g_variant_unref (retval);
+ }
+
+ g_object_unref (self);
+ g_object_unref (res);
+}
+
+void
+gsecret_service_unlock_paths (GSecretService *self,
+ const gchar **paths,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+ UnlockClosure *closure;
+
+ g_return_if_fail (GSECRET_IS_SERVICE (self));
+ g_return_if_fail (paths != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ gsecret_service_unlock_paths);
+ closure = g_slice_new (UnlockClosure);
+ closure->cancellable = cancellable ? g_object_ref (cancellable) : cancellable;
+ g_simple_async_result_set_op_res_gpointer (res, closure, unlock_closure_free);
+
+ g_dbus_proxy_call (G_DBUS_PROXY (self), "Unlock",
+ g_variant_new ("(@ao)", g_variant_new_objv (paths, -1)),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
+ cancellable, on_unlock_called, g_object_ref (res));
+
+ g_object_unref (res);
+}
+
+gint
+gsecret_service_unlock_paths_finish (GSecretService *self,
+ GAsyncResult *result,
+ gchar ***unlocked,
+ GError **error)
+{
+ GSimpleAsyncResult *res;
+ UnlockClosure *closure;
+
+ g_return_val_if_fail (GSECRET_IS_SERVICE (self), -1);
+ g_return_val_if_fail (unlocked != NULL, -1);
+ g_return_val_if_fail (error == NULL || *error == NULL, -1);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+ gsecret_service_unlock_paths), -1);
+
+ res = G_SIMPLE_ASYNC_RESULT (result);
+ if (g_simple_async_result_propagate_error (res, error))
+ return -1;
+
+ closure = g_simple_async_result_get_op_res_gpointer (res);
+ return closure->unlocked;
+}
+
gboolean
gsecret_service_prompt_sync (GSecretService *self,
GSecretPrompt *prompt,
@@ -1568,20 +1734,166 @@ gsecret_service_prompt_finish (GSecretService *self,
return (klass->prompt_finish) (self, result, error);
}
-#if 0
+typedef struct {
+ gchar *collection_path;
+ GSecretValue *value;
+ GCancellable *cancellable;
+ GSecretPrompt *prompt;
+ gboolean created;
+} StoreClosure;
+
+static void
+store_closure_free (gpointer data)
+{
+ StoreClosure *closure = data;
+ g_free (closure->collection_path);
+ gsecret_value_unref (closure->value);
+ g_clear_object (&closure->cancellable);
+ g_clear_object (&closure->prompt);
+ g_free (closure);
+}
void
gsecret_service_store_password (GSecretService *self,
const GSecretSchema *schema,
const gchar *collection_path,
const gchar *label,
- const gchar *password,
+ GSecretValue *value,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
...)
{
+ GHashTable *attributes;
+ va_list va;
+ g_return_if_fail (GSECRET_IS_SERVICE (self));
+ g_return_if_fail (schema != NULL);
+ g_return_if_fail (collection_path != NULL);
+ g_return_if_fail (label != NULL);
+ g_return_if_fail (value != NULL);
+
+ va_start (va, user_data);
+ attributes = _gsecret_util_attributes_for_varargs (schema, va);
+ va_end (va);
+
+ gsecret_service_store_passwordv (self, schema, attributes, collection_path,
+ label, value, cancellable, callback, user_data);
+
+ g_hash_table_unref (attributes);
+}
+
+static void
+on_store_prompt (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ StoreClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ GError *error = NULL;
+
+ closure->created = gsecret_service_prompt_finish (GSECRET_SERVICE (source), result, &error);
+ if (error != NULL)
+ g_simple_async_result_take_error (res, error);
+
+ g_simple_async_result_complete (res);
+ g_object_unref (res);
+}
+
+static void
+on_store_create (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ StoreClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ GSecretService *self = GSECRET_SERVICE (g_async_result_get_source_object (result));
+ const gchar *prompt_path = NULL;
+ const gchar *item_path = NULL;
+ GError *error = NULL;
+ GVariant *retval;
+
+ retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
+ if (error == NULL) {
+ g_variant_get (retval, "(&o&o)", &item_path, &prompt_path);
+ if (!_gsecret_util_empty_path (prompt_path)) {
+ closure->prompt = gsecret_prompt_instance (self, prompt_path);
+ gsecret_service_prompt (self, closure->prompt, closure->cancellable,
+ on_store_prompt, g_object_ref (res));
+
+ } else {
+ g_simple_async_result_complete (res);
+ }
+
+ g_variant_unref (retval);
+
+ } else {
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete (res);
+ }
+
+ g_object_unref (self);
+ g_object_unref (res);
+}
+
+void
+gsecret_service_store_passwordv (GSecretService *self,
+ const GSecretSchema *schema,
+ GHashTable *attributes,
+ const gchar *collection_path,
+ const gchar *label,
+ GSecretValue *value,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+ GVariant *attrs;
+ StoreClosure *closure;
+ GVariantBuilder builder;
+ GVariant *params;
+ GDBusProxy *proxy;
+
+ g_return_if_fail (GSECRET_IS_SERVICE (self));
+ g_return_if_fail (schema != NULL);
+ g_return_if_fail (attributes != NULL);
+ g_return_if_fail (collection_path != NULL);
+ g_return_if_fail (label != NULL);
+ g_return_if_fail (value != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ /* Build up the attributes */
+ attrs = _gsecret_util_variant_for_attributes (attributes);
+
+ /* Build up the various properties */
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&builder, "{sv}", GSECRET_SERVICE_INTERFACE "Attributes", attrs);
+ g_variant_builder_add (&builder, "{sv}", GSECRET_SERVICE_INTERFACE "Label", g_variant_new_string (label));
+ g_variant_builder_add (&builder, "{sv}", GSECRET_SERVICE_INTERFACE "Schema", g_variant_new_string (schema->schema_name));
+
+ res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ gsecret_service_store_passwordv);
+ closure = g_new0 (StoreClosure, 1);
+ closure->collection_path = g_strdup (collection_path);
+ closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+ g_simple_async_result_set_op_res_gpointer (res, closure, store_closure_free);
+
+ params = g_variant_new ("(&a{sv}&(oayays)b)",
+ g_variant_builder_end (&builder),
+ _gsecret_service_encode_secret (self, value),
+ TRUE);
+
+ proxy = G_DBUS_PROXY (self);
+ g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
+ g_dbus_proxy_get_name (proxy),
+ closure->collection_path,
+ GSECRET_COLLECTION_INTERFACE,
+ "CreateItem", params, G_VARIANT_TYPE ("(oo)"),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
+ closure->cancellable, on_store_create,
+ g_object_ref (res));
+
+ g_object_unref (res);
}
gboolean
@@ -1589,20 +1901,106 @@ gsecret_service_store_password_finish (GSecretService *self,
GAsyncResult *result,
GError **error)
{
+ GSimpleAsyncResult *res;
+ StoreClosure *closure;
+ g_return_val_if_fail (GSECRET_IS_SERVICE (self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+ gsecret_service_store_passwordv), FALSE);
+
+ res = G_SIMPLE_ASYNC_RESULT (result);
+ if (!g_simple_async_result_propagate_error (res, error))
+ return FALSE;
+
+ closure = g_simple_async_result_get_op_res_gpointer (res);
+ return closure->created;
}
-void
+gboolean
gsecret_service_store_password_sync (GSecretService *self,
const GSecretSchema *schema,
- const gchar *collection,
- const gchar *display_name,
- const gchar *password,
+ const gchar *collection_path,
+ const gchar *label,
+ GSecretValue *value,
GCancellable *cancellable,
GError **error,
...)
{
+ GHashTable *attributes;
+ gboolean ret;
+ va_list va;
+ g_return_val_if_fail (GSECRET_IS_SERVICE (self), FALSE);
+ g_return_val_if_fail (schema != NULL, FALSE);
+ g_return_val_if_fail (collection_path != NULL, FALSE);
+ g_return_val_if_fail (label != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ va_start (va, error);
+ attributes = _gsecret_util_attributes_for_varargs (schema, va);
+ va_end (va);
+
+ ret = gsecret_service_store_passwordv_sync (self, schema, attributes, collection_path,
+ label, value, cancellable, error);
+
+ g_hash_table_unref (attributes);
+
+ return ret;
+}
+
+gboolean
+gsecret_service_store_passwordv_sync (GSecretService *self,
+ const GSecretSchema *schema,
+ GHashTable *attributes,
+ const gchar *collection_path,
+ const gchar *label,
+ GSecretValue *value,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SyncClosure *closure;
+ gboolean ret;
+
+ g_return_val_if_fail (GSECRET_IS_SERVICE (self), FALSE);
+ g_return_val_if_fail (schema != NULL, FALSE);
+ g_return_val_if_fail (attributes != NULL, FALSE);
+ g_return_val_if_fail (collection_path != NULL, FALSE);
+ g_return_val_if_fail (label != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ closure = sync_closure_new ();
+ g_main_context_push_thread_default (closure->context);
+
+ gsecret_service_store_passwordv (self, schema, attributes, collection_path,
+ label, value, cancellable, on_sync_result, closure);
+
+ g_main_loop_run (closure->loop);
+
+ ret = gsecret_service_store_password_finish (self, closure->result, error);
+
+ g_main_context_pop_thread_default (closure->context);
+ sync_closure_free (closure);
+
+ return ret;
+}
+
+typedef struct {
+ GSecretValue *value;
+ GCancellable *cancellable;
+} LookupClosure;
+
+static void
+lookup_closure_free (gpointer data)
+{
+ LookupClosure *closure = data;
+ gsecret_value_unref (closure->value);
+ g_clear_object (&closure->cancellable);
+ g_slice_free (LookupClosure, closure);
}
void
@@ -1613,28 +2011,214 @@ gsecret_service_lookup_password (GSecretService *self,
gpointer user_data,
...)
{
+ GHashTable *attributes;
+ va_list va;
+ g_return_if_fail (GSECRET_IS_SERVICE (self));
+ g_return_if_fail (schema != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ va_start (va, user_data);
+ attributes = _gsecret_util_attributes_for_varargs (schema, va);
+ va_end (va);
+
+ gsecret_service_lookup_passwordv (self, attributes, cancellable, callback, user_data);
+
+ g_hash_table_unref (attributes);
}
-gchar *
+static void
+on_lookup_get_secret (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ LookupClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ GSecretService *self = GSECRET_SERVICE (source);
+ GError *error = NULL;
+
+ closure->value = gsecret_service_get_secret_for_path_finish (self, result, &error);
+ if (error != NULL)
+ g_simple_async_result_take_error (res, error);
+
+ g_simple_async_result_complete (res);
+ g_object_unref (res);
+}
+
+static void
+on_lookup_unlocked (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ LookupClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ GSecretService *self = GSECRET_SERVICE (source);
+ GError *error = NULL;
+ gchar **unlocked = NULL;
+
+ gsecret_service_unlock_paths_finish (GSECRET_SERVICE (source),
+ result, &unlocked, &error);
+ if (error != NULL) {
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete (res);
+
+ } else if (unlocked && unlocked[0]) {
+ gsecret_service_get_secret_for_path (self, unlocked[0],
+ closure->cancellable,
+ on_lookup_get_secret,
+ g_object_ref (res));
+
+ } else {
+ g_simple_async_result_complete (res);
+ }
+
+ g_strfreev (unlocked);
+ g_object_unref (res);
+}
+
+static void
+on_lookup_searched (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ LookupClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ GSecretService *self = GSECRET_SERVICE (source);
+ GError *error = NULL;
+ gchar **unlocked = NULL;
+ gchar **locked = NULL;
+
+ gsecret_service_search_for_paths_finish (self, result, &unlocked, &locked, &error);
+ if (error != NULL) {
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete (res);
+
+ } else if (unlocked && unlocked[0]) {
+ gsecret_service_get_secret_for_path (self, unlocked[0],
+ closure->cancellable,
+ on_lookup_get_secret,
+ g_object_ref (res));
+
+ } else if (locked && locked[0]) {
+ const gchar *paths[] = { locked[0], NULL };
+ gsecret_service_unlock_paths (self, paths,
+ closure->cancellable,
+ on_lookup_unlocked,
+ g_object_ref (res));
+
+ } else {
+ g_simple_async_result_complete (res);
+ }
+
+ g_strfreev (unlocked);
+ g_strfreev (locked);
+ g_object_unref (res);
+}
+
+void
+gsecret_service_lookup_passwordv (GSecretService *self,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+ LookupClosure *closure;
+
+ g_return_if_fail (GSECRET_IS_SERVICE (self));
+ g_return_if_fail (attributes != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ gsecret_service_lookup_passwordv);
+ closure = g_slice_new0 (LookupClosure);
+ closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+ g_simple_async_result_set_op_res_gpointer (res, closure, lookup_closure_free);
+
+ gsecret_service_search_for_paths (self, attributes, cancellable,
+ on_lookup_searched, g_object_ref (res));
+
+ g_object_unref (res);
+}
+
+GSecretValue *
gsecret_service_lookup_password_finish (GSecretService *self,
GAsyncResult *result,
GError **error)
{
+ GSimpleAsyncResult *res;
+ LookupClosure *closure;
+ GSecretValue *value;
+ g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+ gsecret_service_lookup_passwordv), NULL);
+
+ res = G_SIMPLE_ASYNC_RESULT (result);
+ if (g_simple_async_result_propagate_error (res, error))
+ return NULL;
+
+ closure = g_simple_async_result_get_op_res_gpointer (res);
+ value = closure->value;
+ closure->value = NULL;
+ return value;
}
-gchar *
+GSecretValue *
gsecret_service_lookup_password_sync (GSecretService *self,
const GSecretSchema *schema,
GCancellable *cancellable,
GError **error,
...)
{
+ GHashTable *attributes;
+ GSecretValue *value;
+ va_list va;
+ g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
+ g_return_val_if_fail (schema != NULL, NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+
+ va_start (va, error);
+ attributes = _gsecret_util_attributes_for_varargs (schema, va);
+ va_end (va);
+
+ value = gsecret_service_lookup_passwordv_sync (self, attributes, cancellable, error);
+
+ g_hash_table_unref (attributes);
+
+ return value;
}
-#endif
+GSecretValue *
+gsecret_service_lookup_passwordv_sync (GSecretService *self,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SyncClosure *closure;
+ GSecretValue *value;
+
+ g_return_val_if_fail (GSECRET_IS_SERVICE (self), NULL);
+ g_return_val_if_fail (attributes != NULL, NULL);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+
+ closure = sync_closure_new ();
+ g_main_context_push_thread_default (closure->context);
+
+ gsecret_service_lookup_passwordv (self, attributes, cancellable,
+ on_sync_result, closure);
+
+ g_main_loop_run (closure->loop);
+
+ value = gsecret_service_lookup_password_finish (self, closure->result, error);
+
+ g_main_context_pop_thread_default (closure->context);
+ sync_closure_free (closure);
+
+ return value;
+}
typedef struct {
GCancellable *cancellable;
diff --git a/library/gsecret-service.h b/library/gsecret-service.h
index a65a621..bb1050b 100644
--- a/library/gsecret-service.h
+++ b/library/gsecret-service.h
@@ -235,30 +235,48 @@ gboolean gsecret_service_prompt_finish (GSecretService *se
GAsyncResult *result,
GError **error);
-#if 0
void gsecret_service_store_password (GSecretService *self,
const GSecretSchema *schema,
const gchar *collection_path,
const gchar *label,
- const gchar *password,
+ GSecretValue *value,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
...) G_GNUC_NULL_TERMINATED;
+void gsecret_service_store_passwordv (GSecretService *self,
+ const GSecretSchema *schema,
+ GHashTable *attributes,
+ const gchar *collection_path,
+ const gchar *label,
+ GSecretValue *value,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
gboolean gsecret_service_store_password_finish (GSecretService *self,
GAsyncResult *result,
GError **error);
-void gsecret_service_store_password_sync (GSecretService *self,
+gboolean gsecret_service_store_password_sync (GSecretService *self,
const GSecretSchema *schema,
- const gchar *collection,
- const gchar *display_name,
- const gchar *password,
+ const gchar *collection_path,
+ const gchar *label,
+ GSecretValue *value,
GCancellable *cancellable,
GError **error,
...) G_GNUC_NULL_TERMINATED;
+gboolean gsecret_service_store_passwordv_sync (GSecretService *self,
+ const GSecretSchema *schema,
+ GHashTable *attributes,
+ const gchar *collection_path,
+ const gchar *label,
+ GSecretValue *value,
+ GCancellable *cancellable,
+ GError **error);
+
void gsecret_service_lookup_password (GSecretService *self,
const GSecretSchema *schema,
GCancellable *cancellable,
@@ -266,16 +284,26 @@ void gsecret_service_lookup_password (GSecretService *se
gpointer user_data,
...) G_GNUC_NULL_TERMINATED;
-gchar * gsecret_service_lookup_password_finish (GSecretService *self,
+void gsecret_service_lookup_passwordv (GSecretService *self,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GSecretValue * gsecret_service_lookup_password_finish (GSecretService *self,
GAsyncResult *result,
GError **error);
-gchar * gsecret_service_lookup_password_sync (GSecretService *self,
+GSecretValue * gsecret_service_lookup_password_sync (GSecretService *self,
const GSecretSchema *schema,
GCancellable *cancellable,
GError **error,
...) G_GNUC_NULL_TERMINATED;
-#endif
+
+GSecretValue * gsecret_service_lookup_passwordv_sync (GSecretService *self,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ GError **error);
void gsecret_service_delete_path (GSecretService *self,
const gchar *item_path,
diff --git a/library/gsecret-util.c b/library/gsecret-util.c
index 45c97f1..7c2b5f7 100644
--- a/library/gsecret-util.c
+++ b/library/gsecret-util.c
@@ -99,6 +99,23 @@ _gsecret_util_variant_for_attributes (GHashTable *attributes)
}
+GHashTable *
+_gsecret_util_attributes_for_variant (GVariant *variant)
+{
+ GVariantIter iter;
+ GHashTable *attributes;
+ gchar *value;
+ gchar *key;
+
+ attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ g_variant_iter_init (&iter, variant);
+ while (g_variant_iter_next (&iter, "{sv}", &key, &value))
+ g_hash_table_insert (attributes, key, value);
+
+ return attributes;
+}
+
GHashTable *
_gsecret_util_attributes_for_varargs (const GSecretSchema *schema,
va_list args)
@@ -166,3 +183,105 @@ _gsecret_util_attributes_for_varargs (const GSecretSchema *schema,
return attributes;
}
+
+static void
+on_set_property (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ GError *error = NULL;
+ GVariant *retval;
+
+ retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source),
+ result, &error);
+ if (error != NULL)
+ g_simple_async_result_take_error (res, error);
+ if (retval != NULL)
+ g_variant_unref (retval);
+ g_simple_async_result_set_op_res_gboolean (res, retval != NULL);
+ g_object_unref (res);
+}
+
+void
+_gsecret_util_set_property (GDBusProxy *proxy,
+ const gchar *property,
+ GVariant *value,
+ gpointer result_tag,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ res = g_simple_async_result_new (G_OBJECT (proxy), callback, user_data, result_tag);
+
+ g_dbus_connection_call (g_dbus_proxy_get_connection (proxy),
+ g_dbus_proxy_get_name (proxy),
+ g_dbus_proxy_get_object_path (proxy),
+ GSECRET_PROPERTIES_INTERFACE,
+ "Set",
+ g_variant_new ("(ssv)",
+ g_dbus_proxy_get_interface_name (proxy),
+ property,
+ value),
+ G_VARIANT_TYPE ("()"),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
+ cancellable, on_set_property,
+ g_object_ref (res));
+
+ g_object_unref (res);
+}
+
+gboolean
+_gsecret_util_set_property_finish (GDBusProxy *proxy,
+ gpointer result_tag,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *res;
+
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (proxy), result_tag), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ res = G_SIMPLE_ASYNC_RESULT (result);
+
+ if (g_simple_async_result_propagate_error (res, error))
+ return FALSE;
+
+ return g_simple_async_result_get_op_res_gboolean (res);
+}
+
+
+gboolean
+_gsecret_util_set_property_sync (GDBusProxy *proxy,
+ const gchar *property,
+ GVariant *value,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *retval;
+
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ retval = g_dbus_connection_call_sync (g_dbus_proxy_get_connection (proxy),
+ g_dbus_proxy_get_name (proxy),
+ g_dbus_proxy_get_object_path (proxy),
+ GSECRET_PROPERTIES_INTERFACE,
+ "Set",
+ g_variant_new ("(ssv)",
+ g_dbus_proxy_get_interface_name (proxy),
+ property,
+ value),
+ G_VARIANT_TYPE ("()"),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START, -1,
+ cancellable, error);
+
+ if (retval != NULL)
+ g_variant_unref (retval);
+
+ return (retval != NULL);
+}
diff --git a/library/gsecret-value.c b/library/gsecret-value.c
index 6980264..97d6819 100644
--- a/library/gsecret-value.c
+++ b/library/gsecret-value.c
@@ -12,6 +12,7 @@
#include "config.h"
+#include "gsecret-private.h"
#include "gsecret-value.h"
#include "egg/egg-secure-memory.h"
@@ -112,7 +113,7 @@ gsecret_value_unref (gpointer value)
{
GSecretValue *val = value;
- g_return_if_fail (value);
+ g_return_if_fail (value != NULL);
if (g_atomic_int_dec_and_test (&val->refs)) {
g_free (val->content_type);
@@ -121,3 +122,35 @@ gsecret_value_unref (gpointer value)
g_slice_free (GSecretValue, val);
}
}
+
+gchar *
+_gsecret_value_unref_to_password (GSecretValue *value)
+{
+ GSecretValue *val = value;
+ gchar *result;
+
+ g_return_val_if_fail (value != NULL, NULL);
+
+ if (val->content_type && !g_str_equal (val->content_type, "text/plain")) {
+ gsecret_value_unref (value);
+ return NULL;
+ }
+
+ if (g_atomic_int_dec_and_test (&val->refs)) {
+ if (val->destroy == egg_secure_free) {
+ result = val->secret;
+
+ } else {
+ result = egg_secure_strdup (val->secret);
+ if (val->destroy)
+ (val->destroy) (val->secret);
+ }
+ g_free (val->content_type);
+ g_slice_free (GSecretValue, val);
+
+ } else {
+ result = egg_secure_strdup (val->secret);
+ }
+
+ return result;
+}
diff --git a/library/gsecret-value.h b/library/gsecret-value.h
index 2046467..556827e 100644
--- a/library/gsecret-value.h
+++ b/library/gsecret-value.h
@@ -21,13 +21,13 @@ G_BEGIN_DECLS
#define GSECRET_TYPE_VALUE (gsecret_service_get_type ())
-GType gsecret_value_get_type (void) G_GNUC_CONST;
+GType gsecret_value_get_type (void) G_GNUC_CONST;
-GSecretValue* gsecret_value_new (const gchar *secret,
+GSecretValue* gsecret_value_new (const gchar *secret,
gssize length,
const gchar *content_type);
-GSecretValue* gsecret_value_new_full (gchar *secret,
+GSecretValue* gsecret_value_new_full (gchar *secret,
gssize length,
const gchar *content_type,
GDestroyNotify destroy);
diff --git a/library/tests/test-prompt.c b/library/tests/test-prompt.c
index c7197cb..620da2b 100644
--- a/library/tests/test-prompt.c
+++ b/library/tests/test-prompt.c
@@ -265,16 +265,15 @@ test_prompt_result (Test *test,
prompt = gsecret_prompt_instance (test->service, "/org/freedesktop/secrets/prompts/result");
- result = gsecret_prompt_get_result_value (prompt);
+ result = gsecret_prompt_get_result_value (prompt, NULL);
g_assert (result == NULL);
ret = gsecret_prompt_perform_sync (prompt, 0, NULL, &error);
g_assert_no_error (error);
g_assert (ret == TRUE);
- result = gsecret_prompt_get_result_value (prompt);
+ result = gsecret_prompt_get_result_value (prompt, G_VARIANT_TYPE_STRING);
g_assert (result != NULL);
- g_assert_cmpstr (g_variant_get_type_string (result), ==, "s");
g_assert_cmpstr (g_variant_get_string (result, NULL), ==, "Special Result");
g_variant_unref (result);
@@ -297,9 +296,8 @@ test_prompt_window_id (Test *test,
g_assert_no_error (error);
g_assert (ret == TRUE);
- result = gsecret_prompt_get_result_value (prompt);
+ result = gsecret_prompt_get_result_value (prompt, G_VARIANT_TYPE_STRING);
g_assert (result != NULL);
- g_assert_cmpstr (g_variant_get_type_string (result), ==, "s");
g_assert_cmpstr (g_variant_get_string (result, NULL), ==, "555");
g_variant_unref (result);