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.
5
* Copyright (C) 2000-2001 Ximian, Inc.
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.
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.
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.
21
* Authors: Carlos Garnacho Parro <garparr@teleline.es>,
22
* Tambet Ingo <tambet@ximian.com> and
23
* Arturo Espinosa <arturo@ximian.com>.
34
#include <sys/types.h>
40
#include "callbacks.h"
41
#include "user_group.h"
43
#include "user-settings.h"
44
#include "user-group-xml.h"
46
#include "gst-hig-dialog.h"
49
GList *groups_list = NULL;
51
/* Static prototypes */
52
static GList *group_fill_members_list (xmlNodePtr node);
53
static void group_fill_all_users_list (xmlNodePtr node, GList *exclude);
55
/* Global functions */
58
combo_add_profiles (GtkWidget *combo)
60
xmlNodePtr root = get_root_node (NODE_PROFILE);
61
xmlNodePtr node, default_node = NULL;
65
gboolean has_default = FALSE;
69
model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
70
gtk_list_store_clear (GTK_LIST_STORE (model));
72
model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_POINTER));
74
for (node = gst_xml_element_find_first (root, "profile");
76
node = gst_xml_element_find_next (node, "profile"))
78
if (gst_xml_element_get_boolean (node, "default")) {
84
profile_name = gst_xml_get_child_content (node, "name");
86
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
87
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
92
g_free (profile_name);
96
/* this is some kind of transition code,
97
* because the profiles format has changed */
101
for (node = gst_xml_element_find_first (root, "profile");
103
node = gst_xml_element_find_next (node, "profile"))
105
profile_name = gst_xml_get_child_content (node, "name");
107
if (strcmp (profile_name, "Default") == 0) {
108
gst_xml_element_set_boolean (node, "default", TRUE);
117
gtk_combo_box_set_model (GTK_COMBO_BOX (combo), model);
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);
125
combo_add_shells (GtkWidget *combo)
127
xmlNodePtr shells = gst_xml_element_find_first (gst_xml_doc_get_root (tool->config), "shelldb");
132
g_return_if_fail (combo != NULL);
133
g_return_if_fail (shells != NULL);
135
model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
136
gtk_list_store_clear (GTK_LIST_STORE (model));
138
for (node = gst_xml_element_find_first (shells, "shell");
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);
148
combo_add_groups (GtkWidget *combo, gboolean add_user_group)
150
xmlNodePtr groups = get_root_node (NODE_GROUP);
153
g_return_if_fail (combo != NULL);
154
g_return_if_fail (groups != NULL);
156
groups_list = get_list_from_node ("name", NODE_GROUP);
158
/* we add the '$user' variable, so the user
159
* can choose to create the user's group */
161
groups_list = g_list_prepend (groups_list, "$user");
163
groups_list = g_list_sort (groups_list, my_strcmp);
165
element = g_list_first (groups_list);
168
gtk_combo_box_append_text (GTK_COMBO_BOX (combo), element->data);
169
element = g_list_next (element);
174
show_error_message (gchar *parent_window, gchar *primary_text, gchar *secondary_text)
176
GtkWindow *xd = GTK_WINDOW (gst_dialog_get_widget (tool->main_dialog, parent_window));
179
dialog = gst_hig_dialog_new (xd,
181
GST_HIG_MESSAGE_ERROR,
184
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
186
gtk_dialog_run (GTK_DIALOG (dialog));
187
gtk_widget_destroy (dialog);
191
get_root_node (gint tbl)
193
xmlNodePtr node, root;
195
root = gst_xml_doc_get_root (tool->config);
200
node = gst_xml_element_find_first (root, "userdb");
203
node = gst_xml_element_find_first (root, "groupdb");
205
/* case NODE_NET_USER:
206
node = gst_xml_element_find_first (root, "nis_userdb");
209
node = gst_xml_element_find_first (root, "nis_groupdb");
212
node = gst_xml_element_find_first (root, "profiledb");
223
get_db_node (xmlNodePtr node)
227
if (strstr (node->name, "db"))
237
user_filter (xmlNodePtr node)
244
buf = user_query_string_get ();
245
ar = g_strsplit (buf, " ", 3);
249
if (!strcmp (ar[0], "all")) {
254
if (!strcmp (ar[1], "group"))
255
buf = user_value_group (node);
257
buf = gst_xml_get_child_content (node, ar[1]);
260
if (buf && !strcmp (ar[0], "contains") && strstr (buf, ar[2]))
263
else if (buf && !strcmp (ar[0], "is") && !strcmp (buf, ar[2]))
273
check_node_visibility (xmlNodePtr node)
276
gchar *field, *content;
278
static GtkToggleButton *toggle;
281
toggle = GTK_TOGGLE_BUTTON (gst_dialog_get_widget (tool->main_dialog, "showall"));
283
db_node = get_db_node (node);
284
get_min_max (db_node, &min, &max);
286
if (!strcmp (db_node->name, "userdb"))
288
if (!user_filter (node))
291
field = g_strdup ("uid");
294
else if (!strcmp (db_node->name, "groupdb"))
295
field = g_strdup ("gid");
300
node = gst_xml_element_find_first (node, field);
302
content = gst_xml_element_get_content (node);
303
val = atoi (content);
306
if (val >= min && val <= max)
308
else if (gtk_toggle_button_get_active (toggle))
315
is_valid_name (const gchar *name)
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.
322
if (!*name || !isalpha(*name))
326
if (!isdigit (*name) && !islower (*name) && *name != '-')
336
is_valid_id (const gchar *str)
351
nr = g_strtod (str, NULL);
353
if (nr < 0 || nr > IDMAX)
360
get_min_max (xmlNodePtr db_node, gint *min, gint *max)
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);
369
g_return_val_if_fail (db_node != NULL, FALSE);
371
if (!strcmp (db_node->name, "userdb"))
379
if (!strcmp (db_node->name, "groupdb"))
389
/* What is that? let's put min very small and max very BIG */
399
get_corresp_field (xmlNodePtr node)
403
g_return_val_if_fail (node != NULL, NULL);
405
root = gst_xml_doc_get_root (tool->config);
406
node = get_db_node (node);
408
if (!strcmp (node->name, "userdb"))
409
return gst_xml_element_find_first (root, "groupdb");
411
if (!strcmp (node->name, "groupdb"))
412
return gst_xml_element_find_first (root, "userdb");
414
if (!strcmp (node->name, "nis_groupdb"))
415
return gst_xml_element_find_first (root, "nis_userdb");
417
if (!strcmp (node->name, "nis_userdb"))
418
return gst_xml_element_find_first (root, "nis_groupdb");
424
get_node_by_data (xmlNodePtr dbnode, const gchar *field, const gchar *fdata)
429
g_return_val_if_fail (dbnode != NULL, NULL);
430
g_return_val_if_fail (field != NULL, NULL);
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");
440
for (node = gst_xml_element_find_first (dbnode, key); node != NULL; node = gst_xml_element_find_next (node, key))
442
buf = gst_xml_get_child_content (node, field);
446
if (!strcmp (buf, fdata))
458
/* for GLists of strings only */
460
my_g_list_remove_duplicates (GList *list1, GList *list2)
462
GList *new_list, *tmp_list;
473
if (!strcmp (list1->data, tmp_list->data))
476
tmp_list = tmp_list->next;
480
new_list = g_list_append (new_list, list1->data);
489
find_new_id (xmlNodePtr parent, xmlNodePtr profile)
491
gint umin, umax, gmin, gmax, id, min, max;
492
gchar *field, *buf, *key, *data;
496
g_return_val_if_fail (parent != NULL, NULL);
498
if (profile != NULL) {
499
data = gst_xml_get_child_content (profile, "umin");
500
umin = g_strtod (data, NULL);
503
data = gst_xml_get_child_content (profile, "umax");
504
umax = g_strtod (data, NULL);
507
data = gst_xml_get_child_content (profile, "gmin");
508
gmin = g_strtod (data, NULL);
511
data = gst_xml_get_child_content (profile, "gmax");
512
gmax = g_strtod (data, NULL);
521
if (!strcmp (parent->name, "userdb")) {
522
key = g_strdup ("user");
523
field = g_strdup ("uid");
526
} else if (!strcmp (parent->name, "groupdb")) {
527
key = g_strdup ("group");
528
field = g_strdup ("gid");
532
g_warning ("find_new_id: Unknown data source: %s.", parent->name);
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);
545
if (id <= max && ret < id)
551
if (ret >= min && ret <= max)
552
return g_strdup_printf ("%d", ret);
554
g_warning ("find_new_id: failed: %d >= %d && %d <= %d", ret, min, ret, max);
560
find_new_key (xmlNodePtr parent)
562
/* TODO: Possibily mix together find_new_id and find_new_key. */
568
g_return_val_if_fail (parent != NULL, NULL);
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");
575
for (n0 = gst_xml_element_find_first (parent, key); n0 != NULL; n0 = gst_xml_element_find_next (n0, key))
577
buf = gst_xml_get_child_content (n0, "key");
589
return g_strdup_printf ("%d", ++ret);
595
/* Not used at the moment, if'ed out to get rid of complier warning. */
597
group_update_users (xmlNodePtr node, gchar *old_name, gchar *new_name)
599
xmlNodePtr dbnode, gnode;
602
g_return_if_fail (node != NULL);
603
g_return_if_fail (old_name != NULL);
604
g_return_if_fail (new_name != NULL);
606
if (!strcmp (old_name, new_name))
609
dbnode = get_db_node (node);
610
dbnode = get_corresp_field (dbnode);
612
for (dbnode = gst_xml_element_find_first (dbnode, "group");
614
dbnode = dbnode->next)
616
gnode = gst_xml_element_find_first (dbnode, "users");
621
for (gnode = gnode->childs; gnode; gnode = gnode->next)
623
buf = gst_xml_element_get_content (gnode);
628
if (!strcmp (buf, old_name))
629
gst_xml_element_set_content (gnode, new_name);
638
/* Not used at the moment, if'ed out to get rid of complier warning. */
640
get_group_mainusers (xmlNodePtr group_node)
642
xmlNodePtr user_node, node;
644
GList *userlist = NULL;
646
g_return_val_if_fail (group_node != NULL, NULL);
648
user_node = get_corresp_field (group_node);
649
gid = gst_xml_get_child_content (group_node, "gid");
651
for (node = gst_xml_element_find_first (user_node, "user");
653
node = gst_xml_element_find_next (node, "user"))
656
buf = gst_xml_get_child_content (node, "gid");
660
if (!strcmp (buf, gid))
661
userlist = g_list_prepend (userlist,
662
gst_xml_get_child_content (node, "login"));
672
static gchar *user_search_string;
675
user_query_string_set (gchar *str)
677
if (user_search_string)
678
g_free (user_search_string);
680
user_search_string = g_strdup (str);
684
user_query_string_get (void)
686
if (!user_search_string)
687
user_search_string = g_strdup ("all");
689
return g_strdup (user_search_string);
692
gint my_strcmp (gconstpointer a, gconstpointer b)
694
return strcmp ((const char *) a, (const char *) b);