1 /* keyfileutils.c: useful functions for GKeyFile
2 * vim: set ts=2 sw=2 et: */
3
4 /*
5 * Copyright (C) 2007 Vincent Untz <vuntz@gnome.org>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 * USA.
21 */
22
23 #include <string.h>
24
25 #include "keyfileutils.h"
26
27 gboolean
dfu_key_file_rename_group(GKeyFile * keyfile,const char * oldgroup,const char * newgroup)28 dfu_key_file_rename_group (GKeyFile *keyfile,
29 const char *oldgroup,
30 const char *newgroup)
31 {
32 char **keys;
33 char *value;
34 unsigned int i;
35
36 g_return_val_if_fail (keyfile != NULL, FALSE);
37
38 if (!g_key_file_has_group (keyfile, oldgroup))
39 return TRUE;
40
41 keys = g_key_file_get_keys (keyfile, oldgroup, NULL, NULL);
42 for (i = 0; keys[i] != NULL; i++) {
43 value = g_key_file_get_value (keyfile, oldgroup, keys[i], NULL);
44 g_key_file_set_value (keyfile, newgroup, keys[i], value);
45 g_free (value);
46
47 value = g_key_file_get_comment (keyfile, oldgroup, keys[i], NULL);
48 if (value) {
49 g_key_file_set_comment (keyfile, newgroup, keys[i], value, NULL);
50 g_free (value);
51 }
52 }
53 g_strfreev (keys);
54
55 value = g_key_file_get_comment (keyfile, oldgroup, NULL, NULL);
56 if (value) {
57 g_key_file_set_comment (keyfile, newgroup, NULL, value, NULL);
58 g_free (value);
59 }
60
61 g_key_file_remove_group (keyfile, oldgroup, NULL);
62
63 return TRUE;
64 }
65
66 void
dfu_key_file_drop_locale_strings(GKeyFile * keyfile,const char * group,const char * key)67 dfu_key_file_drop_locale_strings (GKeyFile *keyfile,
68 const char *group,
69 const char *key)
70 {
71 char **keys;
72 gsize len;
73 char *prefix;
74 gsize i;
75
76 keys = g_key_file_get_keys (keyfile, group, &len, NULL);
77 prefix = g_strdup_printf ("%s[", key);
78
79 for (i = 0; i < len; i++)
80 {
81 if (g_str_has_prefix (keys[i], prefix))
82 g_key_file_remove_key (keyfile, group, keys[i], NULL);
83 }
84
85 g_free (prefix);
86 g_strfreev (keys);
87 }
88
89 static gboolean
_dfu_key_file_copy_key_helper(GKeyFile * keyfile,const char * fromgroup,const char * fromkey,const char * togroup,const char * tokey)90 _dfu_key_file_copy_key_helper (GKeyFile *keyfile,
91 const char *fromgroup,
92 const char *fromkey,
93 const char *togroup,
94 const char *tokey)
95 {
96 char *value;
97
98 if (!g_key_file_has_group (keyfile, fromgroup))
99 return FALSE;
100
101 value = g_key_file_get_value (keyfile, fromgroup, fromkey, NULL);
102 if (!value)
103 return FALSE;
104
105 g_key_file_set_value (keyfile, togroup, tokey, value);
106
107 g_free (value);
108
109 return TRUE;
110 }
111
112 gboolean
dfu_key_file_copy_key(GKeyFile * keyfile,const char * fromgroup,const char * fromkey,const char * togroup,const char * tokey)113 dfu_key_file_copy_key (GKeyFile *keyfile,
114 const char *fromgroup,
115 const char *fromkey,
116 const char *togroup,
117 const char *tokey)
118 {
119 char **fromkeys;
120 gsize len;
121 char *fromprefix;
122 gsize i;
123
124 g_return_val_if_fail (keyfile != NULL, FALSE);
125 g_return_val_if_fail (fromgroup != NULL, FALSE);
126 g_return_val_if_fail (fromkey != NULL, FALSE);
127 g_return_val_if_fail (togroup != NULL, FALSE);
128 g_return_val_if_fail (tokey != NULL, FALSE);
129
130 if (!_dfu_key_file_copy_key_helper (keyfile, fromgroup, fromkey,
131 togroup, tokey))
132 return FALSE;
133
134 /* Also copy translations if we're not dealing with localized keys already
135 * (first drop old ones) */
136 if (strchr (fromkey, '[') != NULL || strchr (tokey, '[') != NULL)
137 return TRUE;
138
139 dfu_key_file_drop_locale_strings (keyfile, togroup, tokey);
140
141 fromkeys = g_key_file_get_keys (keyfile, fromgroup, &len, NULL);
142 fromprefix = g_strdup_printf ("%s[", fromkey);
143
144 for (i = 0; i < len; i++)
145 {
146 if (g_str_has_prefix (fromkeys[i], fromprefix))
147 {
148 const char *locale = fromkeys[i] + strlen (fromkey);
149 char *tolocalekey = g_strdup_printf ("%s%s", tokey, locale);
150 _dfu_key_file_copy_key_helper (keyfile, fromgroup, fromkeys[i],
151 togroup, tolocalekey);
152 g_free (tolocalekey);
153 }
154 }
155
156 g_free (fromprefix);
157 g_strfreev (fromkeys);
158
159 return TRUE;
160 }
161
162 void
dfu_key_file_merge_list(GKeyFile * keyfile,const char * group,const char * key,const char * to_merge)163 dfu_key_file_merge_list (GKeyFile *keyfile,
164 const char *group,
165 const char *key,
166 const char *to_merge)
167 {
168 char **values;
169 char *value;
170 char *str;
171 int i;
172
173 g_return_if_fail (keyfile != NULL);
174
175 values = g_key_file_get_string_list (keyfile, group, key, NULL, NULL);
176
177 if (values) {
178 for (i = 0; values[i] != NULL; i++) {
179 if (!strcmp (values[i], to_merge)) {
180 g_strfreev (values);
181 return;
182 }
183 }
184
185 g_strfreev (values);
186 }
187
188 value = g_key_file_get_value (keyfile, group, key, NULL);
189
190 if (value) {
191 size_t len = strlen (value);
192 if (len > 0 && value[len - 1] != ';') {
193 str = g_strconcat (value, ";", to_merge, ";", NULL);
194 } else {
195 str = g_strconcat (value, to_merge, ";", NULL);
196 }
197 } else
198 str = g_strconcat (to_merge, ";", NULL);
199
200 g_key_file_set_value (keyfile, group, key, str);
201
202 g_free (value);
203 g_free (str);
204 }
205
206 void
dfu_key_file_remove_list(GKeyFile * keyfile,const char * group,const char * key,const char * to_remove)207 dfu_key_file_remove_list (GKeyFile *keyfile,
208 const char *group,
209 const char *key,
210 const char *to_remove)
211 {
212 char **values;
213 GString *value;
214 gboolean found;
215 int i;
216
217 g_return_if_fail (keyfile != NULL);
218
219 found = FALSE;
220
221 value = g_string_new ("");
222 values = g_key_file_get_string_list (keyfile, group, key, NULL, NULL);
223
224 if (values) {
225 for (i = 0; values[i] != NULL; i++) {
226 if (!strcmp (values[i], to_remove))
227 found = TRUE;
228 else
229 g_string_append_printf (value, "%s;", values[i]);
230 }
231
232 g_strfreev (values);
233 }
234
235 if (!found) {
236 g_string_free (value, TRUE);
237 return;
238 }
239
240 if (!value->str || value->str[0] == '\0')
241 g_key_file_remove_key (keyfile, group, key, NULL);
242 else
243 g_key_file_set_value (keyfile, group, key, value->str);
244
245 g_string_free (value, TRUE);
246 }
247
248 //FIXME: kill this when bug #309224 is fixed
249 gboolean
dfu_key_file_to_path(GKeyFile * keyfile,const char * path,GError ** error)250 dfu_key_file_to_path (GKeyFile *keyfile,
251 const char *path,
252 GError **error)
253 {
254 char *filename;
255 GError *write_error;
256 char *data;
257 gsize length;
258 gboolean res;
259
260 g_return_val_if_fail (keyfile != NULL, FALSE);
261 g_return_val_if_fail (path != NULL, FALSE);
262
263 write_error = NULL;
264 data = g_key_file_to_data (keyfile, &length, &write_error);
265 if (write_error) {
266 g_propagate_error (error, write_error);
267 return FALSE;
268 }
269
270 filename = g_filename_from_utf8 (path, -1, NULL, NULL, &write_error);
271
272 if (write_error) {
273 g_propagate_error (error, write_error);
274 g_free (data);
275 return FALSE;
276 }
277
278 res = g_file_set_contents (filename, data, length, &write_error);
279 g_free (filename);
280
281 if (write_error) {
282 g_propagate_error (error, write_error);
283 g_free (data);
284 return FALSE;
285 }
286
287 g_free (data);
288 return res;
289 }
290