/* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <gtk/gtk.h>
#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"));
}
}
syntax highlighted by Code2HTML, v. 0.9.1