summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@gnu.org>2019-07-22 10:55:30 +0000
committerDaiki Ueno <ueno@gnu.org>2019-07-22 10:55:30 +0000
commitf7e73bab6dc55947c14f3370f2a227dd80e1fdf3 (patch)
tree68ca699c0d4abcd2831433abfde9d08fc2f577e8
parent9a8f49f237a8e61e8274d66d008e4dcd8dc72bf3 (diff)
parent6886aebb0457d752f348a4cedc5a11ce109544ee (diff)
downloadlibsecret-f7e73bab6dc55947c14f3370f2a227dd80e1fdf3.tar.gz
Merge branch 'wip/dueno/simple-item' into 'master'
secret-password: Add necessary functions to migrate from D-Bus based API See merge request GNOME/libsecret!32
-rw-r--r--docs/reference/libsecret/libsecret-docs.sgml1
-rw-r--r--docs/reference/libsecret/libsecret-sections.txt28
-rw-r--r--libsecret/Makefile.am2
-rw-r--r--libsecret/meson.build4
-rw-r--r--libsecret/secret-item.c71
-rw-r--r--libsecret/secret-password.c588
-rw-r--r--libsecret/secret-password.h116
-rw-r--r--libsecret/secret-retrievable.c307
-rw-r--r--libsecret/secret-retrievable.h64
-rw-r--r--libsecret/secret-service.h7
-rw-r--r--libsecret/secret-types.h7
-rw-r--r--libsecret/secret-value.c40
-rw-r--r--libsecret/secret-value.h3
-rw-r--r--libsecret/secret.h1
-rw-r--r--libsecret/test-password.c161
-rw-r--r--tool/secret-tool.c140
16 files changed, 1408 insertions, 132 deletions
diff --git a/docs/reference/libsecret/libsecret-docs.sgml b/docs/reference/libsecret/libsecret-docs.sgml
index 6ce3dba..0381c5a 100644
--- a/docs/reference/libsecret/libsecret-docs.sgml
+++ b/docs/reference/libsecret/libsecret-docs.sgml
@@ -26,6 +26,7 @@
<xi:include href="xml/secret-service.xml"/>
<xi:include href="xml/secret-collection.xml"/>
<xi:include href="xml/secret-item.xml"/>
+ <xi:include href="xml/secret-retrievable.xml"/>
<xi:include href="xml/secret-value.xml"/>
<xi:include href="xml/secret-attributes.xml"/>
<xi:include href="xml/secret-prompt.xml"/>
diff --git a/docs/reference/libsecret/libsecret-sections.txt b/docs/reference/libsecret/libsecret-sections.txt
index 2ae7250..f811b9d 100644
--- a/docs/reference/libsecret/libsecret-sections.txt
+++ b/docs/reference/libsecret/libsecret-sections.txt
@@ -120,6 +120,10 @@ secret_password_storev
secret_password_store_finish
secret_password_store_sync
secret_password_storev_sync
+secret_password_store_binary
+secret_password_store_binary_sync
+secret_password_storev_binary
+secret_password_storev_binary_sync
secret_password_lookup
secret_password_lookupv
secret_password_lookup_finish
@@ -128,16 +132,39 @@ secret_password_lookup_sync
secret_password_lookup_nonpageable_sync
secret_password_lookupv_sync
secret_password_lookupv_nonpageable_sync
+secret_password_lookup_binary_finish
+secret_password_lookup_binary_sync
+secret_password_lookupv_binary_sync
secret_password_clear
secret_password_clearv
secret_password_clear_finish
secret_password_clear_sync
secret_password_clearv_sync
+secret_password_search
+secret_password_search_finish
+secret_password_search_sync
+secret_password_searchv
+secret_password_searchv_sync
secret_password_wipe
secret_password_free
</SECTION>
<SECTION>
+<FILE>secret-retrievable</FILE>
+<INCLUDE>libsecret/secret.h</INCLUDE>
+SECRET_TYPE_RETRIEVABLE
+SecretRetrievable
+SecretRetrievableInterface
+secret_retrievable_get_attributes
+secret_retrievable_get_created
+secret_retrievable_get_label
+secret_retrievable_get_modified
+secret_retrievable_retrieve_secret
+secret_retrievable_retrieve_secret_finish
+secret_retrievable_retrieve_secret_sync
+</SECTION>
+
+<SECTION>
<FILE>secret-schema</FILE>
<INCLUDE>libsecret/secret.h</INCLUDE>
SECRET_SCHEMA_NOTE
@@ -306,6 +333,7 @@ secret_value_get_text
secret_value_get_content_type
secret_value_ref
secret_value_unref
+secret_value_unref_to_password
<SUBSECTION Standard>
SECRET_TYPE_VALUE
secret_value_get_type
diff --git a/libsecret/Makefile.am b/libsecret/Makefile.am
index c91b733..0e661b8 100644
--- a/libsecret/Makefile.am
+++ b/libsecret/Makefile.am
@@ -12,6 +12,7 @@ libsecret_HEADS = \
libsecret/secret-password.h \
libsecret/secret-paths.h \
libsecret/secret-prompt.h \
+ libsecret/secret-retrievable.h \
libsecret/secret-schema.h \
libsecret/secret-schemas.h \
libsecret/secret-service.h \
@@ -42,6 +43,7 @@ libsecret_PUBLIC = \
libsecret/secret-methods.c \
libsecret/secret-password.h libsecret/secret-password.c \
libsecret/secret-prompt.h libsecret/secret-prompt.c \
+ libsecret/secret-retrievable.h libsecret/secret-retrievable.c \
libsecret/secret-schema.h libsecret/secret-schema.c \
libsecret/secret-schemas.h libsecret/secret-schemas.c \
libsecret/secret-service.h libsecret/secret-service.c \
diff --git a/libsecret/meson.build b/libsecret/meson.build
index f35c396..60fa11e 100644
--- a/libsecret/meson.build
+++ b/libsecret/meson.build
@@ -7,6 +7,7 @@ libsecret_sources = [
'secret-methods.c',
'secret-password.c',
'secret-prompt.c',
+ 'secret-retrievable.c',
'secret-schema.c',
'secret-schemas.c',
'secret-service.c',
@@ -24,6 +25,7 @@ libsecret_headers = [
'secret-password.h',
'secret-paths.h',
'secret-prompt.h',
+ 'secret-retrievable.h',
'secret-schema.h',
'secret-schemas.h',
'secret-service.h',
@@ -104,6 +106,8 @@ libsecret_gir_sources = [
'secret-paths.h',
'secret-prompt.c',
'secret-prompt.h',
+ 'secret-retrievable.c',
+ 'secret-retrievable.h',
'secret-schema.c',
'secret-schema.h',
'secret-schemas.c',
diff --git a/libsecret/secret-item.c b/libsecret/secret-item.c
index d447bcd..a5eb7cf 100644
--- a/libsecret/secret-item.c
+++ b/libsecret/secret-item.c
@@ -19,6 +19,7 @@
#include "secret-item.h"
#include "secret-paths.h"
#include "secret-private.h"
+#include "secret-retrievable.h"
#include "secret-service.h"
#include "secret-types.h"
#include "secret-value.h"
@@ -105,16 +106,21 @@ struct _SecretItemPrivate {
gint disposed;
};
+static SecretRetrievableInterface *secret_item_retrievable_parent_iface = NULL;
+
static GInitableIface *secret_item_initable_parent_iface = NULL;
static GAsyncInitableIface *secret_item_async_initable_parent_iface = NULL;
+static void secret_item_retrievable_iface (SecretRetrievableInterface *iface);
+
static void secret_item_initable_iface (GInitableIface *iface);
static void secret_item_async_initable_iface (GAsyncInitableIface *iface);
G_DEFINE_TYPE_WITH_CODE (SecretItem, secret_item, G_TYPE_DBUS_PROXY,
G_ADD_PRIVATE (SecretItem)
+ G_IMPLEMENT_INTERFACE (SECRET_TYPE_RETRIEVABLE, secret_item_retrievable_iface);
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, secret_item_initable_iface);
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, secret_item_async_initable_iface);
);
@@ -355,9 +361,7 @@ secret_item_class_init (SecretItemClass *klass)
* The attributes set on this item. Attributes are used to locate an
* item. They are not guaranteed to be stored or transferred securely.
*/
- g_object_class_install_property (gobject_class, PROP_ATTRIBUTES,
- g_param_spec_boxed ("attributes", "Attributes", "Item attributes",
- G_TYPE_HASH_TABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_override_property (gobject_class, PROP_ATTRIBUTES, "attributes");
/**
* SecretItem:label:
@@ -368,9 +372,7 @@ secret_item_class_init (SecretItemClass *klass)
* set asynchronously. To properly track the changing of the label use the
* secret_item_set_label() function.
*/
- g_object_class_install_property (gobject_class, PROP_LABEL,
- g_param_spec_string ("label", "Label", "Item label",
- NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_override_property (gobject_class, PROP_LABEL, "label");
/**
* SecretItem:locked:
@@ -391,9 +393,7 @@ secret_item_class_init (SecretItemClass *klass)
* The date and time (in seconds since the UNIX epoch) that this
* item was created.
*/
- g_object_class_install_property (gobject_class, PROP_CREATED,
- g_param_spec_uint64 ("created", "Created", "Item creation date",
- 0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_override_property (gobject_class, PROP_CREATED, "created");
/**
* SecretItem:modified:
@@ -401,9 +401,7 @@ secret_item_class_init (SecretItemClass *klass)
* The date and time (in seconds since the UNIX epoch) that this
* item was last modified.
*/
- g_object_class_install_property (gobject_class, PROP_MODIFIED,
- g_param_spec_uint64 ("modified", "Modified", "Item modified date",
- 0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_override_property (gobject_class, PROP_MODIFIED, "modified");
}
typedef struct {
@@ -1320,6 +1318,55 @@ secret_item_load_secret_sync (SecretItem *self,
return result;
}
+static void
+on_retrieve_load (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ SecretItem *self = SECRET_ITEM (source_object);
+ GTask *task = G_TASK (user_data);
+ GError *error = NULL;
+
+ if (secret_item_load_secret_finish (self, res, &error)) {
+ g_task_return_pointer (task,
+ secret_item_get_secret (self),
+ secret_value_unref);
+ g_object_unref (task);
+ } else {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ }
+}
+
+static void
+secret_item_retrieve_secret (SecretRetrievable *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task = g_task_new (self, cancellable, callback, user_data);
+
+ secret_item_load_secret (SECRET_ITEM (self), cancellable, on_retrieve_load, task);
+}
+
+static SecretValue *
+secret_item_retrieve_secret_finish (SecretRetrievable *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, self), NULL);
+
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+static void
+secret_item_retrievable_iface (SecretRetrievableInterface *iface)
+{
+ secret_item_retrievable_parent_iface = g_type_interface_peek_parent (iface);
+ iface->retrieve_secret = secret_item_retrieve_secret;
+ iface->retrieve_secret_finish = secret_item_retrieve_secret_finish;
+}
+
typedef struct {
SecretService *service;
GCancellable *cancellable;
diff --git a/libsecret/secret-password.c b/libsecret/secret-password.c
index 149995d..632ed2d 100644
--- a/libsecret/secret-password.c
+++ b/libsecret/secret-password.c
@@ -17,6 +17,7 @@
#include "secret-attributes.h"
#include "secret-password.h"
#include "secret-private.h"
+#include "secret-retrievable.h"
#include "secret-value.h"
#include <egg/egg-secure-memory.h>
@@ -103,7 +104,7 @@ secret_password_store (const SecretSchema *schema,
/**
* secret_password_storev: (rename-to secret_password_store)
- * @schema: the schema for attributes
+ * @schema: (nullable): the schema for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
* @label: label for the secret
@@ -137,14 +138,13 @@ secret_password_storev (const SecretSchema *schema,
{
SecretValue *value;
- g_return_if_fail (schema != 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));
/* Warnings raised already */
- if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
+ if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
return;
value = secret_value_new (password, -1, "text/plain");
@@ -156,6 +156,101 @@ secret_password_storev (const SecretSchema *schema,
}
/**
+ * secret_password_store_binary: (skip)
+ * @schema: the schema for attributes
+ * @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
+ * @label: label for the secret
+ * @value: a #SecretValue
+ * @cancellable: optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to be passed to the callback
+ * @...: the attribute keys and values, terminated with %NULL
+ *
+ * Store a password in the secret service.
+ *
+ * This is similar to secret_password_store(), but takes a
+ * #SecretValue as the argument instead of a null-terminated password.
+ *
+ * This method will return immediately and complete asynchronously.
+ *
+ * Since: 0.19.0
+ */
+void
+secret_password_store_binary (const SecretSchema *schema,
+ const gchar *collection,
+ const gchar *label,
+ SecretValue *value,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ ...)
+{
+ GHashTable *attributes;
+ va_list va;
+
+ g_return_if_fail (schema != NULL);
+ g_return_if_fail (label != NULL);
+ g_return_if_fail (value != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ va_start (va, user_data);
+ attributes = secret_attributes_buildv (schema, va);
+ va_end (va);
+
+ /* Precondition failed, already warned */
+ if (!attributes)
+ return;
+
+ secret_password_storev_binary (schema, attributes, collection, label, value,
+ cancellable, callback, user_data);
+
+ g_hash_table_unref (attributes);
+}
+
+/**
+ * secret_password_storev_binary: (rename-to secret_password_store_binary)
+ * @schema: (nullable): the schema for attributes
+ * @attributes: (element-type utf8 utf8): the attribute keys and values
+ * @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
+ * @label: label for the secret
+ * @value: a #SecretValue
+ * @cancellable: optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to be passed to the callback
+ *
+ * Store a password in the secret service.
+ *
+ * This is similar to secret_password_storev(), but takes a
+ * #SecretValue as the argument instead of a null-terminated password.
+ *
+ * This method will return immediately and complete asynchronously.
+ *
+ * Since: 0.19.0
+ */
+void
+secret_password_storev_binary (const SecretSchema *schema,
+ GHashTable *attributes,
+ const gchar *collection,
+ const gchar *label,
+ SecretValue *value,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (label != NULL);
+ g_return_if_fail (value != NULL);
+ g_return_if_fail (attributes != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ /* Warnings raised already */
+ if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
+ return;
+
+ secret_service_store (NULL, schema, attributes, collection,
+ label, value, cancellable, callback, user_data);
+}
+
+/**
* secret_password_store_finish:
* @result: the asynchronous result passed to the callback
* @error: location to place an error on failure
@@ -237,7 +332,7 @@ secret_password_store_sync (const SecretSchema *schema,
/**
* secret_password_storev_sync: (rename-to secret_password_store_sync)
- * @schema: the schema for attributes
+ * @schema: (nullable): the schema for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
* @label: label for the secret
@@ -273,7 +368,6 @@ secret_password_storev_sync (const SecretSchema *schema,
SecretSync *sync;
gboolean ret;
- g_return_val_if_fail (schema != 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);
@@ -281,7 +375,7 @@ secret_password_storev_sync (const SecretSchema *schema,
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
/* Warnings raised already */
- if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
+ if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
return FALSE;
sync = _secret_sync_new ();
@@ -301,6 +395,122 @@ secret_password_storev_sync (const SecretSchema *schema,
}
/**
+ * secret_password_store_binary_sync:
+ * @schema: the schema for attributes
+ * @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
+ * @label: label for the secret
+ * @value: a #SecretValue
+ * @cancellable: optional cancellation object
+ * @error: location to place an error on failure
+ * @...: the attribute keys and values, terminated with %NULL
+ *
+ * Store a password in the secret service.
+ *
+ * This is similar to secret_password_store_sync(), but takes a
+ * #SecretValue as the argument instead of a null terminated password.
+ *
+ * This method may block indefinitely and should not be used in user interface
+ * threads.
+ *
+ * Returns: whether the storage was successful or not
+ *
+ * Since: 0.19.0
+ */
+gboolean
+secret_password_store_binary_sync (const SecretSchema *schema,
+ const gchar *collection,
+ const gchar *label,
+ SecretValue *value,
+ GCancellable *cancellable,
+ GError **error,
+ ...)
+{
+ GHashTable *attributes;
+ va_list va;
+ gboolean ret;
+
+ g_return_val_if_fail (schema != 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 = secret_attributes_buildv (schema, va);
+ va_end (va);
+
+ /* Precondition failed, already warned */
+ if (!attributes)
+ return FALSE;
+
+ ret = secret_password_storev_binary_sync (schema, attributes, collection,
+ label, value, cancellable, error);
+
+ g_hash_table_unref (attributes);
+ return ret;
+}
+
+/**
+ * secret_password_storev_binary_sync: (rename-to secret_password_store_binary_sync)
+ * @schema: (nullable): the schema for attributes
+ * @attributes: (element-type utf8 utf8): the attribute keys and values
+ * @collection: (allow-none): a collection alias, or D-Bus object path of the collection where to store the secret
+ * @label: label for the secret
+ * @value: a #SecretValue
+ * @cancellable: optional cancellation object
+ * @error: location to place an error on failure
+ *
+ * Store a password in the secret service.
+ *
+ * This is similar to secret_password_storev_sync(), but takes a
+ * #SecretValue as the argument instead of a null-terminated passwords.
+ *
+ * This method may block indefinitely and should not be used in user interface
+ * threads.
+ *
+ * Returns: whether the storage was successful or not
+ *
+ * Since: 0.19.0
+ */
+gboolean
+secret_password_storev_binary_sync (const SecretSchema *schema,
+ GHashTable *attributes,
+ const gchar *collection,
+ const gchar *label,
+ SecretValue *value,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SecretSync *sync;
+ gboolean ret;
+
+ g_return_val_if_fail (label != NULL, FALSE);
+ g_return_val_if_fail (value != 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);
+
+ /* Warnings raised already */
+ if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, FALSE))
+ return FALSE;
+
+ sync = _secret_sync_new ();
+ g_main_context_push_thread_default (sync->context);
+
+ secret_password_storev_binary (schema, attributes, collection, label, value,
+ cancellable, _secret_sync_on_result, sync);
+
+ g_main_loop_run (sync->loop);
+
+ ret = secret_password_store_finish (sync->result, error);
+
+ g_main_context_pop_thread_default (sync->context);
+ _secret_sync_free (sync);
+
+ return ret;
+}
+
+/**
* secret_password_lookup: (skip)
* @schema: the schema for the attributes
* @cancellable: optional cancellation object
@@ -348,7 +558,7 @@ secret_password_lookup (const SecretSchema *schema,
/**
* secret_password_lookupv: (rename-to secret_password_lookup)
- * @schema: the schema for attributes
+ * @schema: (nullable): the schema for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @cancellable: optional cancellation object
* @callback: called when the operation completes
@@ -369,12 +579,11 @@ secret_password_lookupv (const SecretSchema *schema,
GAsyncReadyCallback callback,
gpointer user_data)
{
- g_return_if_fail (schema != NULL);
g_return_if_fail (attributes != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
/* Warnings raised already */
- if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
+ if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
return;
secret_service_lookup (NULL, schema, attributes,
@@ -407,6 +616,27 @@ secret_password_lookup_nonpageable_finish (GAsyncResult *result,
}
/**
+ * secret_password_lookup_binary_finish: (skip)
+ * @result: the asynchronous result passed to the callback
+ * @error: location to place an error on failure
+ *
+ * Finish an asynchronous operation to lookup a password in the secret service.
+ *
+ * Returns: (transfer full): a newly allocated #SecretValue, which should be
+ * released with secret_value_unref(), or %NULL if no secret found
+ *
+ * Since: 0.19.0
+ */
+SecretValue *
+secret_password_lookup_binary_finish (GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ return secret_service_lookup_finish (NULL, result, error);
+}
+
+/**
* secret_password_lookup_finish:
* @result: the asynchronous result passed to the callback
* @error: location to place an error on failure
@@ -537,7 +767,7 @@ secret_password_lookup_nonpageable_sync (const SecretSchema *schema,
/**
* secret_password_lookupv_nonpageable_sync: (skip)
- * @schema: the schema for attributes
+ * @schema: (nullable): the schema for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @cancellable: optional cancellation object
* @error: location to place an error on failure
@@ -563,13 +793,12 @@ secret_password_lookupv_nonpageable_sync (const SecretSchema *schema,
SecretSync *sync;
gchar *password;
- g_return_val_if_fail (schema != NULL, NULL);
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);
/* Warnings raised already */
- if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
+ if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
return FALSE;
sync = _secret_sync_new ();
@@ -589,8 +818,111 @@ secret_password_lookupv_nonpageable_sync (const SecretSchema *schema,
}
/**
+ * secret_password_lookup_binary_sync: (skip)
+ * @schema: the schema for the attributes
+ * @cancellable: optional cancellation object
+ * @error: location to place an error on failure
+ * @...: the attribute keys and values, terminated with %NULL
+ *
+ * Lookup a password in the secret service.
+ *
+ * This is similar to secret_password_lookup_sync(), but returns a
+ * #SecretValue instead of a null-terminated password.
+ *
+ * This method may block indefinitely and should not be used in user interface
+ * threads.
+ *
+ * Returns: (transfer full): a newly allocated #SecretValue, which should be
+ * released with secret_value_unref(), or %NULL if no secret found
+ *
+ * Since: 0.19.0
+ */
+SecretValue *
+secret_password_lookup_binary_sync (const SecretSchema *schema,
+ GCancellable *cancellable,
+ GError **error,
+ ...)
+{
+ GHashTable *attributes;
+ SecretValue *value;
+ 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 = secret_attributes_buildv (schema, va);
+ va_end (va);
+
+ /* Precondition failed, already warned */
+ if (!attributes)
+ return NULL;
+
+ value = secret_password_lookupv_binary_sync (schema, attributes,
+ cancellable, error);
+
+ g_hash_table_unref (attributes);
+
+ return value;
+}
+
+/**
+ * secret_password_lookupv_binary_sync: (skip)
+ * @schema: (nullable): the schema for attributes
+ * @attributes: (element-type utf8 utf8): the attribute keys and values
+ * @cancellable: optional cancellation object
+ * @error: location to place an error on failure
+ *
+ * Lookup a password in the secret service.
+ *
+ * This is similar to secret_password_lookupv_sync(), but returns a
+ * #SecretValue instead of a null-terminated password.
+ *
+ * This method may block indefinitely and should not be used in user interface
+ * threads.
+ *
+ * Returns: (transfer full): a newly allocated #SecretValue, which should be
+ * released with secret_value_unref(), or %NULL if no secret found
+ *
+ * Since: 0.19.0
+ */
+SecretValue *
+secret_password_lookupv_binary_sync (const SecretSchema *schema,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SecretSync *sync;
+ SecretValue *value;
+
+ 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);
+
+ /* Warnings raised already */
+ if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
+ return FALSE;
+
+ sync = _secret_sync_new ();
+ g_main_context_push_thread_default (sync->context);
+
+ secret_password_lookupv (schema, attributes, cancellable,
+ _secret_sync_on_result, sync);
+
+ g_main_loop_run (sync->loop);
+
+ value = secret_password_lookup_binary_finish (sync->result, error);
+
+ g_main_context_pop_thread_default (sync->context);
+ _secret_sync_free (sync);
+
+ return value;
+}
+
+/**
* secret_password_lookupv_sync: (rename-to secret_password_lookup_sync)
- * @schema: the schema for attributes
+ * @schema: (nullable): the schema for attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @cancellable: optional cancellation object
* @error: location to place an error on failure
@@ -616,13 +948,12 @@ secret_password_lookupv_sync (const SecretSchema *schema,
SecretSync *sync;
gchar *string;
- g_return_val_if_fail (schema != NULL, NULL);
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);
/* Warnings raised already */
- if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
+ if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
return FALSE;
sync = _secret_sync_new ();
@@ -690,7 +1021,7 @@ secret_password_clear (const SecretSchema *schema,
/**
* secret_password_clearv: (rename-to secret_password_clear)
- * @schema: the schema for the attributes
+ * @schema: (nullable): the schema for the attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @cancellable: optional cancellation object
* @callback: called when the operation completes
@@ -711,12 +1042,11 @@ secret_password_clearv (const SecretSchema *schema,
GAsyncReadyCallback callback,
gpointer user_data)
{
- g_return_if_fail (schema != NULL);
g_return_if_fail (attributes != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
/* Warnings raised already */
- if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
+ if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
return;
secret_service_clear (NULL, schema, attributes,
@@ -794,7 +1124,7 @@ secret_password_clear_sync (const SecretSchema* schema,
/**
* secret_password_clearv_sync: (rename-to secret_password_clear_sync)
- * @schema: the schema for the attributes
+ * @schema: (nullable): the schema for the attributes
* @attributes: (element-type utf8 utf8): the attribute keys and values
* @cancellable: optional cancellation object
* @error: location to place an error on failure
@@ -819,13 +1149,12 @@ secret_password_clearv_sync (const SecretSchema *schema,
SecretSync *sync;
gboolean result;
- g_return_val_if_fail (schema != 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);
/* Warnings raised already */
- if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
+ if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
return FALSE;
sync = _secret_sync_new ();
@@ -845,6 +1174,223 @@ secret_password_clearv_sync (const SecretSchema *schema,
}
/**
+ * secret_password_search: (skip)
+ * @schema: the schema for the attributes
+ * @flags: search option flags
+ * @cancellable: optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to be passed to the callback
+ * @...: the attribute keys and values, terminated with %NULL
+ *
+ * Search for items in the secret service.
+ *
+ * The variable argument list should contain pairs of a) The attribute name as
+ * a null-terminated string, followed by b) attribute value, either a character
+ * string, an int number, or a gboolean value, as defined in the password
+ * @schema. The list of attribtues should be terminated with a %NULL.
+ *
+ * This method will return immediately and complete asynchronously.
+ *
+ * Since: 0.19.0
+ */
+void
+secret_password_search (const SecretSchema *schema,
+ SecretSearchFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ ...)
+{
+ 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 = secret_attributes_buildv (schema, va);
+ va_end (va);
+
+ /* Precondition failed, already warned */
+ if (!attributes)
+ return;
+
+ secret_password_searchv (schema, attributes, flags, cancellable,
+ callback, user_data);
+
+ g_hash_table_unref (attributes);
+}
+
+/**
+ * secret_password_searchv: (rename-to secret_password_search)
+ * @schema: (nullable): the schema for attributes
+ * @attributes: (element-type utf8 utf8): the attribute keys and values
+ * @flags: search option flags
+ * @cancellable: optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to be passed to the callback
+ *
+ * Search for items in the secret service.
+ *
+ * The @attributes should be a set of key and value string pairs.
+ *
+ * This method will return immediately and complete asynchronously.
+ *
+ * Since: 0.19.0
+ */
+void
+secret_password_searchv (const SecretSchema *schema,
+ GHashTable *attributes,
+ SecretSearchFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (attributes != NULL);
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ /* Warnings raised already */
+ if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
+ return;
+
+ secret_service_search (NULL, schema, attributes, flags,
+ cancellable, callback, user_data);
+}
+
+/**
+ * secret_password_search_finish:
+ * @result: the asynchronous result passed to the callback
+ * @error: location to place an error on failure
+ *
+ * Finish an asynchronous operation to search for items in the secret service.
+ *
+ * Returns: (transfer full) (element-type Secret.Retrievable): a list of
+ * #SecretRetrievable containing attributes of the matched items
+ *
+ * Since: 0.19.0
+ */
+GList *
+secret_password_search_finish (GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ return secret_service_search_finish (NULL, result, error);
+}
+
+/**
+ * secret_password_search_sync: (skip)
+ * @schema: the schema for the attributes
+ * @flags: search option flags
+ * @cancellable: optional cancellation object
+ * @error: location to place an error on failure
+ * @...: the attribute keys and values, terminated with %NULL
+ *
+ * Search for items in the secret service.
+ *
+ * The variable argument list should contain pairs of a) The attribute name as
+ * a null-terminated string, followed by b) attribute value, either a character
+ * string, an int number, or a gboolean value, as defined in the password
+ * @schema. The list of attributes should be terminated with a %NULL.
+ *
+ * If no secret is found then %NULL is returned.
+ *
+ * This method may block indefinitely and should not be used in user interface
+ * threads.
+ *
+ * Returns: (transfer full) (element-type Secret.Retrievable): a list of
+ * #SecretRetrievable containing attributes of the matched items
+ *
+ * Since: 0.19.0
+ */
+GList *
+secret_password_search_sync (const SecretSchema *schema,
+ SecretSearchFlags flags,
+ GCancellable *cancellable,
+ GError **error,
+ ...)
+{
+ GHashTable *attributes;
+ GList *items;
+ 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 = secret_attributes_buildv (schema, va);
+ va_end (va);
+
+ /* Precondition failed, already warned */
+ if (!attributes)
+ return NULL;
+
+ items = secret_password_searchv_sync (schema, attributes, flags,
+ cancellable, error);
+
+ g_hash_table_unref (attributes);
+
+ return items;
+}
+
+/**
+ * secret_password_searchv_sync: (rename-to secret_password_search_sync)
+ * @schema: (nullable): the schema for attributes
+ * @attributes: (element-type utf8 utf8): the attribute keys and values
+ * @flags: search option flags
+ * @cancellable: optional cancellation object
+ * @error: location to place an error on failure
+ *
+ * Search for items in the secret service.
+ *
+ * The @attributes should be a set of key and value string pairs.
+ *
+ * If no secret is found then %NULL is returned.
+ *
+ * This method may block indefinitely and should not be used in user interface
+ * threads.
+ *
+ * Returns: (transfer full) (element-type Secret.Retrievable): a list of
+ * #SecretRetrievable containing attributes of the matched items
+ *
+ * Since: 0.19.0
+ */
+GList *
+secret_password_searchv_sync (const SecretSchema *schema,
+ GHashTable *attributes,
+ SecretSearchFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SecretSync *sync;
+ GList *items;
+
+ 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);
+
+ /* Warnings raised already */
+ if (schema != NULL && !_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
+ return NULL;
+
+ sync = _secret_sync_new ();
+ g_main_context_push_thread_default (sync->context);
+
+ secret_password_searchv (schema, attributes, flags, cancellable,
+ _secret_sync_on_result, sync);
+
+ g_main_loop_run (sync->loop);
+
+ items = secret_password_search_finish (sync->result, error);
+
+ g_main_context_pop_thread_default (sync->context);
+ _secret_sync_free (sync);
+
+ return items;
+}
+
+/**
* secret_password_free: (skip)
* @password: (allow-none): password to free
*
diff --git a/libsecret/secret-password.h b/libsecret/secret-password.h
index d47abb3..0719317 100644
--- a/libsecret/secret-password.h
+++ b/libsecret/secret-password.h
@@ -25,8 +25,9 @@ G_BEGIN_DECLS
#include "secret-schema.h"
#include "secret-types.h"
+#include "secret-value.h"
-void secret_password_store (const SecretSchema *schema,
+void secret_password_store (const SecretSchema *schema,
const gchar *collection,
const gchar *label,
const gchar *password,
@@ -35,7 +36,7 @@ void secret_password_store (const SecretSchema *sche
gpointer user_data,
...) G_GNUC_NULL_TERMINATED;
-void secret_password_storev (const SecretSchema *schema,
+void secret_password_storev (const SecretSchema *schema,
GHashTable *attributes,
const gchar *collection,
const gchar *label,
@@ -44,10 +45,28 @@ void secret_password_storev (const SecretSchema *sche
GAsyncReadyCallback callback,
gpointer user_data);
-gboolean secret_password_store_finish (GAsyncResult *result,
+void secret_password_store_binary (const SecretSchema *schema,
+ const gchar *collection,
+ const gchar *label,
+ SecretValue *value,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ ...);
+
+void secret_password_storev_binary (const SecretSchema *schema,
+ GHashTable *attributes,
+ const gchar *collection,
+ const gchar *label,
+ SecretValue *value,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean secret_password_store_finish (GAsyncResult *result,
GError **error);
-gboolean secret_password_store_sync (const SecretSchema *schema,
+gboolean secret_password_store_sync (const SecretSchema *schema,
const gchar *collection,
const gchar *label,
const gchar *password,
@@ -55,7 +74,7 @@ gboolean secret_password_store_sync (const SecretSchema *sche
GError **error,
...) G_GNUC_NULL_TERMINATED;
-gboolean secret_password_storev_sync (const SecretSchema *schema,
+gboolean secret_password_storev_sync (const SecretSchema *schema,
GHashTable *attributes,
const gchar *collection,
const gchar *label,
@@ -63,72 +82,127 @@ gboolean secret_password_storev_sync (const SecretSchema *sche
GCancellable *cancellable,
GError **error);
-void secret_password_lookup (const SecretSchema *schema,
+gboolean secret_password_store_binary_sync (const SecretSchema *schema,
+ const gchar *collection,
+ const gchar *label,
+ SecretValue *value,
+ GCancellable *cancellable,
+ GError **error,
+ ...);
+
+gboolean secret_password_storev_binary_sync (const SecretSchema *schema,
+ GHashTable *attributes,
+ const gchar *collection,
+ const gchar *label,
+ SecretValue *value,
+ GCancellable *cancellable,
+ GError **error);
+
+void secret_password_lookup (const SecretSchema *schema,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
...) G_GNUC_NULL_TERMINATED;
-void secret_password_lookupv (const SecretSchema *schema,
+void secret_password_lookupv (const SecretSchema *schema,
GHashTable *attributes,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
-gchar * secret_password_lookup_finish (GAsyncResult *result,
+gchar * secret_password_lookup_finish (GAsyncResult *result,
GError **error);
-gchar * secret_password_lookup_nonpageable_finish (GAsyncResult *result,
- GError **error);
+gchar * secret_password_lookup_nonpageable_finish (GAsyncResult *result,
+ GError **error);
+SecretValue *secret_password_lookup_binary_finish (GAsyncResult *result,
+ GError **error);
-gchar * secret_password_lookup_sync (const SecretSchema *schema,
+gchar * secret_password_lookup_sync (const SecretSchema *schema,
GCancellable *cancellable,
GError **error,
...) G_GNUC_NULL_TERMINATED;
-gchar * secret_password_lookup_nonpageable_sync (const SecretSchema *schema,
+gchar * secret_password_lookup_nonpageable_sync (const SecretSchema *schema,
GCancellable *cancellable,
GError **error,
...);
+SecretValue *secret_password_lookup_binary_sync (const SecretSchema *schema,
+ GCancellable *cancellable,
+ GError **error,
+ ...);
-gchar * secret_password_lookupv_sync (const SecretSchema *schema,
+gchar * secret_password_lookupv_sync (const SecretSchema *schema,
GHashTable *attributes,
GCancellable *cancellable,
GError **error);
-gchar * secret_password_lookupv_nonpageable_sync (const SecretSchema *schema,
+gchar * secret_password_lookupv_nonpageable_sync (const SecretSchema *schema,
GHashTable *attributes,
GCancellable *cancellable,
GError **error);
+SecretValue *secret_password_lookupv_binary_sync (const SecretSchema *schema,
+ GHashTable *attributes,
+ GCancellable *cancellable,
+ GError **error);
-void secret_password_clear (const SecretSchema *schema,
+void secret_password_clear (const SecretSchema *schema,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
...) G_GNUC_NULL_TERMINATED;
-void secret_password_clearv (const SecretSchema *schema,
+void secret_password_clearv (const SecretSchema *schema,
GHashTable *attributes,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
-gboolean secret_password_clear_finish (GAsyncResult *result,
+gboolean secret_password_clear_finish (GAsyncResult *result,
GError **error);
-gboolean secret_password_clear_sync (const SecretSchema* schema,
+gboolean secret_password_clear_sync (const SecretSchema* schema,
GCancellable *cancellable,
GError **error,
...) G_GNUC_NULL_TERMINATED;
-gboolean secret_password_clearv_sync (const SecretSchema *schema,
+gboolean secret_password_clearv_sync (const SecretSchema *schema,
GHashTable *attributes,
GCancellable *cancellable,
GError **error);
-void secret_password_free (gchar *password);
+void secret_password_search (const SecretSchema *schema,
+ SecretSearchFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ ...) G_GNUC_NULL_TERMINATED;
+
+void secret_password_searchv (const SecretSchema *schema,
+ GHashTable *attributes,
+ SecretSearchFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GList * secret_password_search_sync (const SecretSchema *schema,
+ SecretSearchFlags flags,
+ GCancellable *cancellable,
+ GError **error,
+ ...) G_GNUC_NULL_TERMINATED;
+
+GList * secret_password_searchv_sync (const SecretSchema *schema,
+ GHashTable *attributes,
+ SecretSearchFlags flags,
+ GCancellable *cancellable,
+ GError **error);
+
+GList * secret_password_search_finish (GAsyncResult *result,
+ GError **error);
+
+void secret_password_free (gchar *password);
-void secret_password_wipe (gchar *password);
+void secret_password_wipe (gchar *password);
G_END_DECLS
diff --git a/libsecret/secret-retrievable.c b/libsecret/secret-retrievable.c
new file mode 100644
index 0000000..caa063b
--- /dev/null
+++ b/libsecret/secret-retrievable.c
@@ -0,0 +1,307 @@
+/* libsecret - GLib wrapper for Secret Service
+ *
+ * Copyright 2019 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ *
+ * Author: Daiki Ueno
+ */
+
+#include "config.h"
+
+#include "secret-retrievable.h"
+#include "secret-private.h"
+
+/**
+ * SECTION:secret-retrievable
+ * @title: SecretRetrievable
+ * @short_description: A read-only secret item
+ *
+ * #SecretRetrievable provides a read-only view of a secret item
+ * stored in the Secret Service.
+ *
+ * Each item has a value, represented by a #SecretValue, which can be
+ * retrieved by secret_retrievable_retrieve_secret() and
+ * secret_retrievable_retrieve_secret_finish().
+ *
+ * Stability: Stable
+ */
+
+/**
+ * SecretRetrievable:
+ *
+ * An object representing a read-only view of a secret item in the
+ * Secret Service.
+ *
+ * Since: 0.19.0
+ */
+
+/**
+ * SecretRetrievableInterface:
+ * @parent_iface: the parent interface
+ * @retrieve_secret: implementation of secret_retrievable_retrieve_secret(),
+ * required
+ * @retrieve_secret_finish: implementation of
+ * secret_retrievable_retrieve_secret_finish(), required
+ *
+ * The interface for #SecretRetrievable.
+ *
+ * Since: 0.19.0
+ */
+
+G_DEFINE_INTERFACE (SecretRetrievable, secret_retrievable, G_TYPE_OBJECT);
+
+static void
+secret_retrievable_default_init (SecretRetrievableInterface *iface)
+{
+ /**
+ * SecretRetrievable:attributes: (type GLib.HashTable(utf8,utf8)) (transfer full)
+ *
+ * The attributes set on this item. Attributes are used to locate an
+ * item. They are not guaranteed to be stored or transferred securely.
+ *
+ * Since: 0.19.0
+ */
+ g_object_interface_install_property (iface,
+ g_param_spec_boxed ("attributes", "Attributes", "Item attributes",
+ G_TYPE_HASH_TABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * SecretRetrievable:label:
+ *
+ * The human readable label for the item.
+ *
+ * Since: 0.19.0
+ */
+ g_object_interface_install_property (iface,
+ g_param_spec_string ("label", "Label", "Item label",
+ NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * SecretRetrievable:created:
+ *
+ * The date and time (in seconds since the UNIX epoch) that this
+ * item was created.
+ *
+ * Since: 0.19.0
+ */
+ g_object_interface_install_property (iface,
+ g_param_spec_uint64 ("created", "Created", "Item creation date",
+ 0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * SecretRetrievable:modified:
+ *
+ * The date and time (in seconds since the UNIX epoch) that this
+ * item was last modified.
+ *
+ * Since: 0.19.0
+ */
+ g_object_interface_install_property (iface,
+ g_param_spec_uint64 ("modified", "Modified", "Item modified date",
+ 0UL, G_MAXUINT64, 0UL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+/**
+ * secret_retrievable_retrieve_secret:
+ * @self: a retrievable object
+ * @cancellable: (nullable): optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to pass to the callback
+ *
+ * Retrieve the secret value of this object.
+ *
+ * Each retrievable object has a single secret which might be a
+ * password or some other secret binary value.
+ *
+ * This function returns immediately and completes asynchronously.
+ *
+ * Since: 0.19.0
+ */
+void
+secret_retrievable_retrieve_secret (SecretRetrievable *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ SecretRetrievableInterface *iface;
+
+ g_return_if_fail (SECRET_IS_RETRIEVABLE (self));
+ iface = SECRET_RETRIEVABLE_GET_IFACE (self);
+ g_return_if_fail (iface->retrieve_secret != NULL);
+ iface->retrieve_secret (self, cancellable, callback, user_data);
+}
+
+/**
+ * secret_retrievable_retrieve_secret_finish:
+ * @self: a retrievable object
+ * @result: asynchronous result passed to callback
+ * @error: location to place error on failure
+ *
+ * Complete asynchronous operation to retrieve the secret value of this object.
+ *
+ * Returns: (transfer full) (nullable): the secret value which should be
+ * released with secret_value_unref(), or %NULL
+ *
+ * Since: 0.19.0
+ */
+SecretValue *
+secret_retrievable_retrieve_secret_finish (SecretRetrievable *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ SecretRetrievableInterface *iface;
+
+ g_return_val_if_fail (SECRET_IS_RETRIEVABLE (self), NULL);
+ iface = SECRET_RETRIEVABLE_GET_IFACE (self);
+ g_return_val_if_fail (iface->retrieve_secret_finish != NULL, NULL);
+ return iface->retrieve_secret_finish (self, result, error);
+}
+
+/**
+ * secret_retrievable_retrieve_secret_sync:
+ * @self: a retrievable object
+ * @cancellable: (nullable): optional cancellation object
+ * @error: location to place error on failure
+ *
+ * Retrieve the secret value of this object synchronously.
+ *
+ * Each retrievable object has a single secret which might be a
+ * password or some other secret binary value.
+ *
+ * This method may block indefinitely and should not be used in user interface
+ * threads.
+ *
+ * Returns: (transfer full) (nullable): the secret value which should be
+ * released with secret_value_unref(), or %NULL
+ *
+ * Since: 0.19.0
+ */
+SecretValue *
+secret_retrievable_retrieve_secret_sync (SecretRetrievable *self,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SecretSync *sync;
+ SecretValue *value;
+
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ sync = _secret_sync_new ();
+ g_main_context_push_thread_default (sync->context);
+
+ secret_retrievable_retrieve_secret (self,
+ cancellable,
+ _secret_sync_on_result, sync);
+
+ g_main_loop_run (sync->loop);
+
+ value = secret_retrievable_retrieve_secret_finish (self,
+ sync->result,
+ error);
+
+ g_main_context_pop_thread_default (sync->context);
+ _secret_sync_free (sync);
+
+ return value;
+}
+
+/**
+ * secret_retrievable_get_attributes:
+ * @self: a retrievable object
+ *
+ * Get the attributes of this object.
+ *
+ * The attributes are a mapping of string keys to string values.
+ * Attributes are used to search for items. Attributes are not stored
+ * or transferred securely by the secret service.
+ *
+ * Do not modify the attribute returned by this method.
+ *
+ * Returns: (transfer full) (element-type utf8 utf8): a new reference
+ * to the attributes, which should not be modified, and
+ * released with g_hash_table_unref()
+ *
+ * Since: 0.19.0
+ */
+GHashTable *
+secret_retrievable_get_attributes (SecretRetrievable *self)
+{
+ GHashTable *value;
+
+ g_return_val_if_fail (SECRET_IS_RETRIEVABLE (self), NULL);
+
+ g_object_get (G_OBJECT (self), "attributes", &value, NULL);
+ return value;
+}
+
+/**
+ * secret_retrievable_get_label:
+ * @self: a retrievable object
+ *
+ * Get the label of this item.
+ *
+ * Returns: (transfer full): the label, which should be freed with g_free()
+ *
+ * Since: 0.19.0
+ */
+gchar *
+secret_retrievable_get_label (SecretRetrievable *self)
+{
+ gchar *value;
+
+ g_return_val_if_fail (SECRET_IS_RETRIEVABLE (self), NULL);
+
+ g_object_get (G_OBJECT (self), "label", &value, NULL);
+ return value;
+}
+
+/**
+ * secret_retrievable_get_created:
+ * @self: a retrievable object
+ *
+ * Get the created date and time of the object. The return value is
+ * the number of seconds since the unix epoch, January 1st 1970.
+ *
+ * Returns: the created date and time
+ *
+ * Since: 0.19.0
+ */
+guint64
+secret_retrievable_get_created (SecretRetrievable *self)
+{
+ guint64 value;
+
+ g_return_val_if_fail (SECRET_IS_RETRIEVABLE (self), 0);
+
+ g_object_get (G_OBJECT (self), "created", &value, NULL);
+ return value;
+}
+
+/**
+ * secret_retrievable_get_modified:
+ * @self: a retrievable object
+ *
+ * Get the modified date and time of the object. The return value is
+ * the number of seconds since the unix epoch, January 1st 1970.
+ *
+ * Returns: the modified date and time
+ *
+ * Since: 0.19.0
+ */
+guint64
+secret_retrievable_get_modified (SecretRetrievable *self)
+{
+ guint64 value;
+
+ g_return_val_if_fail (SECRET_IS_RETRIEVABLE (self), 0);
+
+ g_object_get (G_OBJECT (self), "modified", &value, NULL);
+ return value;
+}
diff --git a/libsecret/secret-retrievable.h b/libsecret/secret-retrievable.h
new file mode 100644
index 0000000..8b66cef
--- /dev/null
+++ b/libsecret/secret-retrievable.h
@@ -0,0 +1,64 @@
+/* libsecret - GLib wrapper for Secret Service
+ *
+ * Copyright 2019 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ *
+ * Author: Daiki Ueno
+ */
+
+#if !defined (__SECRET_INSIDE_HEADER__) && !defined (SECRET_COMPILATION)
+#error "Only <libsecret/secret.h> can be included directly."
+#endif
+
+#ifndef __SECRET_RETRIEVABLE_H__
+#define __SECRET_RETRIEVABLE_H__
+
+#include <glib-object.h>
+#include "secret-value.h"
+
+G_BEGIN_DECLS
+
+#define SECRET_TYPE_RETRIEVABLE secret_retrievable_get_type ()
+G_DECLARE_INTERFACE (SecretRetrievable, secret_retrievable, SECRET, RETRIEVABLE, GObject)
+
+struct _SecretRetrievableInterface
+{
+ GTypeInterface parent_iface;
+
+ void (*retrieve_secret) (SecretRetrievable *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ SecretValue *(*retrieve_secret_finish) (SecretRetrievable *self,
+ GAsyncResult *result,
+ GError **error);
+};
+
+void secret_retrievable_retrieve_secret (SecretRetrievable *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+SecretValue *secret_retrievable_retrieve_secret_finish (SecretRetrievable *self,
+ GAsyncResult *result,
+ GError **error);
+
+SecretValue *secret_retrievable_retrieve_secret_sync (SecretRetrievable *self,
+ GCancellable *cancellable,
+ GError **error);
+
+GHashTable *secret_retrievable_get_attributes (SecretRetrievable *self);
+gchar *secret_retrievable_get_label (SecretRetrievable *self);
+guint64 secret_retrievable_get_created (SecretRetrievable *self);
+guint64 secret_retrievable_get_modified (SecretRetrievable *self);
+
+
+G_END_DECLS
+
+#endif /* __SECRET_RETRIEVABLE_H__ */
diff --git a/libsecret/secret-service.h b/libsecret/secret-service.h
index 4c3a827..44cbc1e 100644
--- a/libsecret/secret-service.h
+++ b/libsecret/secret-service.h
@@ -35,13 +35,6 @@ typedef enum {
SECRET_SERVICE_LOAD_COLLECTIONS = 1 << 2,
} SecretServiceFlags;
-typedef enum {
- SECRET_SEARCH_NONE = 0,
- SECRET_SEARCH_ALL = 1 << 1,
- SECRET_SEARCH_UNLOCK = 1 << 2,
- SECRET_SEARCH_LOAD_SECRETS = 1 << 3,
-} SecretSearchFlags;
-
#define SECRET_TYPE_SERVICE (secret_service_get_type ())
#define SECRET_SERVICE(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), SECRET_TYPE_SERVICE, SecretService))
#define SECRET_SERVICE_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), SECRET_TYPE_SERVICE, SecretServiceClass))
diff --git a/libsecret/secret-types.h b/libsecret/secret-types.h
index 708c53f..cbbd3b1 100644
--- a/libsecret/secret-types.h
+++ b/libsecret/secret-types.h
@@ -38,6 +38,13 @@ typedef enum {
#define SECRET_COLLECTION_SESSION "session"
+typedef enum {
+ SECRET_SEARCH_NONE = 0,
+ SECRET_SEARCH_ALL = 1 << 1,
+ SECRET_SEARCH_UNLOCK = 1 << 2,
+ SECRET_SEARCH_LOAD_SECRETS = 1 << 3,
+} SecretSearchFlags;
+
G_END_DECLS
#endif /* __G_SERVICE_H___ */
diff --git a/libsecret/secret-value.c b/libsecret/secret-value.c
index ca891cb..63464cd 100644
--- a/libsecret/secret-value.c
+++ b/libsecret/secret-value.c
@@ -256,39 +256,67 @@ is_password_value (SecretValue *value)
return FALSE;
}
+/**
+ * secret_value_unref_to_password:
+ * @value: the value
+ * @length: the length of the secret
+ *
+ * Unreference a #SecretValue and steal the secret data in
+ * #SecretValue as nonpageable memory.
+ *
+ * Returns: (transfer full): a new password string stored in nonpageable memory
+ * which must be freed with secret_password_free() when done
+ *
+ * Since: 0.19.0
+ */
gchar *
-_secret_value_unref_to_password (SecretValue *value)
+secret_value_unref_to_password (SecretValue *value,
+ gsize *length)
{
SecretValue *val = value;
gchar *result;
g_return_val_if_fail (value != NULL, NULL);
- if (!is_password_value (value)) {
- secret_value_unref (value);
- return NULL;
- }
-
if (g_atomic_int_dec_and_test (&val->refs)) {
if (val->destroy == egg_secure_free) {
result = val->secret;
+ if (length)
+ *length = val->length;
} else {
result = egg_secure_strndup (val->secret, val->length);
if (val->destroy)
(val->destroy) (val->secret);
+ if (length)
+ *length = val->length;
}
g_free (val->content_type);
g_slice_free (SecretValue, val);
} else {
result = egg_secure_strndup (val->secret, val->length);
+ if (length)
+ *length = val->length;
}
return result;
}
gchar *
+_secret_value_unref_to_password (SecretValue *value)
+{
+ g_return_val_if_fail (value != NULL, NULL);
+
+ if (!is_password_value (value)) {
+ secret_value_unref (value);
+ return NULL;
+ }
+
+ return secret_value_unref_to_password (value, NULL);
+}
+
+gchar *
_secret_value_unref_to_string (SecretValue *value)
{
SecretValue *val = value;
diff --git a/libsecret/secret-value.h b/libsecret/secret-value.h
index 43b0e09..7699c08 100644
--- a/libsecret/secret-value.h
+++ b/libsecret/secret-value.h
@@ -51,6 +51,9 @@ SecretValue * secret_value_ref (SecretValue *value);
void secret_value_unref (gpointer value);
+gchar * secret_value_unref_to_password (SecretValue *value,
+ gsize *length);
+
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SecretValue, secret_value_unref)
G_END_DECLS
diff --git a/libsecret/secret.h b/libsecret/secret.h
index 8d11324..7e6e7c6 100644
--- a/libsecret/secret.h
+++ b/libsecret/secret.h
@@ -25,6 +25,7 @@
#include <libsecret/secret-item.h>
#include <libsecret/secret-password.h>
#include <libsecret/secret-prompt.h>
+#include <libsecret/secret-retrievable.h>
#include <libsecret/secret-schema.h>
#include <libsecret/secret-schemas.h>
#include <libsecret/secret-service.h>
diff --git a/libsecret/test-password.c b/libsecret/test-password.c
index cbfb561..f20a31b 100644
--- a/libsecret/test-password.c
+++ b/libsecret/test-password.c
@@ -357,6 +357,160 @@ test_clear_no_name (Test *test,
}
static void
+free_attributes (gpointer data,
+ gpointer user_data)
+{
+ g_object_unref ((GObject *)data);
+}
+
+static void
+test_search_sync (Test *test,
+ gconstpointer used)
+{
+ GList *items;
+ GError *error = NULL;
+
+ items = secret_password_search_sync (&MOCK_SCHEMA, SECRET_SEARCH_ALL,
+ NULL, &error,
+ "even", FALSE,
+ "string", "one",
+ "number", 1,
+ NULL);
+
+ g_assert_no_error (error);
+ g_assert_cmpint (g_list_length (items), ==, 1);
+
+ g_list_foreach (items, free_attributes, NULL);
+ g_list_free (items);
+}
+
+static void
+test_search_async (Test *test,
+ gconstpointer used)
+{
+ GAsyncResult *result = NULL;
+ GError *error = NULL;
+ GList *items;
+
+ secret_password_search (&MOCK_SCHEMA, SECRET_SEARCH_ALL,
+ NULL, on_complete_get_result, &result,
+ "even", FALSE,
+ "string", "one",
+ "number", 1,
+ NULL);
+ g_assert (result == NULL);
+
+ egg_test_wait ();
+
+ items = secret_password_search_finish (result, &error);
+ g_assert_no_error (error);
+ g_object_unref (result);
+
+ g_assert_cmpint (g_list_length (items), ==, 1);
+
+ g_list_foreach (items, free_attributes, NULL);
+ g_list_free (items);
+}
+
+static void
+test_search_no_name (Test *test,
+ gconstpointer used)
+{
+ GError *error = NULL;
+ GList *items;
+
+ /* should return null, because nothing with mock schema and 5 */
+ items = secret_password_search_sync (&MOCK_SCHEMA, SECRET_SEARCH_ALL,
+ NULL, &error,
+ "number", 5,
+ NULL);
+ g_assert_no_error (error);
+ g_assert (items == NULL);
+
+ /* should return an item, because we have a prime schema with 5, and flags not to match name */
+ items = secret_password_search_sync (&NO_NAME_SCHEMA, SECRET_SEARCH_ALL,
+ NULL, &error,
+ "number", 5,
+ NULL);
+
+ g_assert_no_error (error);
+ g_assert_cmpint (g_list_length (items), ==, 1);
+
+ g_list_foreach (items, free_attributes, NULL);
+ g_list_free (items);
+}
+
+static void
+test_binary_sync (Test *test,
+ gconstpointer used)
+{
+ const gchar *collection_path = "/org/freedesktop/secrets/collection/english";
+ GError *error = NULL;
+ SecretValue *value;
+ gboolean ret;
+
+ value = secret_value_new ("the password", -1, "text/plain");
+ ret = secret_password_store_binary_sync (&MOCK_SCHEMA, collection_path,
+ "Label here", value, NULL, &error,
+ "even", TRUE,
+ "string", "twelve",
+ "number", 12,
+ NULL);
+
+ g_assert_no_error (error);
+ g_assert_true (ret);
+ secret_value_unref (value);
+
+ value = secret_password_lookup_binary_sync (&MOCK_SCHEMA, NULL, &error,
+ "string", "twelve",
+ NULL);
+
+ g_assert_no_error (error);
+ g_assert_cmpstr (secret_value_get_text (value), ==, "the password");
+
+ secret_value_unref (value);
+}
+
+static void
+test_binary_async (Test *test,
+ gconstpointer used)
+{
+ const gchar *collection_path = "/org/freedesktop/secrets/collection/english";
+ GAsyncResult *result = NULL;
+ GError *error = NULL;
+ SecretValue *value;
+ gboolean ret;
+
+ value = secret_value_new ("the password", -1, "text/plain");
+ secret_password_store_binary (&MOCK_SCHEMA, collection_path, "Label here",
+ value, NULL, on_complete_get_result, &result,
+ "even", TRUE,
+ "string", "twelve",
+ "number", 12,
+ NULL);
+ g_assert_null (result);
+ secret_value_unref (value);
+
+ egg_test_wait ();
+
+ ret = secret_password_store_finish (result, &error);
+ g_assert_no_error (error);
+ g_assert_true (ret);
+ g_object_unref (result);
+
+ value = secret_password_lookup_binary_sync (&MOCK_SCHEMA, NULL, &error,
+ "string", "twelve",
+ NULL);
+
+ g_assert_no_error (error);
+ g_assert_nonnull (value);
+
+ g_assert_cmpstr (secret_value_get_text (value), ==, "the password");
+
+ secret_value_unref (value);
+}
+
+static void
test_password_free_null (void)
{
secret_password_free (NULL);
@@ -380,6 +534,13 @@ main (int argc, char **argv)
g_test_add ("/password/delete-async", Test, "mock-service-delete.py", setup, test_delete_async, teardown);
g_test_add ("/password/clear-no-name", Test, "mock-service-delete.py", setup, test_clear_no_name, teardown);
+ g_test_add ("/password/search-sync", Test, "mock-service-normal.py", setup, test_search_sync, teardown);
+ g_test_add ("/password/search-async", Test, "mock-service-normal.py", setup, test_search_async, teardown);
+ g_test_add ("/password/search-no-name", Test, "mock-service-normal.py", setup, test_search_no_name, teardown);
+
+ g_test_add ("/password/binary-sync", Test, "mock-service-normal.py", setup, test_binary_sync, teardown);
+ g_test_add ("/password/binary-async", Test, "mock-service-normal.py", setup, test_binary_async, teardown);
+
g_test_add_func ("/password/free-null", test_password_free_null);
return egg_tests_run_with_loop ();
diff --git a/tool/secret-tool.c b/tool/secret-tool.c
index 524a364..9f16257 100644
--- a/tool/secret-tool.c
+++ b/tool/secret-tool.c
@@ -16,7 +16,7 @@
#include "libsecret/secret-item.h"
#include "libsecret/secret-password.h"
-#include "libsecret/secret-service.h"
+#include "libsecret/secret-retrievable.h"
#include "libsecret/secret-value.h"
#include <glib/gi18n.h>
@@ -122,8 +122,8 @@ secret_tool_action_clear (int argc,
{
GError *error = NULL;
GOptionContext *context;
- SecretService *service;
GHashTable *attributes;
+ gboolean ret;
context = g_option_context_new ("attribute value ...");
g_option_context_add_main_entries (context, CLEAR_OPTIONS, GETTEXT_PACKAGE);
@@ -137,14 +137,11 @@ secret_tool_action_clear (int argc,
attributes = attributes_from_arguments (attribute_args);
g_strfreev (attribute_args);
- service = secret_service_get_sync (SECRET_SERVICE_NONE, NULL, &error);
- if (error == NULL)
- secret_service_clear_sync (service, NULL, attributes, NULL, &error);
+ ret = secret_password_clearv_sync (NULL, attributes, NULL, &error);
- g_object_unref (service);
g_hash_table_unref (attributes);
- if (error != NULL) {
+ if (!ret) {
g_printerr ("%s: %s\n", g_get_prgname (), error->message);
return 1;
}
@@ -197,7 +194,6 @@ secret_tool_action_lookup (int argc,
{
GError *error = NULL;
GOptionContext *context;
- SecretService *service;
GHashTable *attributes;
SecretValue *value = NULL;
@@ -213,11 +209,8 @@ secret_tool_action_lookup (int argc,
attributes = attributes_from_arguments (attribute_args);
g_strfreev (attribute_args);
- service = secret_service_get_sync (SECRET_SERVICE_NONE, NULL, &error);
- if (error == NULL)
- value = secret_service_lookup_sync (service, NULL, attributes, NULL, &error);
+ value = secret_password_lookupv_binary_sync (NULL, attributes, NULL, &error);
- g_object_unref (service);
g_hash_table_unref (attributes);
if (error != NULL) {
@@ -285,10 +278,10 @@ secret_tool_action_store (int argc,
{
GError *error = NULL;
GOptionContext *context;
- SecretService *service;
GHashTable *attributes;
SecretValue *value;
gchar *collection = NULL;
+ gboolean ret;
context = g_option_context_new ("attribute value ...");
g_option_context_add_main_entries (context, STORE_OPTIONS, GETTEXT_PACKAGE);
@@ -315,24 +308,20 @@ secret_tool_action_store (int argc,
collection = g_strconcat (SECRET_ALIAS_PREFIX, store_collection, NULL);
}
- service = secret_service_get_sync (SECRET_SERVICE_NONE, NULL, &error);
- if (error == NULL) {
- if (isatty (0))
- value = read_password_tty ();
- else
- value = read_password_stdin ();
+ if (isatty (0))
+ value = read_password_tty ();
+ else
+ value = read_password_stdin ();
- secret_service_store_sync (service, NULL, attributes, collection, store_label, value, NULL, &error);
- secret_value_unref (value);
- }
+ ret = secret_password_storev_binary_sync (NULL, attributes, collection, store_label, value, NULL, &error);
+ secret_value_unref (value);
- g_object_unref (service);
g_hash_table_unref (attributes);
g_free (store_label);
g_free (store_collection);
g_free (collection);
- if (error != NULL) {
+ if (!ret) {
g_printerr ("%s: %s\n", g_get_prgname (), error->message);
return 1;
}
@@ -360,58 +349,76 @@ print_item_when (const char *field,
}
static void
-print_item_details (SecretItem *item)
+on_retrieve_secret (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
{
+ SecretRetrievable *item = SECRET_RETRIEVABLE (source_object);
+ GMainLoop *loop = user_data;
SecretValue *secret;
GHashTableIter iter;
GHashTable *attributes;
- gchar *value, *key;
+ const gchar *value, *key;
guint64 when;
+ gchar *label;
const gchar *part;
const gchar *path;
+ GError *error;
- path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (item));
- g_return_if_fail (path != NULL);
+ error = NULL;
+ secret = secret_retrievable_retrieve_secret_finish (item, res, &error);
+ if (!secret) {
+ g_printerr ("%s: %s\n", g_get_prgname (), error->message);
+ g_clear_error (&error);
+ }
- /* The item identifier */
- part = strrchr (path, '/');
- if (part == NULL)
- part = path;
- g_print ("[%s]\n", path);
+ if (G_IS_DBUS_PROXY (item)) {
+ path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (item));
+ g_return_if_fail (path != NULL);
- /* The label */
- value = secret_item_get_label (item);
- g_print ("label = %s\n", value);
- g_free (value);
+ /* The item identifier */
+ part = strrchr (path, '/');
+ if (part == NULL)
+ part = path;
+ g_print ("[%s]\n", path);
+ } else {
+ g_print ("[no path]\n");
+ }
- /* The secret value */
- secret = secret_item_get_secret (item);
- g_print ("secret = ");
- if (secret != NULL) {
- write_password_data (secret);
- secret_value_unref (secret);
+ /* The label */
+ label = secret_retrievable_get_label (item);
+ g_print ("label = %s\n", label);
+ g_free (label);
+
+ if (secret) {
+ /* The secret value */
+ g_print ("secret = ");
+ if (secret != NULL) {
+ write_password_data (secret);
+ secret_value_unref (secret);
+ }
+ g_print ("\n");
}
- g_print ("\n");
/* The dates */
- when = secret_item_get_created (item);
+ when = secret_retrievable_get_created (item);
print_item_when ("created", when);
- when = secret_item_get_modified (item);
+ when = secret_retrievable_get_modified (item);
print_item_when ("modified", when);
- /* The schema */
- value = secret_item_get_schema_name (item);
- g_print ("schema = %s\n", value);
- g_free (value);
-
/* The attributes */
- attributes = secret_item_get_attributes (item);
+ attributes = secret_retrievable_get_attributes (item);
+ value = g_hash_table_lookup (attributes, "xdg:schema");
+ if (value)
+ g_print ("schema = %s\n", value);
+
g_hash_table_iter_init (&iter, attributes);
while (g_hash_table_iter_next (&iter, (void **)&key, (void **)&value)) {
if (strcmp (key, "xdg:schema") != 0)
g_printerr ("attribute.%s = %s\n", key, value);
}
g_hash_table_unref (attributes);
+ g_main_loop_quit (loop);
}
static int
@@ -420,7 +427,6 @@ secret_tool_action_search (int argc,
{
GError *error = NULL;
GOptionContext *context;
- SecretService *service;
GHashTable *attributes;
SecretSearchFlags flags;
gboolean flag_all = FALSE;
@@ -450,21 +456,25 @@ secret_tool_action_search (int argc,
attributes = attributes_from_arguments (attribute_args);
g_strfreev (attribute_args);
- service = secret_service_get_sync (SECRET_SERVICE_NONE, NULL, &error);
+ flags = SECRET_SEARCH_LOAD_SECRETS;
+ if (flag_all)
+ flags |= SECRET_SEARCH_ALL;
+ if (flag_unlock)
+ flags |= SECRET_SEARCH_UNLOCK;
+ items = secret_password_searchv_sync (NULL, attributes, flags, NULL, &error);
if (error == NULL) {
- flags = SECRET_SEARCH_LOAD_SECRETS;
- if (flag_all)
- flags |= SECRET_SEARCH_ALL;
- if (flag_unlock)
- flags |= SECRET_SEARCH_UNLOCK;
- items = secret_service_search_sync (service, NULL, attributes, flags, NULL, &error);
- if (error == NULL) {
- for (l = items; l != NULL; l = g_list_next (l))
- print_item_details (l->data);
- g_list_free_full (items, g_object_unref);
+ GMainLoop *loop = g_main_loop_new (NULL, FALSE);
+
+ for (l = items; l != NULL; l = g_list_next (l)) {
+ SecretRetrievable *retrievable = SECRET_RETRIEVABLE (l->data);
+ secret_retrievable_retrieve_secret (retrievable,
+ NULL,
+ on_retrieve_secret,
+ loop);
+ g_main_loop_run (loop);
}
- g_object_unref (service);
+ g_list_free_full (items, g_object_unref);
}
g_hash_table_unref (attributes);