1 /* libsecret - GLib wrapper for Secret Service
3 * Copyright 2011 Collabora Ltd.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published
7 * by the Free Software Foundation; either version 2.1 of the licence or (at
8 * your option) any later version.
10 * See the included COPYING file for more information.
12 * Author: Stef Walter <stefw@gnome.org>
17 #include "secret-attributes.h"
18 #include "secret-private.h"
23 * SECTION:secret-attributes
24 * @title: Secret Attributes
25 * @short_description: secret attributes
27 * Each item has a set of attributes, which are used to locate the item later.
28 * These are not stored or transferred in a secure manner. Each attribute has
29 * a string name and a string value. These attributes are represented by a
30 * #GHashTable with string keys and values.
32 * Use secret_attributes_build() to simply build up a set of attributes.
36 _secret_attributes_to_variant (GHashTable *attributes,
37 const gchar *schema_name)
40 GVariantBuilder builder;
44 g_return_val_if_fail (attributes != NULL, NULL);
46 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
48 g_hash_table_iter_init (&iter, attributes);
49 while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&value)) {
50 if (!schema_name || !g_str_equal (name, "xdg:schema"))
51 g_variant_builder_add (&builder, "{ss}", name, value);
55 g_variant_builder_add (&builder, "{ss}", "xdg:schema", schema_name);
57 return g_variant_builder_end (&builder);
61 _secret_attributes_for_variant (GVariant *variant)
64 GHashTable *attributes;
68 attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
70 g_variant_iter_init (&iter, variant);
71 while (g_variant_iter_next (&iter, "{ss}", &key, &value))
72 g_hash_table_insert (attributes, key, value);
78 * secret_attributes_build: (skip)
79 * @schema: the schema for the attributes
80 * @...: the attribute keys and values, terminated with %NULL
82 * Build up a hash table of attribute values.
84 * The variable argument list should contain pairs of a) The attribute name as
85 * a null-terminated string, followed by b) attribute value, either a character
86 * string, an int number, or a gboolean value, as defined in the password
87 * @schema. The list of attribtues should be terminated with a %NULL.
89 * Returns: (transfer full) (element-type utf8 utf8): a new table of
90 * attributes, to be released with g_hash_table_unref()
93 secret_attributes_build (const SecretSchema *schema,
96 GHashTable *attributes;
99 va_start (va, schema);
100 attributes = secret_attributes_buildv (schema, va);
107 * secret_attributes_buildv: (skip)
108 * @schema: the schema for the attributes
109 * @va: the attribute keys and values, terminated with %NULL
111 * Build up a hash table of attribute values.
113 * The variable argument list should contain pairs of a) The attribute name as
114 * a null-terminated string, followed by b) attribute value, either a character
115 * string, an int number, or a gboolean value, as defined in the password
116 * @schema. The list of attribtues should be terminated with a %NULL.
118 * Returns: (transfer full) (element-type utf8 utf8): a new table of
119 * attributes, to be released with g_hash_table_unref()
122 secret_attributes_buildv (const SecretSchema *schema,
125 const gchar *attribute_name;
126 SecretSchemaAttributeType type;
127 GHashTable *attributes;
135 g_return_val_if_fail (schema != NULL, NULL);
137 attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
140 attribute_name = va_arg (va, const gchar *);
141 if (attribute_name == NULL)
145 for (i = 0; i < G_N_ELEMENTS (schema->attributes); ++i) {
146 if (!schema->attributes[i].name)
148 if (g_str_equal (schema->attributes[i].name, attribute_name)) {
150 type = schema->attributes[i].type;
156 g_critical ("The attribute '%s' was not found in the password schema.", attribute_name);
157 g_hash_table_unref (attributes);
162 case SECRET_SCHEMA_ATTRIBUTE_BOOLEAN:
163 boolean = va_arg (va, gboolean);
164 value = g_strdup (boolean ? "true" : "false");
166 case SECRET_SCHEMA_ATTRIBUTE_STRING:
167 string = va_arg (va, gchar *);
168 if (string == NULL) {
169 g_critical ("The value for attribute '%s' was NULL", attribute_name);
172 if (!g_utf8_validate (string, -1, NULL)) {
173 g_critical ("The value for attribute '%s' was not a valid UTF-8 string.", attribute_name);
174 g_hash_table_unref (attributes);
177 value = g_strdup (string);
179 case SECRET_SCHEMA_ATTRIBUTE_INTEGER:
180 integer = va_arg (va, gint);
181 value = g_strdup_printf ("%d", integer);
184 g_critical ("The password attribute '%s' has an invalid type in the password schema.", attribute_name);
185 g_hash_table_unref (attributes);
189 g_hash_table_insert (attributes, g_strdup (attribute_name), value);
196 _secret_attributes_validate (const SecretSchema *schema,
197 GHashTable *attributes,
198 const char *pretty_function,
201 const SecretSchemaAttribute *attribute;
203 gboolean any = FALSE;
209 g_return_val_if_fail (schema != NULL, FALSE);
211 g_hash_table_iter_init (&iter, attributes);
212 while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value)) {
215 /* If the 'xdg:schema' meta-attribute is present,
216 ensure that it is consistent with the schema
218 if (g_str_equal (key, "xdg:schema")) {
219 if (!g_str_equal (value, schema->name)) {
220 g_critical ("%s: xdg:schema value %s differs from schema %s:",
221 pretty_function, value, schema->name);
227 /* Pass through libgnomekeyring specific attributes */
228 if (g_str_has_prefix (key, "gkr:"))
231 /* Find the attribute */
233 for (i = 0; i < G_N_ELEMENTS (schema->attributes); i++) {
234 if (schema->attributes[i].name == NULL)
236 if (g_str_equal (schema->attributes[i].name, key)) {
237 attribute = &schema->attributes[i];
242 if (attribute == NULL) {
243 g_critical ("%s: invalid %s attribute for %s schema",
244 pretty_function, key, schema->name);
248 switch (attribute->type) {
249 case SECRET_SCHEMA_ATTRIBUTE_BOOLEAN:
250 if (!g_str_equal (value, "true") && !g_str_equal (value, "false")) {
251 g_critical ("%s: invalid %s boolean value for %s schema: %s",
252 pretty_function, key, schema->name, value);
256 case SECRET_SCHEMA_ATTRIBUTE_INTEGER:
258 g_ascii_strtoll (value, &end, 10);
259 if (!end || end[0] != '\0') {
260 g_warning ("%s: invalid %s integer value for %s schema: %s",
261 pretty_function, key, schema->name, value);
265 case SECRET_SCHEMA_ATTRIBUTE_STRING:
266 if (!g_utf8_validate (value, -1, NULL)) {
267 g_warning ("%s: invalid %s string value for %s schema: %s",
268 pretty_function, key, schema->name, value);
273 g_warning ("%s: invalid %s value type in %s schema",
274 pretty_function, key, schema->name);
279 /* Nothing to match on, resulting search would match everything :S */
280 if (matching && !any && schema->flags & SECRET_SCHEMA_DONT_MATCH_NAME) {
281 g_warning ("%s: must specify at least one attribute to match",
290 _secret_attributes_copy (GHashTable *attributes)
297 if (attributes == NULL)
300 copy = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
302 g_hash_table_iter_init (&iter, attributes);
303 while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
304 g_hash_table_insert (copy, g_strdup (key), g_strdup (value));