/* 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.
 */

/*
 * Callback-functions for the user manager GUI.
 *
 * Copyright (C) 2003- Isak Savo
 */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

#include "dirbrowser.h"
#include "gui_helper.h"
#include "usr_manager.h"
#include "helper.h"
#include "helpview.h"

void
on_treeview_dlg_users_cursor_changed   (GtkTreeView     *treeview,
                                        gpointer         user_data)
{
	static GtkTreeModel *model = NULL;
	static GtkTreeSelection *sel = NULL;
	static GtkWidget *btn_edit, *btn_remove;
	GtkTreeIter iter;
	gchar *username;
   
	if (G_UNLIKELY (!model || !sel))
	{
		model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
		sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
	}
	if (G_UNLIKELY (!btn_edit || !btn_remove))
	{
		btn_edit = UW("btn_edituser");
		btn_remove = UW("btn_removeuser");
	}
	if (!gtk_tree_selection_get_selected (sel, &model, &iter))
	{
		gtk_widget_set_sensitive (btn_edit, FALSE);
		gtk_widget_set_sensitive (btn_remove, FALSE);
		return;
	}
   
	gtk_tree_model_get (model, &iter, 
			    COL_USRMAN_LOGIN, &username,
			    -1);
	usr_widgets_set_info (username);
	gtk_widget_set_sensitive (btn_edit, TRUE);
	gtk_widget_set_sensitive (btn_remove, TRUE);
}


void
on_usr_dlg_btn_edituser_clicked        (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkWidget *btn_remove, *btn_add, *tree;
	GtkWidget *entry;

	tree = UW("tree_userlist");
	btn_remove = UW("btn_removeuser");
	btn_add = UW("btn_adduser");

	usr_widgets_set_active_state (TRUE);

	gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
	gtk_widget_set_sensitive (tree, FALSE);
	gtk_widget_set_sensitive (btn_remove, FALSE);
	gtk_widget_set_sensitive (btn_add, FALSE);
   
	entry = UW("entry_realname");
	gtk_widget_grab_focus (entry);
   
	g_object_set_data (G_OBJECT (UW("usermanager")), "editing", GINT_TO_POINTER (TRUE));
}


void
on_usr_dlg_btn_removeuser_clicked      (GtkButton       *button,
                                        gpointer         user_data)
{
	static GtkTreeView *tree;
	static GtkTreeModel *model = NULL;
	static GtkTreeSelection *sel = NULL;
	GtkTreePath *path;
	GtkTreeIter iter;
	gchar *username, *msg;
	gint i;
	GError *err = NULL;
   
	if (!tree || !model || !sel)
	{
		tree = (GtkTreeView *) UW("tree_userlist");
		model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree));
		sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
	}

	if (!gtk_tree_selection_get_selected (sel, &model, &iter))
		return;
	path = gtk_tree_model_get_path (model, &iter);
	gtk_tree_model_get (model, &iter, 
			    COL_USRMAN_LOGIN, &username,
			    -1);
	msg = g_strdup_printf (_("Remove User '%s'?"), username);
	if (gui_display_confirmdialog (msg, 
				       _("This will permanently remove the user from pureftpd, preventing him or her to login to your server.\nAre you sure you want to remove this user?"), 
				       _("Yes, _Remove User"), NULL, UW("usermanager")) != GTK_RESPONSE_YES)
	{
		g_free (msg);
		return;
	}
	g_free (msg);
	if (usr_remove_user (username, &err))
	{
		i = usr_fill_users_list ();
		/* Try to restore the selection or move it to the row above if that exists */
		while (i && gtk_tree_selection_path_is_selected (sel, path) == FALSE)
		{
			gtk_tree_selection_select_path (sel, path);
			i = gtk_tree_path_prev (path);
		}
		/* Trigger widget updates FIXME: Is this necessary? */
		g_signal_emit_by_name ((gpointer) tree, "cursor_changed", tree, NULL);   

		return;
	}
	else
		pur_log_err ("Error removing user: %s", err->message);

	switch (err->code)
	{
		case PA_USR_ERROR_PERMISSION_DENIED:
		  msg = g_strdup_printf (_("You do not have permission to remove the user %s from the password-file. This could be because another process is accessing the file(s)."), username);
		  gui_display_msgdialog (_("Error removing user."), msg, MSGDLG_TYPE_WARNING, UW("usermanager"));
		  g_free (msg);
		  break;
		case PA_USR_ERROR_COMMAND_NOT_FOUND:
		  msg = g_strdup_printf (_("The user '%s' could not be removed because the pure-pw command could not be found. Make sure that it is installed and that the configuration points to the correct file."), username);
		  gui_display_msgdialog (_("Error removing user."), msg, MSGDLG_TYPE_WARNING, UW("usermanager"));
		  g_free (msg);
		  break;
		case PA_USR_ERROR_FAILED:
		  msg = g_strdup_printf (_("The user '%s' could not be removed."), username);
		  gui_display_msgdialog (_("Error removing user."), msg, MSGDLG_TYPE_WARNING, UW("usermanager"));
		  g_free (msg);
		  break;
		case PA_USR_ERROR_USER_NOT_FOUND:
		  msg = g_strdup_printf (_("The user '%s' could not be removed because it doesn't exist. If you are sure it exist, please contact the author of this program with a description of your problem."), username);
		  gui_display_msgdialog (_("Error removing user."), msg, MSGDLG_TYPE_WARNING, UW("usermanager"));
		  g_free (msg);
		  break;
	}
	g_error_free (err);
}


void
on_usr_dlg_btn_save_changes_clicked    (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkWidget *btn_remove, *btn_add, *btn_edit;
	static GtkTreeView *tree;
	static GtkTreeModel *model = NULL;
	static GtkTreeSelection *sel = NULL;
	GtkTreePath *path;
	GtkTreeIter iter;
	GError *err = NULL;
	
	if (!tree)
	{
		tree = (GtkTreeView *) UW("tree_userlist");
		model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree));
		sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
	}
	if (!gtk_tree_selection_get_selected (sel, &model, &iter)) /* This should never happen, but we need the iter anyway */
		return; 
	path = gtk_tree_model_get_path (model, &iter);
   
	btn_remove = UW("btn_removeuser");
	btn_add = UW("btn_adduser");
	btn_edit = UW("btn_edituser");

	if (usr_save_user_info (&err))
	{
		usr_widgets_set_active_state (FALSE);
	
		gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
	
		gtk_widget_set_sensitive (GTK_WIDGET (tree), TRUE);
		gtk_widget_set_sensitive (btn_remove, TRUE);
		gtk_widget_set_sensitive (btn_add, TRUE);
		gtk_widget_set_sensitive (btn_edit, TRUE);
	
		usr_fill_users_list ();
		gtk_tree_selection_select_path (sel, path);
	
		g_object_set_data (G_OBJECT (UW("usermanager")), "editing", GINT_TO_POINTER (FALSE));

		return;
	}
	else
		pur_log_err ("Error saving user: %s", err->message);

	switch (err->code)
	{
		case PA_USR_ERROR_PERMISSION_DENIED:
		  gui_display_msgdialog (_("Error saving user."),
					 _("You do not have permission to save the user-information. This could be because another process is accessing the required file(s).\nYou may try again and if that doesn't work, please contact the author with a description of your problem."),
					 MSGDLG_TYPE_WARNING, UW("usermanager"));
		  break;
		case PA_USR_ERROR_COMMAND_NOT_FOUND:
		  gui_display_msgdialog (_("Error saving user."),
					 _("The pure-pw command could not be found. Make sure that the command is installed and that the configuration points to the correct file.\n"),
					 MSGDLG_TYPE_WARNING, UW("usermanager"));
		  break;
	}
	g_error_free (err);
}

void
on_usr_dlg_btn_adduser_clicked         (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkWidget *dlg, *entry;
	gint response, len, response2;
	gchar *user = NULL, *pw, *encrypted = NULL;
	gchar *user_vlocale;
	gboolean add = FALSE, keep_asking = TRUE;
	GError *err = NULL;
	
	dlg = UW("dlg_ask_new_username");
	while (keep_asking)
	{
		keep_asking = FALSE;
		add = FALSE;
		response = gtk_dialog_run (GTK_DIALOG (dlg));

		switch (response)
		{
			case GTK_RESPONSE_OK:
			  entry = UW("nuser_entry_username");
			  user = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
			  user_vlocale = string_to_vuser_locale (user);
			  /* We care for the *number of bytes* not the number of characters (in case of UTF-8 multibyte chars) */
			  len = strlen (user_vlocale);
			  g_free (user_vlocale);
			  entry = UW("nuser_entry_pw1");
			  pw = (gchar *) gtk_entry_get_text (GTK_ENTRY (entry));
			  encrypted = g_strdup (misc_crypt_passwd (pw));
			  add = TRUE;
			  if (len > 32)
			  {
				  response2 = gui_display_confirmdialog (_("Long Username"), 
									 _("The username you have entered contains more than 32 characters. "
									   "This is normally the max length on a standard PureFTPd server. "
									   "Do you wish to continue with this username anyway?"),
									 _("Yes, Use this username "), NULL, UW("usermanager"));
				  if (response2 == GTK_RESPONSE_NO)
					  keep_asking = TRUE;
			  }
			  else if (usr_user_exists (user))
			  {
				  gui_display_msgdialog (_("User already exists"), 
							 _("The username you have entered already exists in PureFTPd. "
							   "You must select a different name for your new login."),
							 MSGDLG_TYPE_ERROR, dlg);
				  keep_asking = TRUE;
			  }
			  break;
			  
			case GTK_RESPONSE_CANCEL:
			  pur_log_dbg ("Aborting creation!\n");
			  break;
		}
	}
	gtk_entry_set_text (GTK_ENTRY (UW("nuser_entry_username")), "");
	gtk_entry_set_text (GTK_ENTRY (UW("nuser_entry_pw1")), "");
	gtk_entry_set_text (GTK_ENTRY (UW("nuser_entry_pw2")), "");
	gtk_widget_hide (dlg);
	if (!add)
		return;
	if (usr_add_user (user, encrypted, &err))
	{
		usr_fill_users_list ();
		usr_select_user (user);
		return;
	}
	else
		pur_log_err ("Error adding user: %s", err->message);
	
	switch (err->code)
	{
		case PA_USR_ERROR_PERMISSION_DENIED:
		  gui_display_msgdialog (_("Add User Failed"),
					 _("Could not add the user because you have insufficient permissions to do so. This could be bacause some other process is accessing the required file(s)."), MSGDLG_TYPE_WARNING, dlg);
		  break;
		case PA_USR_ERROR_COMMAND_NOT_FOUND:
		  gui_display_msgdialog (_("Add User Failed"),
					 _("The pure-pw command could not be found. Make sure that the command is installed and that the configuration points to the correct file.\n"),
					 MSGDLG_TYPE_WARNING, dlg);
		  break;
	}
	g_error_free (err);
}


void
on_usr_dlg_btn_change_pw_clicked       (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkWidget *dlg, *entry;
	const gchar *pw;
	gchar *encrypted;
	gint ret;

	dlg = UW("dlg_set_password");
   
	ret = gtk_dialog_run (GTK_DIALOG (dlg));
	if (ret == GTK_RESPONSE_OK)
	{
		entry = UW("pwset_entry_pw1");
		pw = (gchar *) gtk_entry_get_text (GTK_ENTRY (entry));
      
		encrypted = g_strdup (misc_crypt_passwd (pw));
		g_free (g_object_get_data (G_OBJECT (button), "usr_password"));
		g_object_set_data (G_OBJECT (button), "usr_password", encrypted);
      
	}
	gtk_entry_set_text (GTK_ENTRY (UW("pwset_entry_pw1")), "");	
	gtk_entry_set_text (GTK_ENTRY (UW("pwset_entry_pw2")), "");
	
	gtk_widget_hide (dlg);
}


void
on_usr_dlg_chk_chroot_toggled          (GtkToggleButton *togglebutton,
                                        gpointer         user_data)
{
	GtkWidget *entry;
	entry = UW("entry_fakeroot");
   
	if (GTK_WIDGET_SENSITIVE (GTK_WIDGET (togglebutton)) == FALSE)
		return; /* Don't set sensitive state if togglebutton is insensitive */
	gtk_widget_set_sensitive (entry, 
				  gtk_toggle_button_get_active (togglebutton));
}

void
on_usr_dlg_btn_cancel_changes_clicked  (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkWidget *tree, *btn_remove, *btn_add, *btn_edit;
   
	tree = UW("tree_userlist");
	btn_remove = UW("btn_removeuser");
	btn_edit = UW("btn_edituser");
	btn_add = UW("btn_adduser");
   
	gtk_widget_set_sensitive (GTK_WIDGET (tree), TRUE);
	gtk_widget_set_sensitive (btn_remove, TRUE);
	gtk_widget_set_sensitive (btn_add, TRUE);
	gtk_widget_set_sensitive (btn_edit, TRUE);
	usr_widgets_set_active_state (FALSE);
   
	g_object_set_data (G_OBJECT (UW("usermanager")), "editing", GINT_TO_POINTER (FALSE));
	g_signal_emit_by_name (G_OBJECT (tree), "cursor_changed", GTK_TREE_VIEW (tree), NULL);
}

void
close_usrman_dialog                    (GtkButton       *button,
                                        gpointer         user_data)
{
	gboolean editing;
	gint dlg_ret;
	GtkWidget *save_btn = UW("btn_save_changes");
	editing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (UW("usermanager")), "editing"));

	if (editing)
	{
		dlg_ret = gui_display_confirmdialog (_("You have unsaved info."), 
						     _("You are currently editing the information of an user.\n"
						       "Do you wish to save this information first?"),
						     _("Yes, _Save Info"), _("_Cancel"), UW("usermanager"));
		if (dlg_ret == GTK_RESPONSE_YES)
			g_signal_emit_by_name (G_OBJECT (save_btn), "clicked", GTK_BUTTON (save_btn), NULL);
		else
			return;
	}
	gtk_widget_hide (UW("usermanager"));
}


void
on_usr_dlg_btn_help_clicked            (GtkButton       *button,
                                        gpointer         user_data)
{
	hlp_show_help (HLP_ITEM_USER_MANAGER);
}

gboolean
on_usrman_delete_event                 (GtkWidget       *widget,
                                        GdkEvent        *event,
                                        gpointer         user_data)
{
	GtkWidget *close_button = UW("btn_close");

	if (!close_button)
		return TRUE;

	g_signal_emit_by_name (close_button, "clicked", close_button, NULL);
	return TRUE;
}


/* This is used from the add-new-user dialog */
void
on_new_user_entry_change               (GtkEditable     *editable,
                                        gpointer         data)
{
	GtkWidget *entry_uname = NULL;
	GtkWidget *entry_pw1 = NULL;
	GtkWidget *entry_pw2 = NULL;
	GtkWidget *btn_add = NULL;
	const gchar *uname, *pw1, *pw2;

	entry_uname = UW("nuser_entry_username");
	entry_pw1 = UW("nuser_entry_pw1");
	entry_pw2 = UW("nuser_entry_pw2");
	btn_add = UW("nuser_btn_add");
   
	uname = gtk_entry_get_text (GTK_ENTRY (entry_uname));

	pw1 = gtk_entry_get_text (GTK_ENTRY (entry_pw1));
	pw2 = gtk_entry_get_text (GTK_ENTRY (entry_pw2));
   
	if (G_UNLIKELY (strlen (uname) > 0 && strlen (pw1) > 0 && g_str_equal (pw1, pw2)))
	{
		gtk_widget_set_sensitive (btn_add, TRUE);
		GTK_WIDGET_SET_FLAGS (btn_add, GTK_CAN_DEFAULT);
		GTK_WIDGET_SET_FLAGS (btn_add, GTK_HAS_DEFAULT);
	}
	else
		gtk_widget_set_sensitive (btn_add, FALSE);
}


/* This is used in the dialog that changes the password for a user */
void
on_pwentry_changed                     (GtkEditable     *editable,
                                        gpointer         user_data)
{
	GtkWidget *pw1 = NULL;
	GtkWidget *pw2 = NULL;
	GtkWidget *btn = NULL;
	const gchar *txt1, *txt2;

	pw1 = UW("pwset_entry_pw1");
	pw2 = UW("pwset_entry_pw2");
	btn = UW("pwset_btn_set");
      
	txt1 = gtk_entry_get_text (GTK_ENTRY (pw1));
	txt2 = gtk_entry_get_text (GTK_ENTRY (pw2));
   
	if (G_UNLIKELY (strlen (txt1) > 0 && g_str_equal (txt1, txt2)))
		gtk_widget_set_sensitive (btn, TRUE);
	else
		gtk_widget_set_sensitive (btn, FALSE);
}


void
optmenu_id_changed                     (GtkOptionMenu   *optionmenu,
                                        gpointer         user_data)
{
	static GtkWidget *lbl_gid = NULL, *lbl_uid = NULL;
	static GtkWidget *opt_menu_uid = NULL, *opt_menu_gid = NULL;
   
	if (!opt_menu_uid)
	{
		lbl_uid = UW("lbl_invalid_uid");
		lbl_gid = UW("lbl_invalid_gid");
		opt_menu_uid = UW("optmenu_uid");
		opt_menu_gid = UW("optmenu_gid");
	}
	if ((gpointer) optionmenu == (gpointer) opt_menu_uid)
		gtk_widget_hide (lbl_uid);
	else
		gtk_widget_hide (lbl_gid);


}


void
on_btn_browse_homedir_clicked          (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkWidget *dbr, *entry;
	const gchar *old;
	const gchar *dir;
	gint response;

	entry = UW("entry_home");
	old = gtk_entry_get_text (GTK_ENTRY (entry));
	dbr = dirbrowser_new (NULL);
	dirbrowser_set_directory (DIRBROWSER (dbr), old);
	response = gtk_dialog_run (GTK_DIALOG (dbr));
	if (response == GTK_RESPONSE_OK)
	{
		dir = dirbrowser_get_directory (DIRBROWSER (dbr));
		gtk_entry_set_text (GTK_ENTRY (entry), dir);
	}
	gtk_widget_destroy (dbr);
}


void
on_btn_browse_fakeroot_clicked         (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkWidget *dbr, *entry;
	const gchar *old;
	const gchar *dir;
	gint response;

	entry = UW("entry_fakeroot");
	old = gtk_entry_get_text (GTK_ENTRY (entry));
	dbr = dirbrowser_new (NULL);
	dirbrowser_set_directory (DIRBROWSER (dbr), old);
	response = gtk_dialog_run (GTK_DIALOG (dbr));
	if (response == GTK_RESPONSE_OK)
	{
		dir = dirbrowser_get_directory (DIRBROWSER (dbr));
		gtk_entry_set_text (GTK_ENTRY (entry), dir);
	}
	gtk_widget_destroy (dbr);
}


syntax highlighted by Code2HTML, v. 0.9.1