~lightdm-gtk-greeter-team/lightdm-gtk-greeter/trunk

« back to all changes in this revision

Viewing changes to src/greeterconfiguration.c

  • Committer: Sean Davis
  • Date: 2014-05-04 11:59:11 UTC
  • Revision ID: smd.seandavis@gmail.com-20140504115911-k5t16da98dlcvmei
Tags: 1.8.5
Update version number

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
#include <glib.h>
3
 
 
4
 
#include "greeterconfiguration.h"
5
 
 
6
 
 
7
 
static GKeyFile* greeter_config = NULL;
8
 
static GKeyFile* state_config = NULL;
9
 
static gchar* state_filename = NULL;
10
 
 
11
 
static GKeyFile* get_file_for_group (const gchar** group);
12
 
static void save_key_file           (GKeyFile* config, const gchar* path);
13
 
static gboolean get_int             (GKeyFile* config, const gchar* group, const gchar* key, gint* out);
14
 
static gboolean get_bool            (GKeyFile* config, const gchar* group, const gchar* key, gboolean* out);
15
 
 
16
 
/* Implementation */
17
 
 
18
 
static GList*
19
 
append_directory_content(GList* files, const gchar* path)
20
 
{
21
 
    GError *error = NULL;
22
 
    GList  *content = NULL;
23
 
    GList  *list_iter = NULL;
24
 
    gchar  *full_path = g_build_filename(path, "lightdm", "lightdm-gtk-greeter.conf.d", NULL);
25
 
    GDir   *dir = g_dir_open(full_path, 0, &error);
26
 
 
27
 
    if(error && !g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
28
 
        g_warning("[Configuration] Failed to read configuration directory '%s': %s", full_path, error->message);
29
 
    g_clear_error(&error);
30
 
 
31
 
    if(dir)
32
 
    {
33
 
        const gchar *name;
34
 
        while((name = g_dir_read_name(dir)))
35
 
        {
36
 
            if(!g_str_has_suffix(name, ".conf"))
37
 
                continue;
38
 
            content = g_list_prepend(content, g_build_filename(full_path, name, NULL));
39
 
        }
40
 
        g_dir_close(dir);
41
 
 
42
 
        if(content)
43
 
            content = g_list_sort(content, (GCompareFunc)g_strcmp0);
44
 
    }
45
 
 
46
 
    content = g_list_append(content, g_build_filename(path, "lightdm", "lightdm-gtk-greeter.conf", NULL));
47
 
 
48
 
    for(list_iter = content; list_iter; list_iter = g_list_next(list_iter))
49
 
    {
50
 
        if(g_file_test(list_iter->data, G_FILE_TEST_IS_REGULAR))
51
 
            files = g_list_prepend(files, list_iter->data);
52
 
        else
53
 
            g_free(list_iter->data);
54
 
    }
55
 
 
56
 
    g_list_free(content);
57
 
    g_free(full_path);
58
 
    return files;
59
 
}
60
 
 
61
 
void
62
 
config_init(void)
63
 
{
64
 
    GKeyFile            *tmp_config = NULL;
65
 
    GError              *error = NULL;
66
 
    GList               *files = NULL;
67
 
    GList               *file_iter = NULL;
68
 
    const gchar* const  *dirs;
69
 
    gchar               *state_config_dir;
70
 
    gchar               *config_path_tmp;
71
 
    gchar               *config_path;
72
 
    gint                i;
73
 
 
74
 
    state_config_dir = g_build_filename(g_get_user_cache_dir(), "lightdm-gtk-greeter", NULL);
75
 
    state_filename = g_build_filename(state_config_dir, "state", NULL);
76
 
    g_mkdir_with_parents(state_config_dir, 0775);
77
 
    g_free(state_config_dir);
78
 
 
79
 
    state_config = g_key_file_new();
80
 
    g_key_file_load_from_file(state_config, state_filename, G_KEY_FILE_NONE, &error);
81
 
    if (error && !g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
82
 
        g_warning("[Configuration] Failed to load state from %s: %s", state_filename, error->message);
83
 
    g_clear_error(&error);
84
 
 
85
 
    dirs = g_get_system_data_dirs();
86
 
    for(i = 0; dirs[i]; ++i)
87
 
        files = append_directory_content(files, dirs[i]);
88
 
 
89
 
    dirs = g_get_system_config_dirs();
90
 
    for(i = 0; dirs[i]; ++i)
91
 
        files = append_directory_content(files, dirs[i]);
92
 
 
93
 
    config_path_tmp = g_path_get_dirname(CONFIG_FILE);
94
 
    config_path = g_path_get_dirname(config_path_tmp);
95
 
    files = append_directory_content(files, config_path);
96
 
    g_free(config_path_tmp);
97
 
    g_free(config_path);
98
 
 
99
 
    files = g_list_reverse(files);
100
 
 
101
 
    for(file_iter = files; file_iter; file_iter = g_list_next(file_iter))
102
 
    {
103
 
        const gchar  *path = file_iter->data;
104
 
        gchar       **group_iter = NULL;
105
 
        gchar       **groups;
106
 
 
107
 
        if(!tmp_config)
108
 
            tmp_config = g_key_file_new();
109
 
 
110
 
        if(!g_key_file_load_from_file(tmp_config, path, G_KEY_FILE_NONE, &error))
111
 
        {
112
 
            if(error)
113
 
            {
114
 
                g_warning("[Configuration] Failed to read file '%s': %s", path, error->message);
115
 
                g_clear_error(&error);
116
 
            }
117
 
            else
118
 
                g_warning("[Configuration] Failed to read file '%s'", path);
119
 
            continue;
120
 
        }
121
 
        g_message("[Configuration] Reading file: %s", path);
122
 
 
123
 
        if(!greeter_config)
124
 
        {
125
 
            greeter_config = tmp_config;
126
 
            tmp_config = NULL;
127
 
            continue;
128
 
        }
129
 
 
130
 
        groups = g_key_file_get_groups(tmp_config, NULL);
131
 
        for(group_iter = groups; *group_iter; ++group_iter)
132
 
        {
133
 
            gchar **key_iter = NULL;
134
 
            gchar **keys = NULL;
135
 
            if(**group_iter == '-')
136
 
            {
137
 
                g_key_file_remove_group(greeter_config, *group_iter + 1, NULL);
138
 
                continue;
139
 
            }
140
 
 
141
 
            keys = g_key_file_get_keys(tmp_config, *group_iter, NULL, NULL);
142
 
            for(key_iter = keys; *key_iter; ++key_iter)
143
 
            {
144
 
                gchar *value = NULL;
145
 
 
146
 
                if(**key_iter == '-')
147
 
                {
148
 
                    g_key_file_remove_key(greeter_config, *group_iter, *key_iter + 1, NULL);
149
 
                    continue;
150
 
                }
151
 
 
152
 
                value = g_key_file_get_value(tmp_config, *group_iter, *key_iter, NULL);
153
 
                if(value)
154
 
                {
155
 
                    g_key_file_set_value(greeter_config, *group_iter, *key_iter, value);
156
 
                    g_free(value);
157
 
                }
158
 
            }
159
 
            g_strfreev(keys);
160
 
        }
161
 
        g_strfreev(groups);
162
 
    }
163
 
    if (tmp_config)
164
 
        g_key_file_unref(tmp_config);
165
 
    g_list_free_full(files, g_free);
166
 
 
167
 
    if(!greeter_config)
168
 
        greeter_config = g_key_file_new();
169
 
}
170
 
 
171
 
static GKeyFile*
172
 
get_file_for_group(const gchar** group)
173
 
{
174
 
    if(!*group)
175
 
        *group = CONFIG_GROUP_DEFAULT;
176
 
 
177
 
    if(*group[0] == '/')
178
 
    {
179
 
        (*group)++;
180
 
        return state_config;
181
 
    }
182
 
 
183
 
    return greeter_config;
184
 
}
185
 
 
186
 
static void
187
 
save_key_file(GKeyFile* config, const gchar* path)
188
 
{
189
 
    GError* error = NULL;
190
 
    gsize data_length = 0;
191
 
    gchar* data = g_key_file_to_data(config, &data_length, &error);
192
 
 
193
 
    if(error)
194
 
    {
195
 
        g_warning("[Configuration] Failed to save file: %s", error->message);
196
 
        g_clear_error(&error);
197
 
    }
198
 
 
199
 
    if(data)
200
 
    {
201
 
        g_file_set_contents(path, data, data_length, &error);
202
 
        if(error)
203
 
        {
204
 
            g_warning("[Configuration] Failed to save file: %s", error->message);
205
 
            g_clear_error(&error);
206
 
        }
207
 
        g_free(data);
208
 
    }
209
 
}
210
 
 
211
 
static gboolean
212
 
get_int(GKeyFile* config, const gchar* group, const gchar* key, gint* out)
213
 
{
214
 
    GError* error = NULL;
215
 
    *out = g_key_file_get_integer(config, group, key, &error);
216
 
    if(!error)
217
 
        return TRUE;
218
 
    if(g_error_matches(error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE))
219
 
        g_warning("[Configuration] Failed to parse integer value [%s] %s: %s", group, key, error->message);
220
 
    g_clear_error(&error);
221
 
    return FALSE;
222
 
}
223
 
 
224
 
static gboolean
225
 
get_bool(GKeyFile* config, const gchar* group, const gchar* key, gboolean* out)
226
 
{
227
 
    GError* error = NULL;
228
 
    *out = g_key_file_get_boolean(config, group, key, &error);
229
 
    if(!error)
230
 
        return TRUE;
231
 
    if(g_error_matches(error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE))
232
 
        g_warning("[Configuration] Failed to parse boolean value [%s] %s: %s", group, key, error->message);
233
 
    g_clear_error(&error);
234
 
    return FALSE;
235
 
}
236
 
 
237
 
gchar**
238
 
config_get_groups(const gchar* prefix)
239
 
{
240
 
    gsize groups_size = 0, i, next;
241
 
    gchar** groups = g_key_file_get_groups(greeter_config, &groups_size);
242
 
 
243
 
    for(i = next = 0; i < groups_size; ++i)
244
 
        if(groups[i] && g_str_has_prefix(groups[i], prefix))
245
 
        {
246
 
            if(i != next)
247
 
            {
248
 
                g_free (groups[next]);
249
 
                groups[next] = groups[i];
250
 
                groups[i] = NULL;
251
 
            }
252
 
            ++next;
253
 
        }
254
 
 
255
 
    if(groups)
256
 
        groups[next] = NULL;
257
 
 
258
 
    return groups;
259
 
}
260
 
 
261
 
gboolean
262
 
config_has_key(const gchar* group, const gchar* key)
263
 
{
264
 
    GKeyFile* file = get_file_for_group(&group);
265
 
    return g_key_file_has_key(file, group, key, NULL);
266
 
}
267
 
 
268
 
gchar*
269
 
config_get_string(const gchar* group, const gchar* key, const gchar* fallback)
270
 
{
271
 
    GKeyFile* file = get_file_for_group(&group);
272
 
    gchar* value = g_key_file_get_value(file, group, key, NULL);
273
 
    return value || !fallback ? value : g_strdup(fallback);
274
 
}
275
 
 
276
 
void
277
 
config_set_string(const gchar* group, const gchar* key, const gchar* value)
278
 
{
279
 
    if(get_file_for_group(&group) != state_config)
280
 
    {
281
 
        g_warning("[Configuration] %s(%s, %s, '%s')", __func__, group, key, value);
282
 
        return;
283
 
    }
284
 
 
285
 
    g_key_file_set_value(state_config, group, key, value);
286
 
    save_key_file(state_config, state_filename);
287
 
}
288
 
 
289
 
gchar**
290
 
config_get_string_list(const gchar* group, const gchar* key, gchar** fallback)
291
 
{
292
 
    GKeyFile* file = get_file_for_group(&group);
293
 
    gchar** value = g_key_file_get_string_list(file, group, key, NULL, NULL);
294
 
    return value || !fallback ? value : g_strdupv(fallback);
295
 
}
296
 
 
297
 
gint
298
 
config_get_int(const gchar* group, const gchar* key, gint fallback)
299
 
{
300
 
    GKeyFile* file = get_file_for_group(&group);
301
 
    gint value;
302
 
    if(!get_int(file, group, key, &value))
303
 
        return fallback;
304
 
    return value;
305
 
}
306
 
 
307
 
void
308
 
config_set_int(const gchar* group, const gchar* key, gint value)
309
 
{
310
 
    if(get_file_for_group(&group) != state_config)
311
 
    {
312
 
        g_warning("[Configuration] %s(%s, %s, %d)", __func__, group, key, value);
313
 
        return;
314
 
    }
315
 
 
316
 
    g_key_file_set_integer(state_config, group, key, value);
317
 
    save_key_file(state_config, state_filename);
318
 
}
319
 
 
320
 
gboolean
321
 
config_get_bool(const gchar* group, const gchar* key, gboolean fallback)
322
 
{
323
 
    GKeyFile* file = get_file_for_group(&group);
324
 
    gboolean value;
325
 
    if(!get_bool(file, group, key, &value))
326
 
        return fallback;
327
 
    return value;
328
 
}
329
 
 
330
 
void
331
 
config_set_bool(const gchar* group, const gchar* key, gboolean value)
332
 
{
333
 
    if(get_file_for_group(&group) != state_config)
334
 
    {
335
 
        g_warning("[Configuration] %s(%s, %s, %d)", __func__, group, key, value);
336
 
        return;
337
 
    }
338
 
 
339
 
    g_key_file_set_boolean(state_config, group, key, value);
340
 
    save_key_file(state_config, state_filename);
341
 
}
342
 
 
343
 
gint
344
 
config_get_enum(const gchar* group, const gchar* key, gint fallback, const gchar* first_item, ...)
345
 
{
346
 
    const gchar *item_name;
347
 
    GKeyFile    *file;
348
 
    gchar       *value;
349
 
    gboolean     found = FALSE;
350
 
    va_list      var_args;
351
 
 
352
 
    if(!first_item)
353
 
        return fallback;
354
 
 
355
 
    file = get_file_for_group(&group);
356
 
    value = g_key_file_get_value(file, group, key, NULL);
357
 
 
358
 
    if(!value)
359
 
        return fallback;
360
 
 
361
 
    va_start(var_args, first_item);
362
 
 
363
 
    item_name = first_item;
364
 
    while(item_name)
365
 
    {
366
 
        gint item_value = va_arg(var_args, gint);
367
 
        if(g_strcmp0(value, item_name) == 0)
368
 
        {
369
 
            found = TRUE;
370
 
            fallback = item_value;
371
 
            break;
372
 
        }
373
 
        item_name = va_arg(var_args, gchar*);
374
 
    }
375
 
    va_end(var_args);
376
 
 
377
 
    if(!found)
378
 
        g_warning("[Configuration] Failed to parse enum value [%s] %s: %s", group, key, value);
379
 
 
380
 
    return fallback;
381
 
}