~ubuntu-branches/ubuntu/edgy/gnome-system-tools/edgy-proposed

« back to all changes in this revision

Viewing changes to src/users/user_group.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-10-14 18:49:22 UTC
  • Revision ID: james.westby@ubuntu.com-20041014184922-efvh7u8kpyy67a3z
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 
2
/* user_group.c: this file is part of users-admin, a ximian-setup-tool frontend 
 
3
 * for user administration.
 
4
 * 
 
5
 * Copyright (C) 2000-2001 Ximian, Inc.
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as
 
9
 * published by the Free Software Foundation; either version 2 of the
 
10
 * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 
20
 *
 
21
 * Authors: Carlos Garnacho Parro <garparr@teleline.es>,
 
22
 *          Tambet Ingo <tambet@ximian.com> and 
 
23
 *          Arturo Espinosa <arturo@ximian.com>.
 
24
 */
 
25
 
 
26
#ifdef HAVE_CONFIG_H
 
27
#  include <config.h>
 
28
#endif
 
29
 
 
30
#include <stdlib.h>
 
31
#include <ctype.h>
 
32
#include <gnome.h>
 
33
 
 
34
#include <sys/types.h>
 
35
#include <sys/stat.h>
 
36
#include <unistd.h>
 
37
#include <errno.h>
 
38
#include <utmp.h>
 
39
 
 
40
#include "callbacks.h"
 
41
#include "user_group.h"
 
42
#include "table.h"
 
43
#include "user-settings.h"
 
44
#include "user-group-xml.h"
 
45
#include "passwd.h"
 
46
#include "gst-hig-dialog.h"
 
47
 
 
48
extern GstTool *tool;
 
49
GList *groups_list = NULL;
 
50
 
 
51
/* Static prototypes */
 
52
static GList *group_fill_members_list (xmlNodePtr node);
 
53
static void group_fill_all_users_list (xmlNodePtr node, GList *exclude);
 
54
 
 
55
/* Global functions */
 
56
 
 
57
void
 
58
combo_add_profiles (GtkWidget *combo)
 
59
{
 
60
        xmlNodePtr    root = get_root_node (NODE_PROFILE);
 
61
        xmlNodePtr    node, default_node = NULL;
 
62
        GtkTreeModel *model;
 
63
        GtkTreeIter   iter;
 
64
        gchar        *profile_name;
 
65
        gboolean      has_default = FALSE;
 
66
        gint          index = 0;
 
67
        gint          i = 0;
 
68
 
 
69
        model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
 
70
        gtk_list_store_clear (GTK_LIST_STORE (model));
 
71
 
 
72
        model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER));
 
73
 
 
74
        for (node = gst_xml_element_find_first (root, "profile");
 
75
             node != NULL;
 
76
             node = gst_xml_element_find_next (node, "profile"))
 
77
        {
 
78
                if (gst_xml_element_get_boolean (node, "default")) {
 
79
                        index = i;
 
80
                        default_node = node;
 
81
                        has_default  = TRUE;
 
82
                }
 
83
 
 
84
                profile_name = gst_xml_get_child_content (node, "name");
 
85
 
 
86
                gtk_list_store_append (GTK_LIST_STORE (model), &iter);
 
87
                gtk_list_store_set    (GTK_LIST_STORE (model), &iter,
 
88
                                       0, profile_name,
 
89
                                       1, node,
 
90
                                       -1);
 
91
                
 
92
                g_free (profile_name);
 
93
                i++;
 
94
        }
 
95
 
 
96
        /* this is some kind of transition code,
 
97
         * because the profiles format has changed */
 
98
        if (!has_default) {
 
99
                index = i = 0;
 
100
 
 
101
                for (node = gst_xml_element_find_first (root, "profile");
 
102
                     node;
 
103
                     node = gst_xml_element_find_next (node, "profile"))
 
104
                {
 
105
                        profile_name = gst_xml_get_child_content (node, "name");
 
106
                        
 
107
                        if (strcmp (profile_name, "Default") == 0) {
 
108
                                gst_xml_element_set_boolean (node, "default", TRUE);
 
109
                                default_node = node;
 
110
                                index = i;
 
111
                        }
 
112
 
 
113
                        i++;
 
114
                }
 
115
        }
 
116
                
 
117
        gtk_combo_box_set_model (GTK_COMBO_BOX (combo), model);
 
118
 
 
119
        /* we set the option menu to the 'Default' option */
 
120
        gtk_combo_box_set_active (GTK_COMBO_BOX (combo), index);
 
121
        user_set_profile (default_node);
 
122
}
 
123
 
 
124
void
 
125
combo_add_shells (GtkWidget *combo)
 
126
{
 
127
        xmlNodePtr    shells = gst_xml_element_find_first (gst_xml_doc_get_root (tool->config), "shelldb");
 
128
        xmlNodePtr    node;
 
129
        GtkTreeModel *model;
 
130
        gchar        *str;
 
131
 
 
132
        g_return_if_fail (combo  != NULL);
 
133
        g_return_if_fail (shells != NULL);
 
134
        
 
135
        model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
 
136
        gtk_list_store_clear (GTK_LIST_STORE (model));
 
137
 
 
138
        for (node = gst_xml_element_find_first (shells, "shell");
 
139
             node != NULL;
 
140
             node = gst_xml_element_find_next (node, "shell")) {
 
141
                str = gst_xml_element_get_content (node);
 
142
                gtk_combo_box_append_text (GTK_COMBO_BOX (combo), str);
 
143
                g_free (str);
 
144
        }
 
145
}
 
146
 
 
147
void
 
148
combo_add_groups (GtkWidget *combo, gboolean add_user_group)
 
149
{
 
150
        xmlNodePtr  groups = get_root_node (NODE_GROUP);
 
151
        GList      *element;
 
152
 
 
153
        g_return_if_fail (combo != NULL);
 
154
        g_return_if_fail (groups != NULL);
 
155
 
 
156
        groups_list = get_list_from_node ("name", NODE_GROUP);
 
157
 
 
158
        /* we add the '$user' variable, so the user
 
159
         * can choose to create the user's group */
 
160
        if (add_user_group)
 
161
                groups_list = g_list_prepend (groups_list, "$user");
 
162
 
 
163
        groups_list = g_list_sort (groups_list, my_strcmp);
 
164
 
 
165
        element = g_list_first (groups_list);
 
166
 
 
167
        while (element) {
 
168
                gtk_combo_box_append_text (GTK_COMBO_BOX (combo), element->data);
 
169
                element = g_list_next (element);
 
170
        }
 
171
}
 
172
 
 
173
void
 
174
show_error_message (gchar *parent_window, gchar *primary_text, gchar *secondary_text)
 
175
{
 
176
        GtkWindow *xd = GTK_WINDOW (gst_dialog_get_widget (tool->main_dialog, parent_window));
 
177
        GtkWidget *dialog;
 
178
 
 
179
        dialog = gst_hig_dialog_new (xd,
 
180
                                     GTK_DIALOG_MODAL,
 
181
                                     GST_HIG_MESSAGE_ERROR,
 
182
                                     primary_text,
 
183
                                     secondary_text,
 
184
                                     GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
 
185
                                     NULL);
 
186
        gtk_dialog_run (GTK_DIALOG (dialog));
 
187
        gtk_widget_destroy (dialog);
 
188
}
 
189
 
 
190
xmlNodePtr
 
191
get_root_node (gint tbl)
 
192
{
 
193
        xmlNodePtr node, root;
 
194
 
 
195
        root = gst_xml_doc_get_root (tool->config);
 
196
 
 
197
        switch (tbl)
 
198
        {
 
199
        case NODE_USER:
 
200
                node = gst_xml_element_find_first (root, "userdb");
 
201
                break;
 
202
        case NODE_GROUP:
 
203
                node = gst_xml_element_find_first (root, "groupdb");
 
204
                break;
 
205
/*      case NODE_NET_USER:
 
206
                node = gst_xml_element_find_first (root, "nis_userdb");
 
207
                break;
 
208
        case NODE_NET_GROUP:
 
209
                node = gst_xml_element_find_first (root, "nis_groupdb");
 
210
                break;*/
 
211
        case NODE_PROFILE:
 
212
                node = gst_xml_element_find_first (root, "profiledb");
 
213
                break;
 
214
        default:
 
215
                node = NULL;
 
216
                break;
 
217
        }
 
218
 
 
219
        return node;
 
220
}
 
221
 
 
222
xmlNodePtr
 
223
get_db_node (xmlNodePtr node)
 
224
{
 
225
        while (node)
 
226
        {
 
227
                if (strstr (node->name, "db"))
 
228
                        return node;
 
229
 
 
230
                node = node->parent;
 
231
        }
 
232
 
 
233
        return NULL;
 
234
}
 
235
 
 
236
static gboolean
 
237
user_filter (xmlNodePtr node)
 
238
{
 
239
        gchar *buf;
 
240
        gchar **ar;
 
241
        gboolean ret;
 
242
 
 
243
        ret = FALSE;
 
244
        buf = user_query_string_get ();
 
245
        ar = g_strsplit (buf, " ", 3);
 
246
        
 
247
        g_free (buf);
 
248
        
 
249
        if (!strcmp (ar[0], "all")) {
 
250
                g_strfreev (ar);
 
251
                return TRUE;
 
252
        }
 
253
 
 
254
        if (!strcmp (ar[1], "group"))
 
255
                buf = user_value_group (node);
 
256
        else
 
257
                buf = gst_xml_get_child_content (node, ar[1]);
 
258
 
 
259
        
 
260
        if (buf && !strcmp (ar[0], "contains") && strstr (buf, ar[2]))
 
261
                ret = TRUE;
 
262
 
 
263
        else if (buf && !strcmp (ar[0], "is") && !strcmp (buf, ar[2]))
 
264
                ret = TRUE;
 
265
 
 
266
        g_free (buf);
 
267
        g_strfreev (ar);
 
268
        
 
269
        return ret;
 
270
}
 
271
 
 
272
gboolean
 
273
check_node_visibility (xmlNodePtr node)
 
274
{
 
275
        xmlNodePtr db_node;
 
276
        gchar *field, *content;
 
277
        gint min, max, val;
 
278
        static GtkToggleButton *toggle;
 
279
 
 
280
        if (!toggle)
 
281
                toggle = GTK_TOGGLE_BUTTON (gst_dialog_get_widget (tool->main_dialog, "showall"));
 
282
 
 
283
        db_node = get_db_node (node);
 
284
        get_min_max (db_node, &min, &max);
 
285
 
 
286
        if (!strcmp (db_node->name, "userdb"))
 
287
        {
 
288
                if (!user_filter (node))
 
289
                        return FALSE;
 
290
                
 
291
                field = g_strdup ("uid");
 
292
        }
 
293
 
 
294
        else if (!strcmp (db_node->name, "groupdb"))
 
295
                field = g_strdup ("gid");
 
296
 
 
297
        else
 
298
                return TRUE;
 
299
 
 
300
        node = gst_xml_element_find_first (node, field);
 
301
        g_free (field);
 
302
        content = gst_xml_element_get_content (node);
 
303
        val = atoi (content);
 
304
        g_free (content);
 
305
 
 
306
        if (val >= min && val <= max)
 
307
                return TRUE;
 
308
        else if (gtk_toggle_button_get_active (toggle))
 
309
                return TRUE;
 
310
        else
 
311
                return FALSE;
 
312
}
 
313
 
 
314
gboolean
 
315
is_valid_name (const gchar *name)
 
316
{
 
317
        /*
 
318
         * User/group names must start with a letter, and may not
 
319
         * contain colons, commas, newlines (used in passwd/group
 
320
         * files...) or any non-printable characters.
 
321
         */
 
322
        if (!*name || !isalpha(*name))
 
323
                return FALSE;
 
324
 
 
325
        while (*name) {
 
326
                if (!isdigit (*name) && !islower (*name) && *name != '-')
 
327
                        return FALSE;
 
328
                name++;
 
329
        }
 
330
 
 
331
        return TRUE;
 
332
}
 
333
 
 
334
 
 
335
gboolean
 
336
is_valid_id (const gchar *str)
 
337
{
 
338
        gdouble nr;
 
339
        gchar *buf;
 
340
        
 
341
        if (!str || !*str)
 
342
                return FALSE;
 
343
 
 
344
        buf = (gchar *)str;
 
345
        
 
346
        for (;*buf; buf++) {
 
347
                if (!isdigit (*buf))
 
348
                        return FALSE;
 
349
        }
 
350
 
 
351
        nr = g_strtod (str, NULL);
 
352
        
 
353
        if (nr < 0 || nr > IDMAX)
 
354
                return FALSE;
 
355
        
 
356
        return TRUE;
 
357
}
 
358
 
 
359
gboolean
 
360
get_min_max (xmlNodePtr db_node, gint *min, gint *max)
 
361
{
 
362
        xmlNodePtr profiledb = gst_xml_element_find_first (gst_xml_doc_get_root (tool->config), "profiledb");
 
363
        xmlNodePtr profile = gst_xml_element_find_first (profiledb, "profile");
 
364
        gint umin = g_strtod ((gchar *) gst_xml_get_child_content (profile, "umin"), NULL);
 
365
        gint umax = g_strtod ((gchar *) gst_xml_get_child_content (profile, "umax"), NULL);
 
366
        gint gmin = g_strtod ((gchar *) gst_xml_get_child_content (profile, "gmin"), NULL);
 
367
        gint gmax = g_strtod ((gchar *) gst_xml_get_child_content (profile, "gmax"), NULL);
 
368
        
 
369
        g_return_val_if_fail (db_node != NULL, FALSE);
 
370
 
 
371
        if (!strcmp (db_node->name, "userdb"))
 
372
        {
 
373
                *min = umin;
 
374
                *max = umax;
 
375
 
 
376
                return TRUE;
 
377
        }
 
378
 
 
379
        if (!strcmp (db_node->name, "groupdb"))
 
380
        {
 
381
                *min = gmin;
 
382
                *max = gmax;
 
383
 
 
384
                return TRUE;
 
385
        }
 
386
 
 
387
        else
 
388
        {
 
389
                /* What is that? let's put min very small and max very BIG */
 
390
                *min = 0;
 
391
                *max = 100000;
 
392
                return TRUE;
 
393
        }
 
394
 
 
395
        return FALSE;
 
396
}
 
397
 
 
398
xmlNodePtr
 
399
get_corresp_field (xmlNodePtr node)
 
400
{
 
401
        xmlNodePtr root;
 
402
 
 
403
        g_return_val_if_fail (node != NULL, NULL);
 
404
 
 
405
        root = gst_xml_doc_get_root (tool->config);
 
406
        node = get_db_node (node);
 
407
 
 
408
        if (!strcmp (node->name, "userdb"))
 
409
                return gst_xml_element_find_first (root, "groupdb");
 
410
 
 
411
        if (!strcmp (node->name, "groupdb"))
 
412
                return gst_xml_element_find_first (root, "userdb");
 
413
 
 
414
        if (!strcmp (node->name, "nis_groupdb"))
 
415
                return gst_xml_element_find_first (root, "nis_userdb");
 
416
 
 
417
        if (!strcmp (node->name, "nis_userdb"))
 
418
                return gst_xml_element_find_first (root, "nis_groupdb");
 
419
 
 
420
        return NULL;
 
421
}
 
422
 
 
423
xmlNodePtr
 
424
get_node_by_data (xmlNodePtr dbnode, const gchar *field, const gchar *fdata)
 
425
{
 
426
        xmlNodePtr node;
 
427
        gchar *buf, *key;
 
428
 
 
429
        g_return_val_if_fail (dbnode != NULL, NULL);
 
430
        g_return_val_if_fail (field != NULL, NULL);
 
431
 
 
432
        if (!fdata)
 
433
                return NULL;
 
434
        
 
435
        if (strcmp (dbnode->name, "userdb") == 0)
 
436
                key = g_strdup ("user");
 
437
        else if (strcmp (dbnode->name, "groupdb") == 0)
 
438
                key = g_strdup ("group");
 
439
        
 
440
        for (node = gst_xml_element_find_first (dbnode, key); node != NULL; node = gst_xml_element_find_next (node, key))
 
441
        {
 
442
                buf = gst_xml_get_child_content (node, field);
 
443
                if (!buf)
 
444
                        continue;
 
445
                
 
446
                if (!strcmp (buf, fdata))
 
447
                {
 
448
                        g_free (buf);
 
449
                        return node;
 
450
                }
 
451
 
 
452
                g_free (buf);
 
453
        }
 
454
 
 
455
        return NULL;
 
456
}
 
457
 
 
458
/* for GLists of strings only */
 
459
GList *
 
460
my_g_list_remove_duplicates (GList *list1, GList *list2)
 
461
{
 
462
        GList *new_list, *tmp_list;
 
463
        gboolean found;
 
464
 
 
465
        new_list = NULL;
 
466
        
 
467
        while (list1)
 
468
        {
 
469
                found = FALSE;
 
470
                tmp_list = list2;
 
471
                while (tmp_list)
 
472
                {
 
473
                        if (!strcmp (list1->data, tmp_list->data))
 
474
                                found = TRUE;
 
475
 
 
476
                        tmp_list = tmp_list->next;
 
477
                }
 
478
                
 
479
                if (!found)
 
480
                        new_list = g_list_append (new_list, list1->data);
 
481
 
 
482
                list1 = list1->next;
 
483
        }
 
484
 
 
485
        return new_list;
 
486
}
 
487
 
 
488
gchar *
 
489
find_new_id (xmlNodePtr parent, xmlNodePtr profile)
 
490
{
 
491
        gint umin, umax, gmin, gmax, id, min, max;
 
492
        gchar *field, *buf, *key, *data;
 
493
        gint ret = 0;
 
494
        xmlNodePtr n0;
 
495
 
 
496
        g_return_val_if_fail (parent != NULL, NULL);
 
497
        
 
498
        if (profile != NULL) {
 
499
                data = gst_xml_get_child_content (profile, "umin");
 
500
                umin = g_strtod (data, NULL);
 
501
                g_free (data);
 
502
 
 
503
                data = gst_xml_get_child_content (profile, "umax");
 
504
                umax = g_strtod (data, NULL);
 
505
                g_free (data);
 
506
                
 
507
                data = gst_xml_get_child_content (profile, "gmin");
 
508
                gmin = g_strtod (data, NULL);
 
509
                g_free (data);
 
510
 
 
511
                data = gst_xml_get_child_content (profile, "gmax");
 
512
                gmax = g_strtod (data, NULL);
 
513
                g_free (data);
 
514
        } else {
 
515
                umin = 0;
 
516
                umax = 60000;
 
517
                gmin = 0;
 
518
                gmax = 60000;
 
519
        }
 
520
 
 
521
        if (!strcmp (parent->name, "userdb")) {
 
522
                key = g_strdup ("user");
 
523
                field = g_strdup ("uid");
 
524
                min = umin;
 
525
                max = umax;
 
526
        } else if (!strcmp (parent->name, "groupdb")) {
 
527
                key = g_strdup ("group");
 
528
                field = g_strdup ("gid");
 
529
                min = gmin;
 
530
                max = gmax;
 
531
        } else {
 
532
                g_warning ("find_new_id: Unknown data source: %s.", parent->name);
 
533
                return NULL;
 
534
        }
 
535
 
 
536
        ret = min - 1;
 
537
        for (n0 = gst_xml_element_find_first (parent, key); n0 != NULL; n0 = gst_xml_element_find_next (n0, key)) {
 
538
                buf = gst_xml_get_child_content (n0, field);
 
539
                if (!buf)
 
540
                        continue;
 
541
 
 
542
                id = atoi (buf);
 
543
                g_free (buf);
 
544
 
 
545
                if (id <= max && ret < id)
 
546
                        ret = id;
 
547
        }
 
548
        g_free (field);
 
549
        ret++;
 
550
 
 
551
        if (ret >= min && ret <= max)
 
552
                return g_strdup_printf ("%d", ret);
 
553
 
 
554
        g_warning ("find_new_id: failed: %d >= %d && %d <= %d", ret, min, ret, max);
 
555
        return NULL;
 
556
}
 
557
 
 
558
 
 
559
gchar *
 
560
find_new_key (xmlNodePtr parent)
 
561
{
 
562
        /* TODO: Possibily mix together find_new_id and find_new_key. */
 
563
        gchar *buf, *key;
 
564
        gint id;
 
565
        gint ret = -1;
 
566
        xmlNodePtr n0;
 
567
 
 
568
        g_return_val_if_fail (parent != NULL, NULL);
 
569
        
 
570
        if (strcmp (parent->name, "userdb") == 0)
 
571
                key = g_strdup ("user");
 
572
        else if (strcmp (parent->name, "groupdb") == 0)
 
573
                key = g_strdup ("group");
 
574
        
 
575
        for (n0 = gst_xml_element_find_first (parent, key); n0 != NULL; n0 = gst_xml_element_find_next (n0, key))
 
576
        {
 
577
                buf = gst_xml_get_child_content (n0, "key");
 
578
 
 
579
                if (!buf)
 
580
                        continue;
 
581
 
 
582
                id = atoi (buf);
 
583
                g_free (buf);
 
584
 
 
585
                if (ret < id)
 
586
                        ret = id;
 
587
        }
 
588
 
 
589
        return g_strdup_printf ("%d", ++ret);
 
590
}
 
591
 
 
592
/* User related */
 
593
 
 
594
#if 0
 
595
/* Not used at the moment, if'ed out to get rid of complier warning. */
 
596
static void
 
597
group_update_users (xmlNodePtr node, gchar *old_name, gchar *new_name)
 
598
{
 
599
        xmlNodePtr dbnode, gnode;
 
600
        gchar *buf;
 
601
 
 
602
        g_return_if_fail (node != NULL);
 
603
        g_return_if_fail (old_name != NULL);
 
604
        g_return_if_fail (new_name != NULL);
 
605
 
 
606
        if (!strcmp (old_name, new_name))
 
607
                return;
 
608
        
 
609
        dbnode = get_db_node (node);
 
610
        dbnode = get_corresp_field (dbnode);
 
611
 
 
612
        for (dbnode = gst_xml_element_find_first (dbnode, "group");
 
613
                dbnode;
 
614
                dbnode = dbnode->next)
 
615
        {
 
616
                gnode = gst_xml_element_find_first (dbnode, "users");
 
617
 
 
618
                if (!gnode)
 
619
                        continue;
 
620
 
 
621
                for (gnode = gnode->childs; gnode; gnode = gnode->next)
 
622
                {
 
623
                        buf = gst_xml_element_get_content (gnode);
 
624
 
 
625
                        if (!buf)
 
626
                                continue;
 
627
 
 
628
                        if (!strcmp (buf, old_name))
 
629
                                gst_xml_element_set_content (gnode, new_name);
 
630
 
 
631
                        g_free (buf);
 
632
                }
 
633
        }
 
634
}
 
635
#endif
 
636
 
 
637
#if 0
 
638
/* Not used at the moment, if'ed out to get rid of complier warning. */
 
639
static GList *
 
640
get_group_mainusers (xmlNodePtr group_node)
 
641
{
 
642
        xmlNodePtr user_node, node;
 
643
        gchar *gid, *buf;
 
644
        GList *userlist = NULL;
 
645
        
 
646
        g_return_val_if_fail (group_node != NULL, NULL);
 
647
 
 
648
        user_node = get_corresp_field (group_node);
 
649
        gid = gst_xml_get_child_content (group_node, "gid");
 
650
        
 
651
        for (node = gst_xml_element_find_first (user_node, "user");
 
652
             node;
 
653
             node = gst_xml_element_find_next (node, "user"))
 
654
        {
 
655
 
 
656
                buf = gst_xml_get_child_content (node, "gid");
 
657
                if (!buf)
 
658
                        continue;
 
659
 
 
660
                if (!strcmp (buf, gid))
 
661
                        userlist = g_list_prepend (userlist,
 
662
                                                   gst_xml_get_child_content (node, "login"));
 
663
 
 
664
                g_free (buf);
 
665
        }
 
666
 
 
667
        g_free (gid);
 
668
        return userlist;
 
669
}
 
670
#endif
 
671
 
 
672
static gchar *user_search_string;
 
673
 
 
674
void
 
675
user_query_string_set (gchar *str)
 
676
{
 
677
        if (user_search_string)
 
678
                g_free (user_search_string);
 
679
 
 
680
        user_search_string = g_strdup (str);
 
681
}
 
682
 
 
683
gchar *
 
684
user_query_string_get (void)
 
685
{
 
686
        if (!user_search_string)
 
687
                user_search_string = g_strdup ("all");
 
688
        
 
689
        return g_strdup (user_search_string);
 
690
}
 
691
 
 
692
gint my_strcmp (gconstpointer a, gconstpointer b)
 
693
{
 
694
        return strcmp ((const char *) a, (const char *) b);
 
695
}