Complete the gsecret_password_xxx() API.
authorStef Walter <stefw@gnome.org>
Mon, 16 Jan 2012 14:08:29 +0000 (15:08 +0100)
committerStef Walter <stefw@collabora.co.uk>
Mon, 16 Jan 2012 14:08:29 +0000 (15:08 +0100)
library/gsecret-password.c
library/gsecret-password.h
library/gsecret-private.h
library/gsecret-prompt.c
library/gsecret-prompt.h
library/gsecret-service.c
library/gsecret-service.h
library/gsecret-util.c
library/gsecret-value.c
library/gsecret-value.h
library/tests/test-prompt.c

index d50446172fc22d35b682dbde3dccfcb3e06590f9..be540694cf63fcbe6233fb406bc82abeb2a7b13e 100644 (file)
@@ -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);
-
-               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));
+               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);
+
        } else {
                g_simple_async_result_take_error (res, error);
                g_simple_async_result_complete (res);
-
-               <arg name="item" type="o" direction="out"/>
-               <arg name="prompt" type="o" direction="out"/>
        }
 
        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)
 {
+       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)
 {
+       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;
index 9ab2250ef580b5107e2366b14340183898b218d6..b0aefa43a2373cc936497cbf08119b58fd46d6d8 100644 (file)
@@ -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,
index 15b0b6b9b56f95d66b3495a080580676a2cec638..8e5b620c4aa1daf5910fa134593a741f35b08b33 100644 (file)
@@ -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___ */
index f1e34c60140c878bf747edd7eb213eefaac2b0d7..60697fbfa10f4d0bbe690a8f8233b4a1f690084d 100644 (file)
@@ -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;
+
+       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 NULL;
+       return g_variant_ref (self->pv->last_result);
 }
index 7abfb93e52f6590842aa69fd7786f169ddb04c19..59d2dd995fc35d5473375d1b95a615b6d57448c6 100644 (file)
@@ -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
 
index 44c3e70bbf1c4ff07ce3c454ad059de305a68e06..63144e5733058c45715b68df70cf5e13e5eb7d24 100644 (file)
@@ -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);
+}
+
+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);
 }
 
-gchar *
+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;
index a65a62183da72d4ebec135c3f0d04b5771aacb8d..bb1050be806500d12cad91b4990923b8513ad7b3 100644 (file)
@@ -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,
index 45c97f13b166e5d3f2ca41a987e9de2b6e6ee095..7c2b5f751a3814a30bf2c020fb66bacfa9d2a256 100644 (file)
@@ -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);
+}
index 698026466cad242147d57bc98b9cd8ef53e90923..97d68195b3a344eb98d7c2eac03b136110fede14 100644 (file)
@@ -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;
+}
index 204646710efe8a3694e729f656b8356790a8894a..556827e8bfa70fe4308b7cdd2adb90122ea7d9e7 100644 (file)
@@ -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);
index c7197cb7c85206eb4adca0611ecae6fa929aac72..620da2b376d1f3b161e742f11ff6e99ae386aa88 100644 (file)
@@ -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);