1 /*
2  * Copyright (C) 2008 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General
15  * Public License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17  * Boston, MA 02111-1307, USA.
18  *
19  * Author: David Zeuthen <davidz@redhat.com>
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 #endif
25 
26 #include <string.h>
27 #include "polkitimplicitauthorization.h"
28 #include "polkitdetails.h"
29 
30 #include "polkitprivate.h"
31 
32 /**
33  * SECTION:polkitdetails
34  * @title: PolkitDetails
35  * @short_description: Object used for passing details
36  * @stability: Stable
37  *
38  * An object used for passing details around.
39  */
40 
41 /**
42  * PolkitDetails:
43  *
44  * The #PolkitDetails struct should not be accessed directly.
45  */
46 struct _PolkitDetails
47 {
48   GObject parent_instance;
49 
50   GHashTable *hash;
51 };
52 
53 struct _PolkitDetailsClass
54 {
55   GObjectClass parent_class;
56 };
57 
58 G_DEFINE_TYPE (PolkitDetails, polkit_details, G_TYPE_OBJECT);
59 
60 static void
polkit_details_init(PolkitDetails * details)61 polkit_details_init (PolkitDetails *details)
62 {
63 }
64 
65 static void
polkit_details_finalize(GObject * object)66 polkit_details_finalize (GObject *object)
67 {
68   PolkitDetails *details;
69 
70   details = POLKIT_DETAILS (object);
71 
72   if (details->hash != NULL)
73     g_hash_table_unref (details->hash);
74 
75   if (G_OBJECT_CLASS (polkit_details_parent_class)->finalize != NULL)
76     G_OBJECT_CLASS (polkit_details_parent_class)->finalize (object);
77 }
78 
79 static void
polkit_details_class_init(PolkitDetailsClass * klass)80 polkit_details_class_init (PolkitDetailsClass *klass)
81 {
82   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
83 
84   gobject_class->finalize = polkit_details_finalize;
85 }
86 
87 /**
88  * polkit_details_new:
89  *
90  * Creates a new #PolkitDetails object.
91  *
92  * Returns: A #PolkitDetails object. Free with g_object_unref().
93  */
94 PolkitDetails *
polkit_details_new(void)95 polkit_details_new (void)
96 {
97   PolkitDetails *details;
98 
99   details = POLKIT_DETAILS (g_object_new (POLKIT_TYPE_DETAILS, NULL));
100 
101   return details;
102 }
103 
104 /* private */
105 static PolkitDetails *
polkit_details_new_for_hash(GHashTable * hash)106 polkit_details_new_for_hash (GHashTable *hash)
107 {
108   PolkitDetails *details;
109 
110   details = POLKIT_DETAILS (g_object_new (POLKIT_TYPE_DETAILS, NULL));
111   if (hash != NULL)
112     details->hash = g_hash_table_ref (hash);
113 
114   return details;
115 }
116 
117 /**
118  * polkit_details_lookup:
119  * @details: A #PolkitDetails.
120  * @key: A key.
121  *
122  * Gets the value for @key on @details.
123  *
124  * Returns: (allow-none): %NULL if there is no value for @key, otherwise a string owned by @details.
125  */
126 const gchar *
polkit_details_lookup(PolkitDetails * details,const gchar * key)127 polkit_details_lookup (PolkitDetails *details,
128                        const gchar   *key)
129 {
130   g_return_val_if_fail (POLKIT_IS_DETAILS (details), NULL);
131   g_return_val_if_fail (key != NULL, NULL);
132   if (details->hash == NULL)
133     return NULL;
134   else
135     return g_hash_table_lookup (details->hash, key);
136 }
137 
138 /**
139  * polkit_details_insert:
140  * @details: A #PolkitDetails.
141  * @key: A key.
142  * @value: (allow-none): A value.
143  *
144  * Inserts a copy of @key and @value on @details.
145  *
146  * If @value is %NULL, the key will be removed.
147  */
148 void
polkit_details_insert(PolkitDetails * details,const gchar * key,const gchar * value)149 polkit_details_insert (PolkitDetails *details,
150                        const gchar   *key,
151                        const gchar   *value)
152 {
153   g_return_if_fail (POLKIT_IS_DETAILS (details));
154   g_return_if_fail (key != NULL);
155   if (details->hash == NULL)
156     details->hash = g_hash_table_new_full (g_str_hash,
157                                            g_str_equal,
158                                            g_free,
159                                            g_free);
160   if (value != NULL)
161     g_hash_table_insert (details->hash, g_strdup (key), g_strdup (value));
162   else
163     g_hash_table_remove (details->hash, key);
164 }
165 
166 /**
167  * polkit_details_get_keys:
168  * @details: A #PolkitDetails.
169  *
170  * Gets a list of all keys on @details.
171  *
172  * Returns: (transfer full) (allow-none): %NULL if there are no keys
173  * otherwise an array of strings that should be freed with
174  * g_strfreev().
175  */
176 gchar **
polkit_details_get_keys(PolkitDetails * details)177 polkit_details_get_keys (PolkitDetails *details)
178 {
179   GList *keys, *l;
180   gchar **ret;
181   guint n;
182 
183   g_return_val_if_fail (POLKIT_IS_DETAILS (details), NULL);
184 
185   if (details->hash == NULL)
186     return NULL;
187 
188   keys = g_hash_table_get_keys (details->hash);
189   ret = g_new0 (gchar*, g_list_length (keys) + 1);
190   for (l = keys, n = 0; l != NULL; l = l->next, n++)
191     ret[n] = g_strdup (l->data);
192 
193   g_list_free (keys);
194 
195   return ret;
196 }
197 
198 /* Note that this returns a floating value. */
199 GVariant *
polkit_details_to_gvariant(PolkitDetails * details)200 polkit_details_to_gvariant (PolkitDetails *details)
201 {
202   GVariantBuilder builder;
203 
204   g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
205   if (details != NULL && details->hash != NULL)
206     {
207       GHashTableIter hash_iter;
208       const gchar *key;
209       const gchar *value;
210 
211       g_hash_table_iter_init (&hash_iter, details->hash);
212       while (g_hash_table_iter_next (&hash_iter, (gpointer) &key, (gpointer) &value))
213         g_variant_builder_add (&builder, "{ss}", key, value);
214     }
215   return g_variant_builder_end (&builder);
216 }
217 
218 PolkitDetails *
polkit_details_new_for_gvariant(GVariant * value)219 polkit_details_new_for_gvariant (GVariant *value)
220 {
221   PolkitDetails *ret;
222   GHashTable *hash;
223   GVariantIter iter;
224   gchar *hash_key;
225   gchar *hash_value;
226 
227   hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
228   g_variant_iter_init (&iter, value);
229   while (g_variant_iter_next (&iter, "{ss}", &hash_key, &hash_value))
230     g_hash_table_insert (hash, hash_key, hash_value);
231   ret = polkit_details_new_for_hash (hash);
232   g_hash_table_unref (hash);
233   return ret;
234 }
235 
236