Update to upstream 1.0.1
[profile/ivi/gsignond.git] / src / common / gsignond-identity-info.c
1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4  * This file is part of gsignond
5  *
6  * Copyright (C) 2012-2013 Intel Corporation.
7  *
8  * Contact: Imran Zaman <imran.zaman@linux.intel.com>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23  * 02110-1301 USA
24  */
25
26 #include "gsignond-identity-info.h"
27 #include "gsignond-identity-info-internal.h"
28 #include "gsignond/gsignond-utils.h"
29
30 G_DEFINE_BOXED_TYPE(GSignondIdentityInfo,
31                     gsignond_identity_info,
32                     gsignond_identity_info_ref,
33                     gsignond_identity_info_unref)
34
35 struct _GSignondIdentityInfo
36 {
37     volatile gint ref_count;
38     gchar *username;
39     gchar *secret;
40     GSignondIdentityInfoPropFlags edit_flags;
41     GSignondDictionary *map;
42 };
43
44 static gboolean
45 _gsignond_identity_info_seq_cmp (
46         GSequence *one,
47         GSequence *two)
48 {
49     GSequenceIter *iter1 = NULL, *iter2 = NULL;
50     gboolean equal = TRUE;
51
52    if (one == two)
53         return TRUE;
54
55    if (one == NULL) {
56         if (g_sequence_get_length (two) == 0)
57             return TRUE;
58         else
59             return FALSE;
60    }
61
62    if (two == NULL) {
63         if (g_sequence_get_length (one) == 0)
64             return TRUE;
65         else
66             return FALSE;
67     }
68
69     if (g_sequence_get_length (one) != g_sequence_get_length (two))
70         return FALSE;
71
72     iter1 = g_sequence_get_begin_iter (one);
73     while (!g_sequence_iter_is_end (iter1)) {
74         iter2 = g_sequence_get_iter_at_pos (two,
75                     g_sequence_iter_get_position (iter1));
76         if (g_strcmp0 (g_sequence_get (iter1), g_sequence_get (iter2)) != 0) {
77             equal = FALSE;
78             break;
79         }
80         iter1 = g_sequence_iter_next (iter1);
81     }
82
83     return equal;
84 }
85
86 static gboolean
87 _gsignond_identity_info_sec_context_list_cmp (
88         GSignondSecurityContextList *one,
89         GSignondSecurityContextList *two)
90 {
91     GSignondSecurityContextList *list_elem1 = NULL, *list_elem2 = NULL;
92     gboolean equal = TRUE;
93
94     if (one == NULL && two == NULL)
95         return TRUE;
96
97     if ((one != NULL && two == NULL) ||
98         (one == NULL && two != NULL) ||
99         (g_list_length (one) != g_list_length (two)))
100         return FALSE;
101
102     if (one == two)
103         return TRUE;
104
105     list_elem1 = one;
106     for ( ; list_elem1 != NULL; list_elem1 = g_list_next (list_elem1)) {
107         list_elem2 = g_list_nth (two, g_list_position (one, list_elem1));
108         if (!gsignond_security_context_match (
109                 (GSignondSecurityContext *)list_elem1->data,
110                 (GSignondSecurityContext *)list_elem2->data)) {
111             equal = FALSE;
112             break;
113         }
114     }
115
116     return equal;
117 }
118
119 static gboolean
120 _gsignond_identity_info_methods_cmp (
121         GHashTable *one,
122         GHashTable *two)
123 {
124     GHashTableIter iter1;
125     GSequence *mechs1 = NULL, *mechs2 = NULL;
126     gchar *key = NULL;
127     gboolean equal = TRUE;
128
129     if (one == NULL && two == NULL)
130         return TRUE;
131
132     if ((one != NULL && two == NULL) ||
133         (one == NULL && two != NULL) ||
134         (g_hash_table_size (one) != g_hash_table_size (two)))
135         return FALSE;
136
137     if (one == two)
138         return TRUE;
139
140     g_hash_table_iter_init(&iter1, one);
141     while (g_hash_table_iter_next (&iter1, (gpointer *)&key,
142             (gpointer *)&mechs1)) {
143         mechs2 = (GSequence *)g_hash_table_lookup (two, key);
144         equal = _gsignond_identity_info_seq_cmp (mechs1, mechs2);
145         if (!equal) {
146             break;
147         }
148     }
149
150     return equal;
151 }
152
153 GSignondIdentityInfoPropFlags
154 gsignond_identity_info_get_edit_flags (
155         GSignondIdentityInfo *info)
156 {
157     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO(info),
158                           IDENTITY_INFO_PROP_NONE);
159
160     return info->edit_flags;
161 }
162
163 gboolean
164 gsignond_identity_info_set_edit_flags (
165         GSignondIdentityInfo *info,
166         GSignondIdentityInfoPropFlags flag)
167 {
168     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO(info), FALSE);
169
170     info->edit_flags |= flag;
171
172     return TRUE;
173 }
174
175 gboolean
176 gsignond_identity_info_reset_edit_flags (
177         GSignondIdentityInfo *info,
178         GSignondIdentityInfoPropFlags flags)
179 {
180     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO(info), FALSE);
181
182     info->edit_flags = flags;
183
184     return TRUE; 
185 }
186
187 gboolean
188 gsignond_identity_info_unset_edit_flags (
189         GSignondIdentityInfo *info,
190         GSignondIdentityInfoPropFlags unset_flags)
191 {
192     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO(info), FALSE);
193
194     info->edit_flags &= ~unset_flags;
195
196     return TRUE;
197 }
198
199 GSignondIdentityInfoPropFlags
200 gsignond_identity_info_selective_copy (GSignondIdentityInfo *dest,
201                                        const GSignondIdentityInfo *src,
202                                        GSignondIdentityInfoPropFlags flags)
203 {
204     GSignondIdentityInfoPropFlags tmp_flag;
205     guint i;
206     g_return_val_if_fail (src, IDENTITY_INFO_PROP_NONE);
207     g_return_val_if_fail (dest, IDENTITY_INFO_PROP_NONE);
208     g_return_val_if_fail (flags != IDENTITY_INFO_PROP_NONE, flags);
209
210     /* This table should match to GSignondIdentityInfoPropFlags order */
211     const gchar *keys[] = {
212         GSIGNOND_IDENTITY_INFO_ID,
213         GSIGNOND_IDENTITY_INFO_TYPE,
214         GSIGNOND_IDENTITY_INFO_CAPTION,
215         GSIGNOND_IDENTITY_INFO_STORESECRET,
216         GSIGNOND_IDENTITY_INFO_USERNAME_IS_SECRET,
217         GSIGNOND_IDENTITY_INFO_OWNER,
218         GSIGNOND_IDENTITY_INFO_ACL,
219         GSIGNOND_IDENTITY_INFO_AUTHMETHODS,
220         GSIGNOND_IDENTITY_INFO_REALMS,
221         GSIGNOND_IDENTITY_INFO_REFCOUNT,
222         GSIGNOND_IDENTITY_INFO_VALIDATED
223     };
224
225     for (i= 0, tmp_flag = IDENTITY_INFO_PROP_ID; 
226          tmp_flag < IDENTITY_INFO_PROP_MAX;
227          tmp_flag <<= 1, i++) {
228         if ((flags & tmp_flag) && 
229             gsignond_dictionary_contains (src->map, keys[i])) {
230             gsignond_dictionary_set (dest->map, keys[i],
231                g_variant_ref (gsignond_dictionary_get (src->map, keys[i])));
232         }
233         else {
234             flags &= ~tmp_flag;
235         }
236     }
237
238     if (flags & IDENTITY_INFO_PROP_USERNAME) {
239         g_free (dest->username);
240         dest->username = g_strdup (src->username);
241     }
242
243     if (flags & IDENTITY_INFO_PROP_SECRET) {
244         g_free (dest->secret);
245         dest->secret = g_strdup (src->secret);
246     }
247
248     dest->edit_flags |= flags;
249
250     return flags;
251 }
252
253 void
254 gsignond_identity_info_remove_owner (GSignondIdentityInfo *info)
255 {
256     g_return_if_fail (info && GSIGNOND_IS_IDENTITY_INFO(info));
257
258     gsignond_dictionary_remove (info->map, GSIGNOND_IDENTITY_INFO_OWNER);
259 }
260
261 /**
262  * gsignond_identity_info_new:
263  *
264  * Creates new instance of GSignondIdentityInfo.
265  *
266  * Returns: (transfer full): #GSignondIdentityInfo object if successful,
267  * NULL otherwise.
268  */
269 GSignondIdentityInfo *
270 gsignond_identity_info_new (void)
271 {
272     return gsignond_identity_info_new_from_variant (NULL);
273 }
274
275 /**
276  * gsignond_identity_info_new_from_variant:
277  *
278  * Creates new instance of GSignondIdentityInfo.
279  *
280  * Returns: (transfer full) #GSignondIdentityInfo object if successful,
281  * NULL otherwise.
282  */
283 GSignondIdentityInfo *
284 gsignond_identity_info_new_from_variant (GVariant *variant_map)
285 {
286     gboolean uname_is_secret = FALSE;
287     GSignondIdentityInfo *info = g_slice_new0 (GSignondIdentityInfo);
288     if (!info) return NULL;
289
290     info->ref_count = 1;
291     info->edit_flags = IDENTITY_INFO_PROP_NONE;
292     info->username = info->secret = NULL;
293
294     if (!variant_map) {
295         info->map = gsignond_dictionary_new ();
296
297         gsignond_dictionary_set (info->map, GSIGNOND_IDENTITY_INFO_ID,
298             g_variant_new_uint32 (GSIGNOND_IDENTITY_INFO_NEW_IDENTITY));
299
300         return info;
301     }
302
303     info->map = gsignond_dictionary_new_from_variant (variant_map);
304     if (!info->map) return info;
305
306     /* update edit flags */
307     if (gsignond_dictionary_contains (info->map, GSIGNOND_IDENTITY_INFO_ID))
308         info->edit_flags |= IDENTITY_INFO_PROP_ID;
309     if (gsignond_dictionary_contains (info->map, GSIGNOND_IDENTITY_INFO_TYPE))
310         info->edit_flags |= IDENTITY_INFO_PROP_TYPE;
311     if (gsignond_dictionary_contains (info->map, 
312                 GSIGNOND_IDENTITY_INFO_USERNAME_IS_SECRET)) {
313         info->edit_flags |= IDENTITY_INFO_PROP_USERNAME_IS_SECRET;
314         gsignond_dictionary_get_boolean (info->map,
315                 GSIGNOND_IDENTITY_INFO_USERNAME_IS_SECRET, &uname_is_secret);
316     }
317     if (gsignond_dictionary_contains (info->map,
318                 GSIGNOND_IDENTITY_INFO_USERNAME)) {
319         info->edit_flags |= IDENTITY_INFO_PROP_USERNAME;
320         info->username = g_strdup (gsignond_dictionary_get_string (info->map,
321                                             GSIGNOND_IDENTITY_INFO_USERNAME));
322         gsignond_dictionary_remove (info->map, GSIGNOND_IDENTITY_INFO_USERNAME);
323     }
324     if (gsignond_dictionary_contains (info->map, 
325                 GSIGNOND_IDENTITY_INFO_SECRET)) {
326         info->edit_flags |= IDENTITY_INFO_PROP_SECRET;
327         info->secret = g_strdup (gsignond_dictionary_get_string (info->map,
328                                     GSIGNOND_IDENTITY_INFO_SECRET));
329         gsignond_dictionary_remove (info->map, GSIGNOND_IDENTITY_INFO_SECRET);
330     }
331     if (gsignond_dictionary_contains (info->map,
332                 GSIGNOND_IDENTITY_INFO_STORESECRET))
333         info->edit_flags |= IDENTITY_INFO_PROP_STORE_SECRET;
334     if (gsignond_dictionary_contains (info->map,
335                 GSIGNOND_IDENTITY_INFO_CAPTION))
336         info->edit_flags |= IDENTITY_INFO_PROP_CAPTION;
337     if (gsignond_dictionary_contains (info->map,
338                 GSIGNOND_IDENTITY_INFO_AUTHMETHODS))
339         info->edit_flags |= IDENTITY_INFO_PROP_METHODS;
340     if (gsignond_dictionary_contains (info->map, GSIGNOND_IDENTITY_INFO_REALMS))
341         info->edit_flags |= IDENTITY_INFO_PROP_REALMS;
342     if (gsignond_dictionary_contains (info->map, GSIGNOND_IDENTITY_INFO_ACL))
343         info->edit_flags |= IDENTITY_INFO_PROP_ACL;
344     if (gsignond_dictionary_contains (info->map, GSIGNOND_IDENTITY_INFO_OWNER))
345         info->edit_flags |= IDENTITY_INFO_PROP_OWNER;
346     if (gsignond_dictionary_contains (info->map,
347                 GSIGNOND_IDENTITY_INFO_REFCOUNT))
348         info->edit_flags |= IDENTITY_INFO_PROP_REF_COUNT;
349     if (gsignond_dictionary_contains (info->map,
350                 GSIGNOND_IDENTITY_INFO_VALIDATED))
351         info->edit_flags |= IDENTITY_INFO_PROP_VALIDATED;
352
353     return info;
354 }
355
356 /**
357  * gsignond_identity_info_copy:
358  * @info: instance of #GSignondIdentityInfo
359  *
360  * Creates a copy of info structure.
361  *
362  * Returns: copy of the info.
363  */
364 GSignondIdentityInfo *
365 gsignond_identity_info_copy (GSignondIdentityInfo *info)
366 {
367     GSignondIdentityInfo *new_info = NULL;
368     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), NULL);
369
370     new_info = g_slice_new0 (GSignondIdentityInfo);
371     if (!new_info) return NULL;
372
373     new_info->ref_count = 1;
374     new_info->edit_flags = info->edit_flags;
375     new_info->username = g_strdup (info->username);
376     new_info->secret = g_strdup (info->secret);
377     new_info->map = gsignond_dictionary_copy (info->map);
378
379     return new_info;
380 }
381
382 /**
383  * gsignond_identity_info_ref:
384  * @info: instance of #GSignondIdentityInfo
385  *
386  * Increment reference count of the info structure.
387  * 
388  * Returns: (transfer none) returns the same  copy of the info.
389  */
390 GSignondIdentityInfo *
391 gsignond_identity_info_ref (GSignondIdentityInfo *info)
392 {
393     g_return_val_if_fail (info != NULL, info);
394
395     g_atomic_int_inc (&info->ref_count);
396
397     return info;
398 }
399
400 /**
401  * gsignond_identity_info_unref:
402  * @info: instance of #GSignondIdentityInfo
403  *
404  * Decrement reference count of the info structure.
405  */
406 void
407 gsignond_identity_info_unref (GSignondIdentityInfo *info)
408 {
409     g_return_if_fail (info != NULL);
410
411     if (g_atomic_int_dec_and_test (&info->ref_count)) {
412         gsignond_dictionary_unref (info->map);
413         g_free(info->username);
414         g_free(info->secret);
415         g_slice_free (GSignondIdentityInfo, info);
416     }
417 }
418
419 /**
420  * gsignond_identity_info_get_id:
421  * @info: instance of #GSignondIdentityInfo
422  *
423  * Retrieves the id from the info.
424  *
425  * Returns: the id; negative id is returned in case of failure.
426  */
427 guint32
428 gsignond_identity_info_get_id (GSignondIdentityInfo *info)
429 {
430     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info),
431             GSIGNOND_IDENTITY_INFO_NEW_IDENTITY);
432
433     GVariant *var = gsignond_dictionary_get (info->map,
434                         GSIGNOND_IDENTITY_INFO_ID);
435
436     return var ? g_variant_get_uint32 (var)
437                : GSIGNOND_IDENTITY_INFO_NEW_IDENTITY;
438 }
439
440 /**
441  * gsignond_identity_info_set_id:
442  * @info: instance of #GSignondIdentityInfo
443  *
444  * @id: id to be set
445  *
446  * Sets the id of the info.
447  *
448  * Returns: TRUE if successful, FALSE otherwise.
449  */
450 gboolean
451 gsignond_identity_info_set_id (
452         GSignondIdentityInfo *info,
453         guint32 id)
454 {
455     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
456
457     if (gsignond_identity_info_get_id (info) == id)
458         return TRUE;
459
460     return gsignond_dictionary_set (
461             info->map,
462             GSIGNOND_IDENTITY_INFO_ID,
463             g_variant_new_uint32 (id)) &&
464            gsignond_identity_info_set_edit_flags (info,
465             IDENTITY_INFO_PROP_ID);
466 }
467
468 /**
469  * gsignond_identity_info_get_is_identity_new:
470  * @info: instance of #GSignondIdentityInfo
471  *
472  * Retrieves the info whether the identity is new or not.
473  *
474  * Returns: TRUE if new, FALSE otherwise.
475  */
476 gboolean
477 gsignond_identity_info_get_is_identity_new (GSignondIdentityInfo *info)
478 {
479     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
480
481     return GSIGNOND_IDENTITY_INFO_NEW_IDENTITY ==
482             gsignond_identity_info_get_id (info);
483 }
484
485 /**
486  * gsignond_identity_info_set_identity_new:
487  * @info: instance of #GSignondIdentityInfo
488  *
489  * Sets the id of the identity info to be new.
490  *
491  * Returns: TRUE if successful, FALSE otherwise.
492  */
493 gboolean
494 gsignond_identity_info_set_identity_new (
495         GSignondIdentityInfo *info)
496 {
497     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
498  
499     return gsignond_identity_info_set_id (
500             info,
501             GSIGNOND_IDENTITY_INFO_NEW_IDENTITY);
502 }
503
504 /**
505  * gsignond_identity_info_get_username:
506  * @info: instance of #GSignondIdentityInfo
507  *
508  * Retrieves the username from the info.
509  *
510  * Returns: the username if successful, NULL otherwise.
511  */
512 const gchar *
513 gsignond_identity_info_get_username (GSignondIdentityInfo *info)
514 {
515     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), NULL);
516
517     return (const gchar *)info->username;
518 }
519
520 /**
521  * gsignond_identity_info_set_username:
522  * @info: instance of #GSignondIdentityInfo
523  *
524  * @username: username to be set
525  *
526  * Sets the username of the info.
527  *
528  * Returns: TRUE if successful, FALSE otherwise.
529  */
530 gboolean
531 gsignond_identity_info_set_username (
532         GSignondIdentityInfo *info,
533         const gchar *username)
534 {
535     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
536
537     const gchar *current_name = gsignond_identity_info_get_username(info);
538     if (g_strcmp0 (username, current_name) == 0) return TRUE;
539
540     g_free (info->username);
541     info->username = g_strdup (username);
542  
543     return gsignond_identity_info_set_edit_flags (info,
544                 IDENTITY_INFO_PROP_USERNAME);
545 }
546
547 /**
548  * gsignond_identity_info_get_is_username_secret:
549  * @info: instance of #GSignondIdentityInfo
550  *
551  * Retrieves the is_username_secret flag from the info.
552  *
553  * Returns: the is_username_secret flag.
554  */
555 gboolean
556 gsignond_identity_info_get_is_username_secret (GSignondIdentityInfo *info)
557 {
558     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
559
560     GVariant *var = gsignond_dictionary_get (info->map,
561             GSIGNOND_IDENTITY_INFO_USERNAME_IS_SECRET);
562     return var ? g_variant_get_boolean (var) : FALSE;
563 }
564
565 /**
566  * gsignond_identity_info_set_username_secret:
567  * @info: instance of #GSignondIdentityInfo
568  *
569  * @store_secret: store_secret to be set
570  *
571  * Sets the store_secret of the info.
572  *
573  * Returns: TRUE if successful, FALSE otherwise.
574  */
575 gboolean
576 gsignond_identity_info_set_username_secret (
577         GSignondIdentityInfo *info,
578         gboolean username_secret)
579 {
580     gboolean res = FALSE;
581     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
582
583     if (gsignond_identity_info_get_is_username_secret(info) == username_secret)
584         return TRUE;
585
586     res = gsignond_dictionary_set (info->map,
587             GSIGNOND_IDENTITY_INFO_USERNAME_IS_SECRET,
588             g_variant_new_boolean(username_secret)) &&
589            gsignond_identity_info_set_edit_flags (info, 
590             IDENTITY_INFO_PROP_USERNAME_IS_SECRET);
591
592     return res;
593 }
594
595 /**
596  * gsignond_identity_info_get_secret:
597  * @info: instance of #GSignondIdentityInfo
598  *
599  * Retrieves the secret from the info.
600  *
601  * Returns: the secret if successful, NULL otherwise.
602  */
603 const gchar *
604 gsignond_identity_info_get_secret (GSignondIdentityInfo *info)
605 {
606     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
607
608     return info->secret;
609 }
610
611 /**
612  * gsignond_identity_info_set_secret:
613  * @info: instance of #GSignondIdentityInfo
614  *
615  * @secret: secret to be set
616  *
617  * Sets the secret of the info.
618  *
619  * Returns: TRUE if successful, FALSE otherwise.
620  */
621 gboolean
622 gsignond_identity_info_set_secret (
623         GSignondIdentityInfo *info,
624         const gchar *secret)
625 {
626     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
627
628     const gchar *current_secret = 
629                 gsignond_identity_info_get_secret (info);
630
631     if (g_strcmp0 (current_secret, secret) == 0) return TRUE;
632
633     if (info->secret) g_free (info->secret);
634
635     info->secret = g_strdup (secret);
636
637     return gsignond_identity_info_set_edit_flags (
638                 info, IDENTITY_INFO_PROP_SECRET);
639 }
640
641 /**
642  * gsignond_identity_info_get_store_secret:
643  * @info: instance of #GSignondIdentityInfo
644  *
645  * Retrieves the store_secret flag from the info.
646  *
647  * Returns: the store_secret flag.
648  */
649 gboolean
650 gsignond_identity_info_get_store_secret (GSignondIdentityInfo *info)
651 {
652     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
653
654     GVariant *var = gsignond_dictionary_get (info->map,
655             GSIGNOND_IDENTITY_INFO_STORESECRET);
656     return var ? g_variant_get_boolean (var) : FALSE;
657 }
658
659 /**
660  * gsignond_identity_info_set_store_secret:
661  * @info: instance of #GSignondIdentityInfo
662  *
663  * @store_secret: store_secret to be set
664  *
665  * Sets the store_secret of the info.
666  *
667  * Returns: TRUE if successful, FALSE otherwise.
668  */
669 gboolean
670 gsignond_identity_info_set_store_secret (
671         GSignondIdentityInfo *info,
672         gboolean store_secret)
673 {
674     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
675
676     if (gsignond_identity_info_get_store_secret (info) == store_secret)
677         return TRUE;
678
679     return gsignond_dictionary_set (info->map,
680                 GSIGNOND_IDENTITY_INFO_STORESECRET,
681                 g_variant_new_boolean(store_secret)) &&
682            gsignond_identity_info_set_edit_flags (info,
683                 IDENTITY_INFO_PROP_STORE_SECRET);
684 }
685
686 /**
687  * gsignond_identity_info_get_caption:
688  * @info: instance of #GSignondIdentityInfo
689  *
690  * Retrieves the caption from the info.
691  *
692  * Returns: the caption if successful, NULL otherwise.
693  */
694 const gchar *
695 gsignond_identity_info_get_caption (GSignondIdentityInfo *info)
696 {
697     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), NULL);
698
699     GVariant *var = gsignond_dictionary_get (info->map,
700                         GSIGNOND_IDENTITY_INFO_CAPTION);
701     return var ? g_variant_get_string (var, NULL) : NULL;
702 }
703
704 /**
705  * gsignond_identity_info_set_caption:
706  * @info: instance of #GSignondIdentityInfo
707  *
708  * @caption: caption to be set
709  *
710  * Sets the caption of the info.
711  *
712  * Returns: TRUE in case of success, FALSE otherwise.
713  */
714 gboolean
715 gsignond_identity_info_set_caption (
716         GSignondIdentityInfo *info,
717         const gchar *caption)
718 {
719     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
720     const gchar *current_caption = 
721         gsignond_identity_info_get_caption (info);
722
723     if (g_strcmp0 (current_caption, caption) == 0)
724         return TRUE;
725
726     if (!caption) {
727         return gsignond_dictionary_remove (info->map,
728                 GSIGNOND_IDENTITY_INFO_CAPTION) &&
729                gsignond_identity_info_set_edit_flags (info,
730                 IDENTITY_INFO_PROP_CAPTION);
731     }
732     return gsignond_dictionary_set (info->map,
733                 GSIGNOND_IDENTITY_INFO_CAPTION,
734                 g_variant_new_string (caption)) &&
735            gsignond_identity_info_set_edit_flags (info,
736                 IDENTITY_INFO_PROP_CAPTION);
737 }
738
739 /**
740  * gsignond_identity_info_get_realms:
741  * @info: instance of #GSignondIdentityInfo
742  *
743  * Retrieves the realms from the info.
744  *
745  * Returns: (transfer full): the realms if successful, NULL Otherwise.
746  * when done realms should be freed using g_sequence_free.
747  */
748 GSequence *
749 gsignond_identity_info_get_realms (GSignondIdentityInfo *info)
750 {
751     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), NULL);
752
753     GVariant *var = gsignond_dictionary_get (info->map,
754                         GSIGNOND_IDENTITY_INFO_REALMS);
755     return var ? gsignond_variant_to_sequence (var) : NULL;
756 }
757
758 /**
759  * gsignond_identity_info_set_realms:
760  * @info: instance of #GSignondIdentityInfo
761  *
762  * @realms: (transfer none): realms to be set
763  *
764  * Sets the realms of the info.
765  *
766  * Returns: TRUE if successful, FALSE otherwise.
767  */
768 gboolean
769 gsignond_identity_info_set_realms (
770         GSignondIdentityInfo *info,
771         GSequence *realms)
772 {
773     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
774
775     g_return_val_if_fail (realms != NULL, FALSE);
776     GVariant *current_realms = gsignond_dictionary_get (info->map,
777                         GSIGNOND_IDENTITY_INFO_REALMS);
778     GVariant *var_realms = gsignond_sequence_to_variant (realms);
779
780     if (current_realms != NULL &&
781         g_variant_equal (current_realms, var_realms) == TRUE) {
782         g_variant_unref (var_realms);
783         return TRUE;
784     }
785
786     return gsignond_dictionary_set (info->map,
787                 GSIGNOND_IDENTITY_INFO_REALMS,
788                 var_realms) &&
789            gsignond_identity_info_set_edit_flags (info,
790                 IDENTITY_INFO_PROP_REALMS);
791 }
792
793 /**
794  * gsignond_identity_info_get_methods:
795  * @info: instance of #GSignondIdentityInfo
796  *
797  * Retrieves the methods from the info whereas #GHashTable consists of
798  * (gchar*,GSequence*) and #GSequence is a sequence of gchar *.
799  *
800  * Returns: (transfer full): the methods if successful, NULL otherwise.
801  * when done, methods should be freed using g_hash_table_unref.
802  */
803 GHashTable *
804 gsignond_identity_info_get_methods (GSignondIdentityInfo *info)
805 {
806     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), NULL);
807
808     GHashTable *methods = NULL;
809     GVariant *var = gsignond_dictionary_get (info->map,
810                         GSIGNOND_IDENTITY_INFO_AUTHMETHODS);
811     if (var != NULL) {
812         GVariantIter iter;
813         gchar *vmethod;
814         gchar **vmechanisms = NULL;
815         GSequence *seq = NULL;
816
817         methods = g_hash_table_new_full ((GHashFunc) g_str_hash,
818                                          (GEqualFunc) g_str_equal,
819                                          (GDestroyNotify) g_free,
820                                          (GDestroyNotify) g_sequence_free);
821
822         g_variant_iter_init (&iter, var);
823         while (g_variant_iter_next (&iter, "{s^as}", &vmethod, &vmechanisms))
824         {
825             /* ownership is transferred */
826             seq = gsignond_array_to_sequence (vmechanisms);
827             g_hash_table_insert (methods, vmethod, seq);
828         }
829     }
830     return methods;
831 }
832
833 /**
834  * gsignond_identity_info_set_methods:
835  * @info: instance of #GSignondIdentityInfo
836  *
837  * @methods: (transfer none): methods to be set whereas #GHashTable consists of
838  * (gchar*,#GSequence*) and #GSequence is a sequence of gchar *.
839  *
840  * Sets the methods of the info.
841  *
842  * Returns: TRUE if successful, FALSE otherwise.
843  */
844 gboolean
845 gsignond_identity_info_set_methods (
846         GSignondIdentityInfo *info,
847         GHashTable *methods)
848 {
849     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
850
851     gchar **items = NULL;
852     GVariantBuilder builder;
853     GVariant *current_mehtods, *var_methods;
854
855     GHashTableIter iter;
856     const gchar *method;
857     GSequence *mechanisms = NULL;
858
859     g_return_val_if_fail (info != NULL, FALSE);
860     g_return_val_if_fail (methods != NULL, FALSE);
861
862     g_variant_builder_init (&builder, (const GVariantType *)"a{sas}");
863     g_hash_table_iter_init (&iter, methods);
864     while (g_hash_table_iter_next (&iter,
865                                    (gpointer)&method,
866                                    (gpointer)&mechanisms))
867     {
868         items = gsignond_sequence_to_array (mechanisms);
869         g_variant_builder_add (&builder, "{s^as}", method, items);
870         g_free (items);
871     }
872
873     var_methods = g_variant_builder_end (&builder);
874     current_mehtods = gsignond_dictionary_get (info->map,
875                         GSIGNOND_IDENTITY_INFO_AUTHMETHODS);
876
877     if (current_mehtods != NULL &&
878         g_variant_equal (current_mehtods, var_methods) == TRUE) {
879         g_variant_unref (var_methods);
880         return TRUE;
881     }
882
883     return gsignond_dictionary_set (info->map,
884                 GSIGNOND_IDENTITY_INFO_AUTHMETHODS,
885                 var_methods) &&
886            gsignond_identity_info_set_edit_flags (info,
887                 IDENTITY_INFO_PROP_METHODS);
888 }
889
890 /**
891  * gsignond_identity_info_get_mechanisms:
892  * @info: instance of #GSignondIdentityInfo
893  *
894  * @method: the method for which mechanisms are sought
895  *
896  * Retrieves the mechanisms from the info.
897  *
898  * Returns: (transfer full): the mechanisms if successful, NULL otherwise.
899  * when done, mechanisms should be freed using g_sequence_free; #GSequence is a
900  * sequence of gchar *.
901  */
902 GSequence *
903 gsignond_identity_info_get_mechanisms (
904         GSignondIdentityInfo *info,
905         const gchar *method)
906 {
907     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), NULL);
908
909     GVariant *var = NULL;
910     GSequence *mechanisms = NULL;
911
912     g_return_val_if_fail (method != NULL, NULL);
913
914     var = gsignond_dictionary_get (info->map,
915                 GSIGNOND_IDENTITY_INFO_AUTHMETHODS);
916     if (var != NULL) {
917         GVariantIter iter;
918         gchar *vmethod;
919         gchar **vmechanisms;
920
921         g_variant_iter_init (&iter, var);
922         while (g_variant_iter_next (&iter, "{s^as}", &vmethod, &vmechanisms))
923         {
924             /* ownership is transferred */
925             if (vmethod != NULL && g_strcmp0 (vmethod, method) == 0) {
926                 mechanisms = gsignond_array_to_sequence (vmechanisms);
927                 g_free (vmethod);
928                 break;
929             }
930             g_free (vmethod); vmethod = NULL;
931             g_strfreev (vmechanisms); vmechanisms = NULL;
932         }
933     }
934     return mechanisms;
935 }
936
937 /**
938  * gsignond_identity_info_remove_method:
939  * @info: instance of #GSignondIdentityInfo
940  *
941  * Removes the method from the info.
942  *
943  * Returns: TRUE if successful, FALSE otherwise.
944  */
945 gboolean
946 gsignond_identity_info_remove_method (
947         GSignondIdentityInfo *info,
948         const gchar *method)
949 {
950     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
951
952     GHashTable *methods = NULL;
953     gboolean ret = FALSE;
954
955     g_return_val_if_fail (method != NULL, FALSE);
956
957     methods = gsignond_identity_info_get_methods (info);
958     if (methods && g_hash_table_remove (methods, method)) {
959         ret = gsignond_identity_info_set_methods (info, methods);
960     }
961     if (methods)
962         g_hash_table_unref (methods);
963     return ret;
964 }
965
966 /**
967  * gsignond_identity_info_get_access_control_list:
968  * @info: instance of #GSignondIdentityInfo
969  *
970  * Retrieves the access control list from the info.
971  *
972  * Returns: (transfer full): the list if successful, NULL otherwise.
973  * when done, list should be freed using gsignond_security_context_list_free.
974  */
975 GSignondSecurityContextList *
976 gsignond_identity_info_get_access_control_list (GSignondIdentityInfo *info)
977 {
978     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), NULL);
979
980     GVariant *var = gsignond_dictionary_get (info->map,
981                         GSIGNOND_IDENTITY_INFO_ACL);
982     return var ? gsignond_security_context_list_from_variant (var) : NULL;
983 }
984
985 /**
986  * gsignond_identity_info_set_access_control_list:
987  * @info: instance of #GSignondIdentityInfo
988  *
989  * @acl: (transfer none): access control list to be set
990  *
991  * Sets the access control list of the info.
992  *
993  * Returns: TRUE if successful, FALSE otherwise.
994  */
995 gboolean
996 gsignond_identity_info_set_access_control_list (
997         GSignondIdentityInfo *info,
998         const GSignondSecurityContextList *acl)
999 {
1000     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
1001
1002     GVariant *current_acl = gsignond_dictionary_get (info->map,
1003                               GSIGNOND_IDENTITY_INFO_ACL);
1004     GVariant *var_acl = NULL;
1005
1006     if (!current_acl && !acl) return TRUE;
1007
1008     var_acl = gsignond_security_context_list_to_variant (acl);
1009     if (current_acl != NULL &&
1010         g_variant_equal (current_acl, var_acl) == TRUE) {
1011         g_variant_unref (var_acl);
1012         return TRUE;
1013     }
1014
1015     g_return_val_if_fail (acl != NULL, FALSE);
1016     return gsignond_dictionary_set (info->map,
1017                 GSIGNOND_IDENTITY_INFO_ACL, var_acl) &&
1018            gsignond_identity_info_set_edit_flags (info,
1019                 IDENTITY_INFO_PROP_ACL);
1020 }
1021
1022 /**
1023  * gsignond_identity_info_get_owner:
1024  * @info: instance of #GSignondIdentityInfo
1025  *
1026  * Retrieves the id from the info.
1027  *
1028  * Returns: (transfer full): the owner if successful, NULL otherwise.
1029  * when done, owner list should be freed using
1030  * gsignond_security_context_free.
1031  */
1032 GSignondSecurityContext *
1033 gsignond_identity_info_get_owner (GSignondIdentityInfo *info)
1034 {
1035     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), NULL);
1036
1037     GVariant *var = gsignond_dictionary_get (info->map,
1038                                              GSIGNOND_IDENTITY_INFO_OWNER);
1039     return var ? gsignond_security_context_from_variant (var) : NULL;
1040 }
1041
1042 /**
1043  * gsignond_identity_info_set_owner:
1044  * @info: instance of #GSignondIdentityInfo
1045  *
1046  * @owner: (transfer none): owner to be set
1047  *
1048  * Sets the owner of the info.
1049  *
1050  * Returns: TRUE if successful, FALSE otherwise.
1051  */
1052 gboolean
1053 gsignond_identity_info_set_owner (
1054         GSignondIdentityInfo *info,
1055         const GSignondSecurityContext *owner)
1056 {
1057     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
1058
1059     g_return_val_if_fail (owner != NULL, FALSE);
1060     GSignondSecurityContext *current_owner = 
1061         gsignond_identity_info_get_owner (info);
1062
1063     if (current_owner != NULL &&
1064         gsignond_security_context_compare (current_owner, owner) == 0)
1065         return TRUE;
1066
1067     return (gsignond_dictionary_set (info->map,
1068                                      GSIGNOND_IDENTITY_INFO_OWNER,
1069                                      gsignond_security_context_to_variant (owner)) &&
1070             gsignond_identity_info_set_edit_flags (info,
1071                                                    IDENTITY_INFO_PROP_OWNER));
1072 }
1073
1074 /**
1075  * gsignond_identity_info_get_validated:
1076  * @info: instance of #GSignondIdentityInfo
1077  *
1078  * Retrieves the validated flag from the info.
1079  *
1080  * Returns: the validated flag.
1081  */
1082 gboolean
1083 gsignond_identity_info_get_validated (GSignondIdentityInfo *info)
1084 {
1085     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
1086
1087     GVariant *var = gsignond_dictionary_get (info->map,
1088                         GSIGNOND_IDENTITY_INFO_VALIDATED);
1089     return var ? g_variant_get_boolean (var) : FALSE;
1090 }
1091
1092 /**
1093  * gsignond_identity_info_set_validated:
1094  * @info: instance of #GSignondIdentityInfo
1095  *
1096  * @validated: validated flag to be set
1097  *
1098  * Sets the validated flag of the info.
1099  *
1100  * Returns: TRUE if successful, FALSE otherwise.
1101  */
1102 gboolean
1103 gsignond_identity_info_set_validated (
1104         GSignondIdentityInfo *info,
1105         gboolean validated)
1106 {
1107     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
1108
1109     if (gsignond_identity_info_get_validated (info) == validated)
1110         return TRUE;
1111
1112     return gsignond_dictionary_set (info->map,
1113                 GSIGNOND_IDENTITY_INFO_VALIDATED,
1114                 g_variant_new_boolean (validated)) &&
1115            gsignond_identity_info_set_edit_flags (info,
1116                 IDENTITY_INFO_PROP_VALIDATED);
1117 }
1118
1119 /**
1120  * gsignond_identity_info_get_identity_type:
1121  * @info: instance of #GSignondIdentityInfo
1122  *
1123  * Retrieves the type from the info.
1124  *
1125  * Returns: the type; negative type is returned in case of failure.
1126  */
1127 guint32
1128 gsignond_identity_info_get_identity_type (GSignondIdentityInfo *info)
1129 {
1130     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), 0);
1131
1132     GVariant *var = gsignond_dictionary_get (info->map,
1133                         GSIGNOND_IDENTITY_INFO_TYPE);
1134     return var ? g_variant_get_int32 (var) : 0;
1135 }
1136
1137 /**
1138  * gsignond_identity_info_set_identity_type:
1139  * @info: instance of #GSignondIdentityInfo
1140  *
1141  * @type: type to be set
1142  *
1143  * Sets the type of the info.
1144  *
1145  * Returns: TRUE if successful, FALSE otherwise.
1146  */
1147 gboolean
1148 gsignond_identity_info_set_identity_type (
1149         GSignondIdentityInfo *info,
1150         guint32 type)
1151 {
1152     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
1153
1154     if (gsignond_identity_info_get_identity_type (info) == type)
1155         return TRUE;
1156
1157     return gsignond_dictionary_set (info->map,
1158                 GSIGNOND_IDENTITY_INFO_TYPE,
1159                 g_variant_new_int32 (type)) &&
1160            gsignond_identity_info_set_edit_flags (info,
1161                 IDENTITY_INFO_PROP_TYPE);
1162 }
1163
1164 /**
1165  * gsignond_identity_info_compare:
1166  * @info: instance1 of #GSignondIdentityInfo
1167  *
1168  * @other: instance2 of #GSignondIdentityInfo
1169  *
1170  * Compares two instances of #GSignondIdentityInfo for equality.
1171  *
1172  * Returns: TRUE if the two instances are equal, FALSE otherwise.
1173  */
1174 gboolean
1175 gsignond_identity_info_compare (
1176         GSignondIdentityInfo *info,
1177         GSignondIdentityInfo *other)
1178 {
1179     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), FALSE);
1180     g_return_val_if_fail (other && GSIGNOND_IS_IDENTITY_INFO (other), FALSE);
1181
1182     GSequence *info_realms = NULL, *other_realms = NULL;
1183     GHashTable *info_methods = NULL, *other_methods = NULL;
1184     GSignondSecurityContextList *info_acl = NULL, *other_acl = NULL;
1185     GSignondSecurityContext *info_owner = NULL, *other_owner = NULL;
1186     gboolean equal = FALSE;
1187
1188     if (info == other)
1189         return TRUE;
1190
1191     if (info == NULL || other == NULL)
1192         return FALSE;
1193
1194     if (gsignond_identity_info_get_id (info) !=
1195         gsignond_identity_info_get_id (other)) {
1196         return FALSE;
1197     }
1198
1199     if (g_strcmp0 (gsignond_identity_info_get_username (info),
1200         gsignond_identity_info_get_username (other)) != 0) {
1201         return FALSE;
1202     }
1203
1204     if (g_strcmp0 (gsignond_identity_info_get_secret (info),
1205         gsignond_identity_info_get_secret (other)) != 0) {
1206         return FALSE;
1207     }
1208
1209     if (gsignond_identity_info_get_store_secret (info) !=
1210         gsignond_identity_info_get_store_secret (other)) {
1211         return FALSE;
1212     }
1213
1214     if (g_strcmp0 (gsignond_identity_info_get_caption (info),
1215         gsignond_identity_info_get_caption (other)) != 0) {
1216         return FALSE;
1217     }
1218
1219     info_realms = gsignond_identity_info_get_realms (info);
1220     other_realms = gsignond_identity_info_get_realms (other);
1221     equal = _gsignond_identity_info_seq_cmp (info_realms, other_realms);
1222     if (info_realms) g_sequence_free (info_realms);
1223     if (other_realms) g_sequence_free (other_realms);
1224     if (!equal) {
1225         return FALSE;
1226     }
1227
1228     info_methods = gsignond_identity_info_get_methods (info);
1229     other_methods = gsignond_identity_info_get_methods (other);
1230     equal = _gsignond_identity_info_methods_cmp (info_methods, other_methods);
1231     if (info_methods) g_hash_table_unref (info_methods);
1232     if (other_methods) g_hash_table_unref (other_methods);
1233     if (!equal) {
1234         return FALSE;
1235     }
1236
1237     info_acl = gsignond_identity_info_get_access_control_list (info);
1238     if (info_acl)
1239         info_acl = g_list_sort (
1240                         info_acl,
1241                         (GCompareFunc)gsignond_security_context_compare);
1242     other_acl = gsignond_identity_info_get_access_control_list (other);
1243     if (other_acl)
1244         other_acl = g_list_sort (
1245                         other_acl,
1246                         (GCompareFunc)gsignond_security_context_compare);
1247     equal = _gsignond_identity_info_sec_context_list_cmp (info_acl, other_acl);
1248     if (info_acl) gsignond_security_context_list_free (info_acl);
1249     if (other_acl) gsignond_security_context_list_free (other_acl);
1250     if (!equal) {
1251         return FALSE;
1252     }
1253
1254     info_owner = gsignond_identity_info_get_owner (info);
1255     other_owner = gsignond_identity_info_get_owner (other);
1256     equal = gsignond_security_context_match (info_owner, other_owner);
1257     if (info_owner) gsignond_security_context_free (info_owner);
1258     if (other_owner) gsignond_security_context_free (other_owner);
1259     if (!equal) {
1260         return FALSE;
1261     }
1262
1263     if (gsignond_identity_info_get_validated (info) !=
1264         gsignond_identity_info_get_validated (other)) {
1265         return FALSE;
1266     }
1267
1268     if (gsignond_identity_info_get_identity_type (info) !=
1269         gsignond_identity_info_get_identity_type (other)) {
1270         return FALSE;
1271     }
1272
1273     return TRUE;
1274 }
1275
1276 /**
1277  * gsignond_identity_info_to_variant:
1278  * @info: instance of #GSignondIdentityInfo
1279  *
1280  * Converts the #GSignondIndentityInfo to a #GVariant.
1281  *
1282  * Returns: (transfer full): #GVariant object if successful, NULL otherwise.
1283  */
1284 GVariant *
1285 gsignond_identity_info_to_variant (GSignondIdentityInfo *info)
1286 {
1287     gboolean username_is_secret ;
1288
1289     g_return_val_if_fail (info && GSIGNOND_IS_IDENTITY_INFO (info), NULL);
1290
1291     username_is_secret = gsignond_identity_info_get_is_username_secret (info);
1292
1293     if (username_is_secret)
1294         return gsignond_dictionary_to_variant (info->map);
1295     else {
1296         GVariant *vdict = NULL;
1297         GVariantBuilder *builder = 
1298                 gsignond_dictionary_to_variant_builder (info->map);
1299         if (!builder) return NULL;
1300
1301         g_variant_builder_add (builder, "{sv}", GSIGNOND_IDENTITY_INFO_USERNAME,
1302                 g_variant_new_string (info->username ? info->username : ""));
1303
1304         vdict = g_variant_builder_end (builder);
1305
1306         g_variant_builder_unref (builder);
1307
1308         return vdict;
1309     }
1310 }
1311
1312 void
1313 gsignond_identity_info_list_free (GSignondIdentityInfoList *list)
1314 {
1315     g_return_if_fail (list != NULL);
1316     g_list_free_full (list, (GDestroyNotify)gsignond_identity_info_unref);
1317 }