Use upstream tag
[platform/upstream/libsecret.git] / libsecret / secret-schema.c
1 /* libsecret - GLib wrapper for Secret Service
2  *
3  * Copyright 2011 Collabora Ltd.
4  *
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.
9  *
10  * See the included COPYING file for more information.
11  *
12  * Author: Stef Walter <stefw@gnome.org>
13  */
14
15 #include "config.h"
16
17 #include "secret-password.h"
18 #include "secret-private.h"
19 #include "secret-value.h"
20
21 #include "libsecret/secret-enum-types.h"
22
23 #include "egg/egg-secure-memory.h"
24
25 /**
26  * SECTION:secret-schema
27  * @title: SecretSchema
28  * @short_description: Schema for defining which attributes are on items
29  *
30  * Each password is associated with a set of attributes. Attribute values can
31  * be either strings, integers or booleans.
32  *
33  * The names and types of allowed attributes for a given password are defined
34  * with a schema.
35  *
36  * Additional schemas can be defined via the %SecretSchema structure like this:
37  *
38  * <informalexample><programlisting language="c">
39  * /<!-- -->* in a header: *<!-- -->/
40  *
41  * const SecretSchema * example_get_schema (void) G_GNUC_CONST;
42  *
43  * #define EXAMPLE_SCHEMA  example_get_schema ()
44  *
45  *
46  * /<!-- -->* in a .c file: *<!-- -->/
47  *
48  * const SecretSchema *
49  * example_get_schema (void)
50  * {
51  *      static const SecretSchema the_schema = {
52  *              "org.example.Password", SECRET_SCHEMA_NONE,
53  *              {
54  *                      {  "number", SECRET_SCHEMA_ATTRIBUTE_INTEGER },
55  *                      {  "string", SECRET_SCHEMA_ATTRIBUTE_STRING },
56  *                      {  "even", SECRET_SCHEMA_ATTRIBUTE_BOOLEAN },
57  *                      {  NULL, 0 },
58  *              }
59  *      };
60  *      return &the_schema;
61  * }
62  * </programlisting></informalexample>
63  *
64  * Stability: Stable
65  */
66
67 /**
68  * SecretSchema:
69  * @name: the dotted name of the schema
70  * @flags: flags for the schema
71  * @attributes: the attribute names and types of those attributes
72  *
73  * Represents a set of attributes that are stored with an item. These schemas
74  * are used for interoperability between various services storing the same types
75  * of items.
76  *
77  * Each schema has a name like "org.gnome.keyring.NetworkPassword", and defines
78  * a set of attributes, and types (string, integer, boolean) for those attributes.
79  *
80  * Attributes are stored as strings in the Secret Service, and the attribute
81  * types simply define standard ways to store integer and boolean values as strings.
82  * Attributes are represented in libsecret via a #GHashTable with string keys and
83  * values. Even for values that defined as an integer or boolean in the schema,
84  * the attribute values in the #GHashTable are strings. Boolean values are stored
85  * as the strings 'true' and 'false'. Integer values are stored in decimal, with
86  * a preceeding negative sign for negative integers.
87  *
88  * Schemas are handled entirely on the client side by this library. The name of the
89  * schema is automatically stored as an attribute on the item.
90  *
91  * Normally when looking up passwords only those with matching schema names are
92  * returned. If the schema @flags contain the %SECRET_SCHEMA_DONT_MATCH_NAME flag,
93  * then lookups will not check that the schema name matches that on the item, only
94  * the schema's attributes are matched. This is useful when you are looking up items
95  * that are not stored by the libsecret library. Other libraries such as libgnome-keyring
96  * don't store the schema name.
97  *
98  * Stability: Stable
99  */
100
101 /**
102  * SecretSchemaFlags:
103  * @SECRET_SCHEMA_NONE: no flags for the schema
104  * @SECRET_SCHEMA_DONT_MATCH_NAME: don't match the schema name when looking up or
105  *                                 removing passwords
106  *
107  * Flags for a #SecretSchema definition.
108  */
109
110 /**
111  * SecretSchemaAttribute:
112  * @name: name of the attribute
113  * @type: the type of the attribute
114  *
115  * An attribute in a #SecretSchema.
116  */
117
118 /**
119  * SecretSchemaAttributeType:
120  * @SECRET_SCHEMA_ATTRIBUTE_BOOLEAN: a boolean attribute, stored as 'true' or 'false'
121  * @SECRET_SCHEMA_ATTRIBUTE_INTEGER: an integer attribute, stored as a decimal
122  * @SECRET_SCHEMA_ATTRIBUTE_STRING: a utf-8 string attribute
123  *
124  * The type of an attribute in a #SecretSchema. Attributes are stored as strings
125  * in the Secret Service, and the attribute types simply define standard ways
126  * to store integer and boolean values as strings.
127  */
128
129 static SecretSchemaAttribute *
130 schema_attribute_copy (SecretSchemaAttribute *attribute)
131 {
132         SecretSchemaAttribute *copy;
133
134         copy = g_slice_new0 (SecretSchemaAttribute);
135         copy->name = g_strdup (attribute->name);
136         copy->type = attribute->type;
137
138         return copy;
139 }
140
141 static void
142 schema_attribute_free (SecretSchemaAttribute *attribute)
143 {
144         g_free ((gchar *)attribute->name);
145         g_slice_free (SecretSchemaAttribute, attribute);
146 }
147
148 G_DEFINE_BOXED_TYPE (SecretSchemaAttribute, secret_schema_attribute,
149                      schema_attribute_copy, schema_attribute_free);
150
151 /**
152  * secret_schema_newv:
153  * @name: the dotted name of the schema
154  * @flags: the flags for the schema
155  * @attribute_names_and_types: (element-type utf8 Secret.SchemaAttributeType): the attribute names and types of those attributes
156  *
157  * Using this function is not normally necessary from C code. This is useful
158  * for constructing #SecretSchema structures in bindings.
159  *
160  * A schema represents a set of attributes that are stored with an item. These
161  * schemas are used for interoperability between various services storing the
162  * same types of items.
163  *
164  * Each schema has an @name like "org.gnome.keyring.NetworkPassword", and
165  * defines a set of attributes names, and types (string, integer, boolean) for
166  * those attributes.
167  *
168  * Each key in the @attributes table should be a attribute name strings, and
169  * the values in the table should be integers from the #SecretSchemaAttributeType
170  * enumeration, representing the attribute type for each attribute name.
171  *
172  * Normally when looking up passwords only those with matching schema names are
173  * returned. If the schema @flags contain the %SECRET_SCHEMA_DONT_MATCH_NAME flag,
174  * then lookups will not check that the schema name matches that on the item, only
175  * the schema's attributes are matched. This is useful when you are looking up items
176  * that are not stored by the libsecret library. Other libraries such as libgnome-keyring
177  * don't store the schema name.
178  *
179  * Rename to: secret_schema_new
180  *
181  * Returns: (transfer full): the new schema, which should be unreferenced with
182  *          secret_schema_unref() when done
183  */
184 SecretSchema *
185 secret_schema_newv (const gchar *name,
186                     SecretSchemaFlags flags,
187                     GHashTable *attribute_names_and_types)
188 {
189         SecretSchema *schema;
190         GHashTableIter iter;
191         GEnumClass *enumc;
192         gpointer value;
193         gpointer key;
194         gint type;
195         gint ind = 0;
196
197         g_return_val_if_fail (name != NULL, NULL);
198         g_return_val_if_fail (attribute_names_and_types != NULL, NULL);
199
200         schema = g_slice_new0 (SecretSchema);
201         schema->name = g_strdup (name);
202         schema->flags = flags;
203         schema->reserved = 1;
204
205         if (attribute_names_and_types) {
206                 g_hash_table_iter_init (&iter, attribute_names_and_types);
207                 while (g_hash_table_iter_next (&iter, &key, &value)) {
208
209                         if (ind >= G_N_ELEMENTS (schema->attributes)) {
210                                 g_warning ("too many attributes for schema, max %d",
211                                            (gint) G_N_ELEMENTS (schema->attributes));
212                                 break;
213                         }
214
215                         type = GPOINTER_TO_INT (value);
216
217                         enumc = G_ENUM_CLASS (g_type_class_ref (SECRET_TYPE_SCHEMA_ATTRIBUTE_TYPE));
218                         if (!g_enum_get_value (enumc, type)) {
219                                 g_warning ("invalid type for attribute %s", (gchar *)key);
220                                 type = -1;
221                         }
222
223                         g_type_class_unref (enumc);
224
225                         if (type >= 0) {
226                                 schema->attributes[ind].name = g_strdup (key);
227                                 schema->attributes[ind].type = type;
228                         }
229
230                         ind++;
231                 }
232         }
233
234         return schema;
235 }
236
237 /**
238  * secret_schema_new: (skip)
239  * @name: the dotted name of the schema
240  * @flags: the flags for the schema
241  * @...: the attribute names and types, terminated with %NULL
242  *
243  * Using this function is not normally necessary from C code.
244  *
245  * A schema represents a set of attributes that are stored with an item. These
246  * schemas are used for interoperability between various services storing the
247  * same types of items.
248  *
249  * Each schema has an @name like "org.gnome.keyring.NetworkPassword", and
250  * defines a set of attributes names, and types (string, integer, boolean) for
251  * those attributes.
252  *
253  * The variable argument list should contain pairs of a) The attribute name as
254  * a null-terminated string, followed by b) integers from the
255  * #SecretSchemaAttributeType enumeration, representing the attribute type for
256  * each attribute name. The list of attribtues should be terminated with a %NULL.
257  *
258  * Normally when looking up passwords only those with matching schema names are
259  * returned. If the schema @flags contain the %SECRET_SCHEMA_DONT_MATCH_NAME flag,
260  * then lookups will not check that the schema name matches that on the item, only
261  * the schema's attributes are matched. This is useful when you are looking up items
262  * that are not stored by the libsecret library. Other libraries such as libgnome-keyring
263  * don't store the schema name.
264  *
265  * Returns: (transfer full): the new schema, which should be unreferenced with
266  *          secret_schema_unref() when done
267  */
268 SecretSchema *
269 secret_schema_new (const gchar *name,
270                    SecretSchemaFlags flags,
271                    ...)
272 {
273         SecretSchemaAttributeType type;
274         GHashTable *attributes;
275         SecretSchema *schema;
276         const gchar *attribute;
277         va_list va;
278
279         g_return_val_if_fail (name != NULL, NULL);
280
281         va_start (va, flags);
282         attributes = g_hash_table_new (g_str_hash, g_str_equal);
283
284         while ((attribute = va_arg (va, const gchar *)) != NULL) {
285                 type = va_arg (va, SecretSchemaAttributeType);
286                 g_hash_table_insert (attributes, (gpointer *)attribute,
287                                      GINT_TO_POINTER (type));
288         }
289
290         schema = secret_schema_newv (name, flags, attributes);
291
292         g_hash_table_unref (attributes);
293         va_end (va);
294
295         return schema;
296 }
297
298 /**
299  * secret_schema_ref:
300  * @schema: the schema to reference
301  *
302  * Adds a reference to the #SecretSchema.
303  *
304  * It is not normally necessary to call this function from C code, and is
305  * mainly present for the sake of bindings. If the @schema was statically
306  * allocated, then this function will copy the schema.
307  *
308  * Returns: (transfer full): the referenced schema, which should be later
309  *          unreferenced with secret_schema_unref()
310  */
311 SecretSchema *
312 secret_schema_ref (SecretSchema *schema)
313 {
314         SecretSchema *result;
315         gint i;
316
317         g_return_val_if_fail (schema != NULL, NULL);
318
319         /* If it's static, then copy it */
320         if (g_atomic_int_get (&schema->reserved) > 0) {
321                 g_atomic_int_inc (&schema->reserved);
322                 result = schema;
323         } else {
324                 result = g_slice_new0 (SecretSchema);
325                 result->reserved = 1;
326                 result->name = g_strdup (schema->name);
327
328                 for (i = 0; i < G_N_ELEMENTS (schema->attributes); i++) {
329                         result->attributes[i].name = g_strdup (schema->attributes[i].name);
330                         result->attributes[i].type = schema->attributes[i].type;
331                 }
332         }
333
334         return result;
335 }
336
337 const SecretSchema *
338 _secret_schema_ref_if_nonstatic (const SecretSchema *schema)
339 {
340         if (schema && g_atomic_int_get (&schema->reserved) > 0)
341                 secret_schema_ref ((SecretSchema *)schema);
342
343         return schema;
344 }
345
346 /**
347  * secret_schema_unref:
348  * @schema: the schema to reference
349  *
350  * Releases a reference to the #SecretSchema. If the last reference is
351  * released then the schema will be freed.
352  *
353  * It is not normally necessary to call this function from C code, and is
354  * mainly present for the sake of bindings. It is an error to call this for
355  * a @schema that was statically allocated.
356  */
357 void
358 secret_schema_unref (SecretSchema *schema)
359 {
360         gint refs;
361         gint i;
362
363         g_return_if_fail (schema != NULL);
364
365         refs = g_atomic_int_add (&schema->reserved, -1);
366         if (refs < 0) {
367                 g_warning ("should not unreference a static or invalid SecretSchema");
368
369         } else if (refs == 0) {
370                 g_free ((gpointer)schema->name);
371                 for (i = 0; i < G_N_ELEMENTS (schema->attributes); i++)
372                         g_free ((gpointer)schema->attributes[i].name);
373                 g_slice_free (SecretSchema, schema);
374         }
375 }
376
377 void
378 _secret_schema_unref_if_nonstatic (const SecretSchema *schema)
379 {
380         if (schema && g_atomic_int_get (&schema->reserved) > 0)
381                 secret_schema_unref ((SecretSchema *)schema);
382 }
383
384 G_DEFINE_BOXED_TYPE (SecretSchema, secret_schema, secret_schema_ref, secret_schema_unref);