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