/* PureAdmin * Copyright (C) 2003 Isak Savo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * Handles Pre-requistities for the user manager * * Copyright (C) 2006 - Isak Savo */ #include #include #include #include #include #include "cfg.h" #include "helper.h" #include "gui_helper.h" #include "globals.h" #include "system_accounts.h" #include "prereq_usrmanager.h" /* The columns in the GUI list */ enum { COL_CHANGETYPE, /* Not visible in the GUI */ COL_DESCRIPTION, COL_VALUE, COL_VALUE2, N_COLUMNS }; /* Callbacks */ static void cell_value1_edited_cb (GtkCellRendererText *cellrenderertext, gchar *path, gchar *new_text, gpointer user_data); static void cell_value2_edited_cb (GtkCellRendererText *cellrenderertext, gchar *path, gchar *new_text, gpointer user_data); static void init_prereq_window (void) { static GtkWidget *tree = NULL; GtkCellRenderer *renderer; GtkTreeViewColumn *column; GtkListStore *model; if (tree) return; tree = DW("tree_system_changes"); model = gtk_list_store_new (N_COLUMNS, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); gtk_tree_view_set_model (GTK_TREE_VIEW (tree), GTK_TREE_MODEL (model)); g_object_unref (G_OBJECT (model)); gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree)), GTK_SELECTION_SINGLE); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes (_("Action"), renderer, "text", COL_DESCRIPTION, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW(tree), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes (_("Value"), renderer, "text", COL_VALUE, NULL); g_object_set(renderer, "editable", TRUE, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW(tree), column); g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(cell_value1_edited_cb), GINT_TO_POINTER(COL_VALUE)); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes (_("Numerical Value"), renderer, "text", COL_VALUE2, NULL); g_object_set(renderer, "editable", TRUE, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW(tree), column); g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(cell_value2_edited_cb), GINT_TO_POINTER(COL_VALUE2)); } static gboolean is_pwfile_ok() { return g_file_test(cfg.pwfile, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR); } static gboolean is_default_home_ok () { return g_file_test (cfg.default_home, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR); } static gboolean is_default_gid_ok() { return (cfg.default_gid > 1 && sys_get_gid_exists(cfg.default_gid)); } static gboolean is_default_uid_ok() { return (cfg.default_uid > 1 && sys_get_uid_exists(cfg.default_uid)); } static SystemActions *get_required_actions (void) { SystemActions *rv = g_new0 (SystemActions, 1); if (!is_pwfile_ok()) { // It doesn't exist, get the guessed default value rv->pwfile = cfg_get_pftp_default_pwfile(); rv->changes |= CHANGES_CREATE_PWFILE; } if (!is_default_home_ok()) { rv->ftpdir = cfg_find_default_home(); rv->changes |= CHANGES_CREATE_HOMEDIR; } if (!is_default_gid_ok()) { rv->grp_id = sys_get_available_group_id(100); rv->ftpgroup = g_strdup ("ftpgroup"); rv->changes |= CHANGES_ADD_GROUP; } if (!is_default_uid_ok()) { rv->usr_id = sys_get_available_user_id(100); rv->ftpuser = g_strdup ("ftpuser"); rv->changes |= CHANGES_ADD_USER; } return rv; } static void append_row (SystemChangesType change, const gchar *description, const gchar *value, const gchar *value2) { static GtkWidget *tree = NULL; static GtkListStore *model; GtkTreeIter iter; if (tree == NULL) { tree = DW("tree_system_changes"); model = (GtkListStore*) gtk_tree_view_get_model(GTK_TREE_VIEW (tree)); } gtk_list_store_append(GTK_LIST_STORE(model), &iter); gtk_list_store_set(model, &iter, COL_CHANGETYPE, change, COL_DESCRIPTION, description, COL_VALUE, value, COL_VALUE2, value2, -1); } static void clear_list(void) { GtkListStore *model = (GtkListStore*) gtk_tree_view_get_model (GTK_TREE_VIEW (DW("tree_system_changes"))); gtk_list_store_clear(model); } static gboolean take_required_actions (SystemActions *actions, GList **errors) { GError *err = NULL; gboolean ok, retval = TRUE; guint grp = cfg.default_gid; guint usr = cfg.default_uid; g_return_val_if_fail (errors != NULL && *errors == NULL, FALSE); if (actions->changes & CHANGES_ADD_GROUP) { ok = sys_create_group(actions->ftpgroup, actions->grp_id, &err); if (!ok) { *errors = g_list_append (*errors, g_strdup (err->message)); g_error_free(err); err = NULL; retval = FALSE; } else { cfg.default_gid = cfg_find_ftpgroup_gid(); grp = actions->grp_id; } } if (actions->changes & CHANGES_ADD_USER) { ok = sys_create_user(actions->ftpuser, actions->usr_id, grp, &err); if (!ok) { *errors = g_list_append (*errors, g_strdup (err->message)); g_error_free(err); err = NULL; retval = FALSE; } else { cfg.default_uid = cfg_find_ftpuser_uid(); usr = actions->usr_id; } } if (actions->changes & CHANGES_CREATE_HOMEDIR) { ok = misc_create_directory(actions->ftpdir, (usr > 0 ? usr : -1), (grp > 0 ? grp : -1), &err); if (!ok) { *errors = g_list_append (*errors, g_strdup (err->message)); g_error_free(err); err = NULL; retval = FALSE; } g_free (cfg.default_home); cfg.default_home = g_strdup (actions->ftpdir); } if (actions->changes & CHANGES_CREATE_PWFILE) { ok = misc_create_passwd_file(actions->pwfile); if (!ok) { *errors = g_list_append (*errors, g_strdup (err->message)); g_error_free(err); err = NULL; retval = FALSE; } g_free (cfg.pwfile); g_free (cfg.pdbfile); cfg.pwfile = g_strdup (actions->pwfile); gchar *fnamebase = filename_without_extension(actions->pwfile); cfg.pdbfile = g_strconcat (fnamebase, ".pdb", NULL); } return retval; } static void populate_actions (SystemActions *actions) { if (actions->changes & CHANGES_ADD_GROUP) { gchar newgid[10]; g_snprintf(newgid, 10, "%u", actions->grp_id); append_row(CHANGES_ADD_GROUP, _("Add a dedicated ftp system group"), actions->ftpgroup, newgid); } if (actions->changes & CHANGES_ADD_USER) { gchar newuid[10]; g_snprintf(newuid, 10, "%u", actions->usr_id); append_row(CHANGES_ADD_USER, _("Add a dedicated ftp system user"), actions->ftpuser, newuid); } if (actions->changes & CHANGES_CREATE_HOMEDIR) { append_row (CHANGES_CREATE_HOMEDIR, _("Create a default home directory for ftp users"), actions->ftpdir, NULL); } if (actions->changes & CHANGES_CREATE_PWFILE) append_row(CHANGES_CREATE_PWFILE, _("Create a new password file for ftp users"), actions->pwfile, NULL); } /**** Global Functions ****/ gboolean prereq_show_dialog (GtkWindow *parent) { init_prereq_window(); gboolean rv = FALSE;; SystemActions *a = get_required_actions(); populate_actions(a); g_object_set_data_full(G_OBJECT(DW("dlg_prepare_usermanager")), "systemactions", a, (GDestroyNotify) system_actions_free); if (parent) gtk_window_set_transient_for(GTK_WINDOW (DW("dlg_prepare_usermanager")), parent); GtkResponseType response = gtk_dialog_run(GTK_DIALOG(DW("dlg_prepare_usermanager"))); if (response == GTK_RESPONSE_YES) { a = g_object_get_data(G_OBJECT(DW("dlg_prepare_usermanager")), "systemactions"); GList *errors = NULL; if (!take_required_actions (a, &errors)) { pur_log_wrn ("Couldn't take action:"); GList *node = errors; while (node) { pur_log_wrn((gchar*)node->data); g_free (node->data); node = g_list_next(node); } g_list_free(node); } else rv = TRUE; } clear_list(); gtk_widget_hide(DW("dlg_prepare_usermanager")); return rv; } gboolean prereq_are_all_requirements_met (void) { if (!is_default_gid_ok()) return FALSE; if (!is_default_uid_ok()) return FALSE; if (!is_default_home_ok()) return FALSE; if (!is_pwfile_ok()) return FALSE; return TRUE; } void system_actions_free (SystemActions *actions) { g_free (actions->ftpuser); g_free (actions->ftpgroup); g_free (actions->ftpdir); g_free (actions->pwfile); g_free (actions); } static gboolean is_valid_system_name (const gchar *str) { if (!str || *str == '\0') return FALSE; const gchar *p = str; while (*p) { if (!g_ascii_isalpha(*p)) return FALSE; p++; } return TRUE; } /**** Callbacks ****/ static void cell_value1_edited_cb (GtkCellRendererText *cellrenderertext, gchar *path, gchar *new_text, gpointer user_data) { GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (DW("tree_system_changes"))); GtkTreeIter iter; SystemActions *actions; SystemChangesType change_type; gtk_tree_model_get_iter_from_string(model, &iter, path); gtk_tree_model_get(model, &iter, COL_CHANGETYPE, &change_type, -1); actions = g_object_get_data(G_OBJECT(DW("dlg_prepare_usermanager")), "systemactions"); g_return_if_fail (actions != NULL); switch (change_type) { case CHANGES_ADD_GROUP: case CHANGES_ADD_USER: // Username column if (!is_valid_system_name(new_text)) { gui_display_msgdialog("Invalid Name", "The text you entered contains illegal characters. Only english characters are allowed", MSGDLG_TYPE_ERROR, DW("dlg_prepare_usermanager")); } else { gtk_list_store_set (GTK_LIST_STORE(model), &iter, COL_VALUE, new_text, -1); /* Update the action object */ if (change_type == CHANGES_ADD_GROUP) { g_free (actions->ftpgroup); actions->ftpgroup = g_strdup (new_text); } else { g_free (actions->ftpuser); actions->ftpuser = g_strdup (new_text); } } break; case CHANGES_CREATE_HOMEDIR: case CHANGES_CREATE_PWFILE: if (!g_path_is_absolute(new_text)) gui_display_msgdialog("Invalid Directory", "The entered directory is not a valid location", MSGDLG_TYPE_ERROR, DW("dlg_prepare_usermanager")); else { gtk_list_store_set (GTK_LIST_STORE(model), &iter, COL_VALUE, new_text, -1); if (change_type == CHANGES_CREATE_HOMEDIR) { g_free (actions->ftpdir); actions->ftpdir = g_strdup (new_text); } else { g_free (actions->pwfile); actions->pwfile = g_strdup (new_text); } } break; } } static void cell_value2_edited_cb (GtkCellRendererText *cellrenderertext, gchar *path, gchar *new_text, gpointer user_data) { GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (DW("tree_system_changes"))); GtkTreeIter iter; SystemActions *actions; SystemChangesType change_type; gtk_tree_model_get_iter_from_string(model, &iter, path); gtk_tree_model_get(model, &iter, COL_CHANGETYPE, &change_type, -1); actions = g_object_get_data(G_OBJECT(DW("dlg_prepare_usermanager")), "systemactions"); g_return_if_fail (actions != NULL); guint num = atoi(new_text); if (num == 0) return; g_free (new_text); new_text = g_strdup_printf ("%d", num); if (change_type == CHANGES_ADD_GROUP) actions->grp_id = num; else if (change_type == CHANGES_ADD_USER) actions->usr_id = num; else { /* FIXME; Write a better message */ gui_display_msgdialog("Invalid Setting", "You cannot set this field since this row does not allow it!", MSGDLG_TYPE_ERROR, DW("dlg_prepare_usermanager")); } }