/* Copyright (C) 2000,2001,2002 Manuel Amador (Rudd-O)
   This file is part of Directory administrator.

   Directory administrator 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.1 of
   the License, or (at your option) any later version.

   Directory administrator 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 Directory administrator; if not, send e-mail to amador@alomega.com 
*/


#include <pthread.h>
#include "appsupport.h"
#include "appglobals.h"
#include "usergrouplists.h"
#include "prefsdialog.h"
#include "appfunctions.h"
#include "dir_entry.h"

GtkWidget *
create_messagebox_with_message (char *messagetext)
{
  GtkWidget *messagebox;
  GtkWidget *dialog_vbox6;
  GtkWidget *button35;
  GtkWidget *dialog_action_area6;

  messagebox = gnome_message_box_new (messagetext,
				      GNOME_MESSAGE_BOX_INFO, NULL);
  gtk_object_set_data (GTK_OBJECT (messagebox), "messagebox", messagebox);
  gtk_window_set_title (GTK_WINDOW (messagebox), "Information");
  gtk_window_set_modal (GTK_WINDOW (messagebox), TRUE);
  gtk_window_set_policy (GTK_WINDOW (messagebox), FALSE, FALSE, FALSE);

  dialog_vbox6 = GNOME_DIALOG (messagebox)->vbox;
  gtk_object_set_data (GTK_OBJECT (messagebox), "dialog_vbox6", dialog_vbox6);
  gtk_widget_show (dialog_vbox6);

  gnome_dialog_append_button (GNOME_DIALOG (messagebox),
			      GNOME_STOCK_BUTTON_OK);
  button35 = g_list_last (GNOME_DIALOG (messagebox)->buttons)->data;
  gtk_widget_ref (button35);
  gtk_object_set_data_full (GTK_OBJECT (messagebox), "button35", button35,
			    (GtkDestroyNotify) gtk_widget_unref);
  gtk_widget_show (button35);
  GTK_WIDGET_SET_FLAGS (button35, GTK_CAN_DEFAULT);

  dialog_action_area6 = GNOME_DIALOG (messagebox)->action_area;
  gtk_widget_ref (dialog_action_area6);
  gtk_object_set_data_full (GTK_OBJECT (messagebox), "dialog_action_area6",
			    dialog_action_area6,
			    (GtkDestroyNotify) gtk_widget_unref);

  return messagebox;
}

GList *
get_user_uid_list_from_cache ()
{
  GList *milista = NULL;
  GList *it = NULL;

  g_print("\n\nget_user_uid_list: filtering entries for users' UIDs\n");
  for (it = g_list_first(cached_dir_entries);it;it=g_list_next(it))
    {

      if (dir_entry_is_user(it->data)) {
	  milista =
	    g_list_append (milista, g_strdup (dir_entry_get_uid(it->data)));
       }


    }


  milista = g_list_sort(milista,(GCompareFunc) g_strcasecmp);
  return milista;

}
GList *
get_group_cn_list_from_cache ()
{
  GList *milista = NULL;
  GList *it = NULL;

  g_print("\n\nget_group_cn_list: filtering entries for groups' CNs\n");
  for (it = g_list_first(cached_dir_entries);it;it=g_list_next(it))
    {

      if (dir_entry_is_group(it->data)) {

	  milista =
	    g_list_append (milista, g_strdup (dir_entry_get_cn(it->data)));
       }


    }
  milista = g_list_sort(milista,(GCompareFunc) g_strcasecmp);
  return milista;

}




void
fill_users_dropdown (GtkWidget * dropdown)
{
  GList *items = get_user_uid_list_from_cache ();
  if (items == NULL)
    gtk_widget_show (create_messagebox_with_message
		     ("Your directory has no users"));
  else
    {
      gtk_combo_set_popdown_strings (GTK_COMBO (dropdown), items);
      g_list_foreach (items, (GFunc) g_free, NULL);
      g_list_free (items);
    }
}

void
fill_groups_dropdown (GtkWidget * dropdown)
{
  GList *items = get_group_cn_list_from_cache ();
  if (items == NULL)
    gtk_widget_show (create_messagebox_with_message
		     ("Your directory has no groups"));
  else
    {
      gtk_combo_set_popdown_strings (GTK_COMBO (dropdown), items);
      g_list_foreach (items, (GFunc) g_free, NULL);
      g_list_free (items);
    }
}

gchar *
get_lowest_uid (connection_profile * usethisone)
{

  LDAPMessage *results = NULL;
  LDAPMessage *entry = NULL;
  LDAP *conn = NULL;
  gchar *treeroot = NULL;
  char **value_collection;
  gchar *lowestuid = NULL;
  int ldap_errors;
  int counter;
  int currentnumber;
  gchar *filter;
  gchar *attributetoreturn[2];
  GList *milista = NULL;
  GList *iterador = NULL;

  if (connection_profile_is_connected (usethisone) == FALSE)
    {
      g_print
	("NOT CONNECTED!!!! - returning! (while filling groups dropdown ");
      return NULL;
    }

  conn = connection_profile_get_ldap_handler (usethisone);
  treeroot = connection_profile_get_treeroot (usethisone);

  filter = "(objectClass=posixAccount)";

  attributetoreturn[0] = "uidnumber";
  attributetoreturn[1] = NULL;

  //look data up
  ldap_errors = ldap_search_s (conn,
			       treeroot,
			       LDAP_SCOPE_SUBTREE,
			       filter, attributetoreturn, 0, &results);
  if (ldap_errors)
    g_print ("LDAP error on get_lowest_uid: %s\n",
	     ldap_err2string (ldap_errors));
  else
    {
      g_assert (results);

      entry =
	ldap_first_entry (connection_profile_get_ldap_handler (usethisone),
			  results);
      if (entry)
	{

	  while (entry)
	    {

	      value_collection = ldap_get_values (conn, entry, "uidnumber");
	      g_assert (value_collection);
	      milista =
		g_list_append (milista, g_strdup (value_collection[0]));
	      ldap_value_free (value_collection);
	      entry = ldap_next_entry (conn, entry);
	    }

	  counter = preferences.logindefaults.VUID_MIN;
	  for (iterador=g_list_first(milista);iterador;iterador=iterador->next)
	    {
		  currentnumber = atoi(iterador->data);
		  if (currentnumber > counter) counter = currentnumber;
	    }
	  counter++;
          lowestuid = g_new0 (gchar, 256);
          g_snprintf (lowestuid, 256, "%d", counter);

 /*
	  while (lowestuid == NULL)
	    {
	      lowestuid = g_new0 (gchar, 256);
	      g_snprintf (lowestuid, 256, "%d", counter);
	      if (g_list_find_custom
		  (milista, lowestuid, (GCompareFunc) g_strcasecmp) != NULL)
		{
		  g_free (lowestuid);
		  lowestuid = NULL;
		  counter++;
		}
	    }

*/

	  g_list_foreach (milista, (GFunc) g_free, NULL);
	  g_list_free (milista);

	}
      else
	{
	  lowestuid = g_new0 (gchar, 256);
	  g_snprintf (lowestuid, 256, "%d",
		      preferences.logindefaults.VUID_MIN);
	}

      ldap_msgfree (results);
    }
  return (lowestuid);

}

gchar *
get_lowest_gid (connection_profile * usethisone)
{

  LDAPMessage *results = NULL;
  LDAPMessage *entry = NULL;
  char **value_collection;
  gchar *lowestuid = NULL;
  int ldap_errors;
  int counter;
  int currentnumber;
  gchar *filter;
  gchar *attributetoreturn[2];
  GList *milista = NULL;
  GList *iterador = NULL;

  if (connection_profile_is_connected (usethisone) == FALSE)
    {
      g_print
	("NOT CONNECTED!!!! - returning! (while filling groups dropdown ");
      return NULL;
    }


  filter = "(objectClass=posixGroup)";

  attributetoreturn[0] = "gidnumber";
  attributetoreturn[1] = NULL;

//debug:  g_print(filter);

  //look data up
  ldap_errors =
    ldap_search_s (connection_profile_get_ldap_handler (usethisone),
		   connection_profile_get_treeroot (usethisone),
		   LDAP_SCOPE_SUBTREE, filter, attributetoreturn, 0,
		   &results);
  if (ldap_errors)
	     	{
    g_print ("LDAP error on get_lowest_gid: %s, continuing with default of %d\n",
	     ldap_err2string (ldap_errors),preferences.logindefaults.VGID_MIN);
	  lowestuid = g_new0 (gchar, 256);
	  g_snprintf (lowestuid, 256, "%d",
		      preferences.logindefaults.VGID_MIN);
		ldap_msgfree (results);

	}

  else
    {
      g_assert (results);

      entry =
	ldap_first_entry (connection_profile_get_ldap_handler (usethisone),
			  results);

      if (entry)
	{
	  while (entry)
	    {

	      value_collection =
		ldap_get_values (connection_profile_get_ldap_handler
				 (usethisone), entry, "gidnumber");
	      g_assert (value_collection);
	      milista =
		g_list_append (milista, g_strdup (value_collection[0]));
	      ldap_value_free (value_collection);
	      entry =
		ldap_next_entry (connection_profile_get_ldap_handler
				 (usethisone), entry);
	    }

	  counter = preferences.logindefaults.VGID_MIN;
	  for (iterador=g_list_first(milista);iterador;iterador=iterador->next)
	    {
		  currentnumber = atoi(iterador->data);
		  if (currentnumber > counter) counter = currentnumber;
	    }
	  counter++;
          lowestuid = g_new0 (gchar, 256);
          g_snprintf (lowestuid, 256, "%d", counter);


	  g_list_foreach (milista, (GFunc) g_free, NULL);
	  g_list_free (milista);
	}
      else
	{
	  lowestuid = g_new0 (gchar, 256);
	  g_snprintf (lowestuid, 256, "%d",
		      preferences.logindefaults.VGID_MIN);
	}
      ldap_msgfree (results);

    }
//  g_free(filter);  NOT FREED - STATIC!
  return (lowestuid);

}

GList *
get_orgunit_dn_list_from_cache ()
{
  GList *milista = NULL;
  GList *it = NULL;

  g_print("\n\nget_orgunit_dn_list: filtering entries for orgunits' DNs\n");
  for (it = g_list_first(cached_dir_entries);it;it=g_list_next(it))
    {

      if (dir_entry_is_orgunit(it->data)) {

	  milista =
	    g_list_append (milista, g_strdup (dir_entry_get_dn(it->data)));
       }


    }
  milista = g_list_sort(milista,(GCompareFunc) g_strcasecmp);
  return milista;

}



void open_website(void) {
  gchar **args = g_new0(gchar*,3);
  args[0] = "--newwin";
  args[1] = "http://diradmin.open-it.org/";
  g_print("\nOpening Web site..."); 

}

void app_set_status(gchar* message) {

  GnomeApp* a = (GnomeApp*)app;
  GnomeAppBar* b = (GnomeAppBar*)a->statusbar;
  gnome_appbar_set_status(b,message);
  while (g_main_iteration(FALSE)) {};

}

void app_set_progress(gfloat progress) {

  GnomeApp* a = (GnomeApp*)app;
  GnomeAppBar* b = (GnomeAppBar*)a->statusbar;
  GtkProgress* p = gnome_appbar_get_progress(b);

  gtk_progress_set_percentage(p,progress);
  while (g_main_iteration(FALSE)) {};

}

void app_interactive_connect(void) {
//returns TRUE on success, FALSE on no connection

GtkWidget *about;
GtkToggleButton *connect_button;
connection_profile* uniq = NULL;

      g_print ("Intentando conectar interactivamente\n");
      //are there any profiles?
      if (g_list_length (connection_profile_list) == 1)
	{
          g_print("Existe solo un perfil de conexion\n");
          uniq = connection_profile_list->data;
	  app_connect(connection_profile_get_name(uniq));
	}
      else if (g_list_length (connection_profile_list))
	{
//          g_print("Existen perfiles de conexion\n");
	  about = create_connect_selectprofile ();
	  gtk_widget_show (about);
	}
      else
	{
	  //if not, prompt me to create one
	  g_print ("No existen perfiles de conexion\n");
          connect_button = GTK_TOGGLE_BUTTON(lookup_widget(app,"button_connect"));
	  gtk_toggle_button_set_active (connect_button, FALSE);

//        about = create_login ();
	  about = create_druid_new_profile ();
/*	  gtk_signal_connect (GTK_OBJECT (lookup_widget (about, "finish")),
			      "finish", GTK_SIGNAL_FUNC (on_button4_clicked),
			      NULL);*/
	  gtk_widget_show (about);
/*	  gtk_widget_show (create_messagebox_with_message
			   ("Please create a new connection profile")); */
	}



}


void app_interactive_disconnect(void) {
//disconnects the application interactively

GtkWidget* togglebutton;
togglebutton = app;
   connection_profile_disconnect (current_connection_profile);
   connection_profile_destroy (current_connection_profile);
   current_connection_profile = NULL;


//turn off buttons
      gtk_widget_set_sensitive (lookup_widget
				(GTK_WIDGET (togglebutton), "button_refresh"),
				FALSE);
      gtk_widget_set_sensitive (lookup_widget
				(GTK_WIDGET (togglebutton), "button_new"),
				FALSE);
      gtk_widget_set_sensitive (lookup_widget
				(GTK_WIDGET (togglebutton),
				 "button_new_group"), FALSE);

//turn off menus
      gtk_widget_set_sensitive (lookup_widget
				(GTK_WIDGET (togglebutton), "new_user2"),
				FALSE);
      gtk_widget_set_sensitive (lookup_widget
				(GTK_WIDGET (togglebutton),
				 "new_group1"), FALSE);
      gtk_widget_set_sensitive (lookup_widget (app, "refresh1"), FALSE);
      gtk_widget_set_sensitive (lookup_widget (app, "disconnect1"), FALSE);

app_disable_editing_controls();
app_disable_filtercontrols();



      //this has the effect of emptying user lists
      app_refresh();
}

int app_is_connected(void) {
//asks whether the application is connected
  if (connection_profile_is_connected(current_connection_profile)) return
TRUE;
  return FALSE;

}

int _app_connect(char *profilename) {

//really connects the application and makes sure everything is right,
//else show an ldap error msg
  int ldap_error_definition;
  GtkWidget* askpass;

  g_assert (profilename);
  g_print ("\ncalled: app_connect with profile name: %s\n", profilename);


  ///DESTROY AND FREE THE ARGUMENT!!!!! SET IT TO NULL AFTER DESTROYING IT PLEAse
  //  BUGBUG should make sure it is disconnected first!!!!

  connection_profile_destroy (current_connection_profile);
  current_connection_profile = NULL;

  //gimme a copy of the selected one and point the current one to the copy

  current_connection_profile =
      connection_profile_duplicate (connection_profile_list_getbyname
                                    (connection_profile_list, profilename));

  ldap_error_definition =
      connection_profile_connect (current_connection_profile);

  if (ldap_error_definition == LDAP_INVALID_CREDENTIALS) {
      askpass = create_invalidcredentials();
      gtk_entry_set_text (GTK_ENTRY
                        (lookup_widget (askpass, "userid")),
                        connection_profile_get_dn(current_connection_profile));
      gtk_entry_set_text (GTK_ENTRY
                        (lookup_widget (askpass, "password")),
                        connection_profile_get_password(current_connection_profile));
      gtk_object_set_user_data(GTK_OBJECT(askpass),g_strdup(profilename));
      gtk_widget_show(askpass);
  }

  if (ldap_error_definition)

    {

		if (ldap_error_definition != LDAP_INVALID_CREDENTIALS) {
			if (ldap_error_definition == 91) {
				if (connection_profile_get_tls(current_connection_profile)) {
					gtk_widget_show(create_messagebox_with_message("Could not connect to the directory: TLS appears not to be supported.\nPlease disable TLS in your connection profile."));
				} else {
					gtk_widget_show(create_messagebox_with_message("Could not connect to the directory.  Either try using TLS, or set your directory up to accept version 2 connections."));
				}
			} else {
				gtk_widget_show (create_messagebox_with_message
						(ldap_err2string (ldap_error_definition)));
			}
		}

      gtk_toggle_button_set_active ((GtkToggleButton *)
                                    lookup_widget (app, "button_connect"),
                                    FALSE);

      connection_profile_destroy (current_connection_profile);
      current_connection_profile = NULL;

      app_set_status(g_strconcat("Connection to ",profilename," failed: ",ldap_err2string
             (ldap_error_definition),NULL));

    }
  else { /* conect con exito */
      g_print( "\nSe conecto con exito\n");
      app_refresh();
      gtk_widget_set_sensitive (lookup_widget (app, "button_refresh"), TRUE);
      gtk_widget_set_sensitive (lookup_widget (app, "button_new"), TRUE);
      gtk_widget_set_sensitive (lookup_widget (app, "button_new_group"),
                                TRUE);
      gtk_widget_set_sensitive (lookup_widget (app, "new_user2"), TRUE);
      gtk_widget_set_sensitive (lookup_widget (app, "new_group1"), TRUE);
      gtk_widget_set_sensitive (lookup_widget (app, "refresh1"), TRUE);
      gtk_widget_set_sensitive (lookup_widget (app, "disconnect1"), TRUE);
	  app_enable_filtercontrols();
  }


  return (ldap_error_definition);

}

int app_connect(char *profilename) {

  _app_connect(profilename);
  return 0;

}


void app_refresh(void) {
char buf[2048];
char *message;
gint numobjects;

app_set_status("Retrieving entries from directory...");
app_set_progress(0);
cached_dir_entries_refetch(current_connection_profile);

 app_set_status("Analyzing data...");
 objectview_fill();


if (connection_profile_is_connected(current_connection_profile)) {

 numobjects = g_list_length(cached_dir_entries);
 snprintf(buf,sizeof(buf),"%d",numobjects);
if (numobjects == 1)
 message = g_strconcat((const gchar*)&buf," object in directory",NULL);
 else
 message = g_strconcat((const gchar*)&buf," objects in directory",NULL);

 app_set_status(message);
 g_free(message);

 message=g_strconcat("Directory administrator: ",connection_profile_get_name(current_connection_profile));
 gtk_window_set_title(GTK_WINDOW(app),message);
 g_free(message);
 }
 else {
 app_set_status("Click Connect to connect to the directory.");
 gtk_window_set_title(GTK_WINDOW(app),"Directory administrator");
 }
 app_set_progress(0);



}



void _delete_this_user_from_this_group(gint gidnumber,char*dn,char*uid) {
	char*groupdn = NULL;
	dir_entry*groupentry = NULL;
	diradmin_group * oldgroup;diradmin_group * newgroup;
	ldaptransaction*t;
	int ldap_errors;

	groupentry = cached_dir_entries_getgroupbygidnumber(gidnumber);
	if (groupentry == NULL) return;

	groupdn = dir_entry_get_dn(groupentry);
	g_print("\nRemoving %s (uid %s) from group %s\n",dn,uid,groupdn);


	//g_print("\n\nBringing group %s to the match\n",groupdn);
	oldgroup = diradmin_group_new_from_ldap(current_connection_profile,groupdn);
	g_assert(oldgroup);
	//g_print("Duplicating group\n");
	//		newgroup = diradmin_group_duplicate(oldgroup);
	newgroup = diradmin_group_new_from_ldap(current_connection_profile,groupdn);
	g_assert(newgroup);
	//diradmin_group_dump_dnmembers(newgroup);
	//g_print("Removing %s from this group\n",dn);
	diradmin_group_remove_dnmember(newgroup,dn);
	diradmin_group_remove_member(newgroup,dn);
	//diradmin_group_dump_dnmembers(newgroup);

	//g_print("Generating difference\n");
	t = diradmin_group_generate_ldapdiff (oldgroup, newgroup);

	ldaptransaction_dump(t);
	if (ldaptransaction_has_mods)	{
		//g_print("Committing operation to the directory\n");
		ldap_errors =
		connection_profile_commit_modifications
		(current_connection_profile, t->mods,groupdn);
		if (ldap_errors) {
			g_print("There was an LDAP error while removing this user's DN from the new group\n");
		}
	}
	ldaptransaction_destroy(t);
	diradmin_group_destroy(oldgroup);
	diradmin_group_destroy(newgroup);

}


void _delete_this_dn_from_this_group(char*dn,gint gidnumber) {
	char*groupdn = NULL;
	dir_entry*groupentry = NULL;
	diradmin_group * oldgroup;diradmin_group * newgroup;
	ldaptransaction*t;
	int ldap_errors;

	groupentry = cached_dir_entries_getgroupbygidnumber(gidnumber);
	if (groupentry == NULL) return;
	g_print("\nRemoving %s from group with gid number %d\n",dn,gidnumber);

	groupdn = dir_entry_get_dn(groupentry);

	//g_print("\n\nBringing group %s to the match\n",groupdn);
	oldgroup = diradmin_group_new_from_ldap(current_connection_profile,groupdn);
	g_assert(oldgroup);
	//g_print("Duplicating group\n");
	//		newgroup = diradmin_group_duplicate(oldgroup);
	newgroup = diradmin_group_new_from_ldap(current_connection_profile,groupdn);
	g_assert(newgroup);
	//diradmin_group_dump_dnmembers(newgroup);
	//g_print("Removing %s from this group\n",dn);
	diradmin_group_remove_dnmember(newgroup,dn);
	//diradmin_group_dump_dnmembers(newgroup);

	//g_print("Generating difference\n");
	t = diradmin_group_generate_ldapdiff (oldgroup, newgroup);

	ldaptransaction_dump(t);
	if (ldaptransaction_has_mods)	{
		//g_print("Committing operation to the directory\n");
		ldap_errors =
		connection_profile_commit_modifications
		(current_connection_profile, t->mods,groupdn);
		if (ldap_errors) {
			g_print("There was an LDAP error while removing this user's DN from the new group\n");
		}
	}
	ldaptransaction_destroy(t);
	diradmin_group_destroy(oldgroup);
	diradmin_group_destroy(newgroup);

}

void _delete_this_uid_from_this_group(char*dn,gint gidnumber) {
	char*groupdn = NULL;
	dir_entry*groupentry = NULL;
	diradmin_group * oldgroup;diradmin_group * newgroup;
	ldaptransaction*t;
	int ldap_errors;

	groupentry = cached_dir_entries_getgroupbygidnumber(gidnumber);
	if (groupentry == NULL) return;
	g_print("\nRemoving UID %s from group with gid number %d\n",dn,gidnumber);

	groupdn = dir_entry_get_dn(groupentry);

	//g_print("\n\nBringing group %s to the match\n",groupdn);
	oldgroup = diradmin_group_new_from_ldap(current_connection_profile,groupdn);
	g_assert(oldgroup);
	//g_print("Duplicating group\n");
	//		newgroup = diradmin_group_duplicate(oldgroup);
	newgroup = diradmin_group_new_from_ldap(current_connection_profile,groupdn);
	g_assert(newgroup);
	//diradmin_group_dump_dnmembers(newgroup);
	//g_print("Removing %s from this group\n",dn);
	diradmin_group_remove_member(newgroup,dn);
	//diradmin_group_dump_dnmembers(newgroup);

	//g_print("Generating difference\n");
	t = diradmin_group_generate_ldapdiff (oldgroup, newgroup);

	ldaptransaction_dump(t);
	if (ldaptransaction_has_mods)	{
		//g_print("Committing operation to the directory\n");
		ldap_errors =
		connection_profile_commit_modifications
		(current_connection_profile, t->mods,groupdn);
		if (ldap_errors) {
			g_print("There was an LDAP error while removing this user's UID from the new group\n");
		}
	}
	ldaptransaction_destroy(t);
	diradmin_group_destroy(oldgroup);
	diradmin_group_destroy(newgroup);

}

void _delete_this_user_from_all_groups(char*dn) {

	char*groupdn = NULL;
	dir_entry*groupentry = NULL;
	dir_entry*userentry = NULL;
	diradmin_group * oldgroup;diradmin_group * newgroup;
	ldaptransaction*t;
	int ldap_errors;
	GList* currentelement;


	userentry = cached_dir_entries_getbydn(dn);
	if (userentry == NULL) return;


	for (currentelement=cached_dir_entries;currentelement;currentelement=currentelement->next)
	if (dir_entry_is_group(currentelement->data))
	{
		groupentry = currentelement->data;
		groupdn = dir_entry_get_dn(groupentry);
		g_print("\nRemoving user %s from group %s\n",userentry->cn,groupentry->cn);
		oldgroup = diradmin_group_new_from_ldap(current_connection_profile,groupdn);
		g_assert(oldgroup);
		//g_print("Duplicating group\n"); BUG fix so duplicate can be used!
		//		newgroup = diradmin_group_duplicate(oldgroup);
		newgroup = diradmin_group_new_from_ldap(current_connection_profile,groupdn);
		g_assert(newgroup);
		//diradmin_group_dump_dnmembers(newgroup);
		//g_print("Removing %s from this group\n",dn);
		diradmin_group_remove_member(newgroup,userentry->uid);
		diradmin_group_remove_dnmember(newgroup,dn);
		//diradmin_group_dump_dnmembers(newgroup);

		//g_print("Generating difference\n");
		t = diradmin_group_generate_ldapdiff (oldgroup, newgroup);

		ldaptransaction_dump(t);
		if (ldaptransaction_has_mods)	{
			//g_print("Committing operation to the directory\n");
			ldap_errors =
			connection_profile_commit_modifications
			(current_connection_profile, t->mods,groupdn);
			if (ldap_errors) {
				g_print("There was an LDAP error while removing this user from the group\n");
			}
		}
		ldaptransaction_destroy(t);
		diradmin_group_destroy(oldgroup);
		diradmin_group_destroy(newgroup);

	}
}


void _add_this_dn_to_this_group(char*dn,gint gidnumber) {
	char*groupdn = NULL;
	dir_entry*groupentry = NULL;
	diradmin_group * oldgroup;diradmin_group * newgroup;
	ldaptransaction*t;
	int ldap_errors;


	//g_print("\nAdding %s to group with gid number %d\n",dn,gidnumber);
	groupentry = cached_dir_entries_getgroupbygidnumber(gidnumber);
	if (groupentry == NULL) return;
	g_print("\nAdding %s to group with gid number %d\n",dn,gidnumber);

	groupdn = dir_entry_get_dn(groupentry);

	//g_print("\n\nBringing group %s to the match\n",groupdn);
	oldgroup = diradmin_group_new_from_ldap(current_connection_profile,groupdn);
	g_assert(oldgroup);
	//g_print("Duplicating the group\n");
	//		newgroup = diradmin_group_duplicate(oldgroup);
	newgroup = diradmin_group_new_from_ldap(current_connection_profile,groupdn);
	g_assert(newgroup);
	diradmin_group_add_dnmember(newgroup,dn);

	t = diradmin_group_generate_ldapdiff (oldgroup, newgroup);
	//g_print("Removing %s to this group\n",dn);
	ldaptransaction_dump(t);
	if (ldaptransaction_has_mods)	{
		ldap_errors =
		connection_profile_commit_modifications
		(current_connection_profile, t->mods,groupdn);
		if (ldap_errors) {
			g_print("There was an LDAP error while adding this user's DN to the new group\n");
		}
	}
	ldaptransaction_destroy(t);
	diradmin_group_destroy(oldgroup);
	diradmin_group_destroy(newgroup);

}


void _group_remove_memberuid(char*groupdn,char*uid) {
	diradmin_group * oldgroup;diradmin_group * newgroup;
	ldaptransaction*t;
	int ldap_errors;

	g_print("\nRemoving UID %s from group %s\n",uid,groupdn);

	//g_print("\n\nBringing group %s to the match\n",groupdn);
	oldgroup = diradmin_group_new_from_ldap(current_connection_profile,groupdn);
	g_assert(oldgroup);
	//g_print("Duplicating group\n");
	//		newgroup = diradmin_group_duplicate(oldgroup);
	newgroup = diradmin_group_new_from_ldap(current_connection_profile,groupdn);
	g_assert(newgroup);
	//diradmin_group_dump_dnmembers(newgroup);
	//g_print("Removing %s from this group\n",dn);
	diradmin_group_remove_member(newgroup,uid);
	//diradmin_group_dump_dnmembers(newgroup);

	//g_print("Generating difference\n");
	t = diradmin_group_generate_ldapdiff (oldgroup, newgroup);

	ldaptransaction_dump(t);
	if (ldaptransaction_has_mods)	{
		//g_print("Committing operation to the directory\n");
		ldap_errors =
		connection_profile_commit_modifications
		(current_connection_profile, t->mods,groupdn);
		if (ldap_errors) {
			g_print("There was an LDAP error while removing this user's UID from the group\n");
		}
	}
	ldaptransaction_destroy(t);
	diradmin_group_destroy(oldgroup);
	diradmin_group_destroy(newgroup);

}


void _group_add_memberuid(char*groupdn,char*uid) {
	diradmin_group * oldgroup;diradmin_group * newgroup;
	ldaptransaction*t;
	int ldap_errors;


	//g_print("\nAdding %s to group with gid number %d\n",dn,gidnumber);
	g_print("\nAdding UID %s to group %s\n",uid,groupdn);

	//g_print("\n\nBringing group %s to the match\n",groupdn);
	oldgroup = diradmin_group_new_from_ldap(current_connection_profile,groupdn);
	g_assert(oldgroup);
	//g_print("Duplicating the group\n");
	//		newgroup = diradmin_group_duplicate(oldgroup);
	newgroup = diradmin_group_new_from_ldap(current_connection_profile,groupdn);
	g_assert(newgroup);
	diradmin_group_add_member(newgroup,uid);

	t = diradmin_group_generate_ldapdiff (oldgroup, newgroup);
	//g_print("Removing %s to this group\n",dn);
	ldaptransaction_dump(t);
	if (ldaptransaction_has_mods)	{
		ldap_errors =
		connection_profile_commit_modifications
		(current_connection_profile, t->mods,groupdn);
		if (ldap_errors) {
			g_print("There was an LDAP error while adding the uid to the group\n");
		}
	}
	ldaptransaction_destroy(t);
	diradmin_group_destroy(oldgroup);
	diradmin_group_destroy(newgroup);

}

void _group_switch_memberuids(char*groupdn,char*olduid,char*newuid) {
	diradmin_group * oldgroup;diradmin_group * newgroup;
	ldaptransaction*t;
	int ldap_errors;


	//g_print("\nAdding %s to group with gid number %d\n",dn,gidnumber);
	g_print("\nSwitching UIDs from %s to %s in group %s\n",olduid,newuid,groupdn);

	//g_print("\n\nBringing group %s to the match\n",groupdn);
	oldgroup = diradmin_group_new_from_ldap(current_connection_profile,groupdn);
	g_assert(oldgroup);
	//g_print("Duplicating the group\n");
	//		newgroup = diradmin_group_duplicate(oldgroup);
	newgroup = diradmin_group_new_from_ldap(current_connection_profile,groupdn);
	g_assert(newgroup);
	diradmin_group_remove_member(newgroup,olduid);
	diradmin_group_add_member(newgroup,newuid);

	t = diradmin_group_generate_ldapdiff (oldgroup, newgroup);
	//g_print("Removing %s to this group\n",dn);
	ldaptransaction_dump(t);
	if (ldaptransaction_has_mods)	{
		ldap_errors =
		connection_profile_commit_modifications
		(current_connection_profile, t->mods,groupdn);
		if (ldap_errors) {
			g_print("There was an LDAP error while switching UIDs in the group\n");
		}
	}
	ldaptransaction_destroy(t);
	diradmin_group_destroy(oldgroup);
	diradmin_group_destroy(newgroup);

}

void app_enable_filtercontrols (void) {
 gtk_widget_set_sensitive(lookup_widget(app,"filter"),TRUE);
 gtk_widget_set_sensitive(lookup_widget(app,"filterdropdown"),TRUE);
 gtk_widget_set_sensitive(lookup_widget(app,"filtertype"),TRUE);
 gtk_widget_set_sensitive(lookup_widget(app,"filterbutton"),TRUE);
 gtk_widget_set_sensitive(lookup_widget(app,"filterclear"),TRUE);
 gtk_widget_set_sensitive(lookup_widget(app,"filteradvanced"),TRUE);
 app_filter_fill();

}

void app_disable_filtercontrols (void) {
 gtk_widget_set_sensitive(lookup_widget(app,"filter"),FALSE);
 gtk_widget_set_sensitive(lookup_widget(app,"filterdropdown"),FALSE);
 gtk_widget_set_sensitive(lookup_widget(app,"filtertype"),FALSE);
 gtk_widget_set_sensitive(lookup_widget(app,"filterbutton"),FALSE);
 gtk_widget_set_sensitive(lookup_widget(app,"filterclear"),FALSE);
 gtk_widget_set_sensitive(lookup_widget(app,"filteradvanced"),FALSE);
 app_filter_fill();

}

void app_filter_fill (void )
{

  //gint i;
  GList * dnlist;
  GtkEntry*m;

  dnlist = get_orgunit_dn_list_from_cache ();

  gtk_combo_set_popdown_strings (GTK_COMBO (lookup_widget(app,"filterdropdown")),dnlist);

m=(GtkEntry*)lookup_widget(app,"filter");
gtk_entry_set_text(m,"");
}



int app_delete_interactive(GList *dns) {
	LDAP *conn;
	int ldap_errors = LDAP_SUCCESS;
	gchar *message;
	int wasthereanerror = LDAP_SUCCESS;
	gchar *dn;
	GList *iter;
	dir_entry*current;
	dir_entry*temp;
	gboolean erase;
	gint objectn = 0;
	char buf[2048];

	conn = connection_profile_get_ldap_handler (current_connection_profile);

	for (iter=dns;iter;iter=iter->next) {
		erase = 1;
		dn = iter->data;
		g_assert(dn);
		current = cached_dir_entries_getbydn(dn);
		g_assert(current);
		message = g_strconcat ("Deleting ",current->name," (",dn,")...",NULL);
		app_set_status(message);
		g_free(message);
		if (dir_entry_is_user(current)) {
			//borrar de LDAP este dato
			//_delete_this_dn_from_this_group(dn,current->gidnumber);
			///borrar de LDAP este otro dato
			_delete_this_user_from_all_groups(current->dn);
		}
		else if (dir_entry_is_group(current)) {
			temp = cached_dir_entries_getbygidnumber(current->gidnumber);
			if (temp) {
				erase = 0;
				message = g_strconcat (
				"The group ",current->cn," cannot be deleted because it is ",
				"the primary group for ",temp->name,NULL);
				gtk_widget_show (create_messagebox_with_message (message));
				g_free(message);
			}
		}
		if (erase) {
			g_print("\nDeleting entry %s...",dn);
			ldap_errors = ldap_delete_s (conn, dn);
			if (ldap_errors != LDAP_SUCCESS) wasthereanerror = ldap_errors;
			else app_delete_dir_entry(dn);
			objectn++;
		}
	}
	if (wasthereanerror)
	{
		message = g_strconcat (
			"One or more of the selected objects could not be deleted:\n",
			ldap_err2string (wasthereanerror), NULL);
		gtk_widget_show (create_messagebox_with_message (message));
		g_free(message);
	}
	snprintf(buf,sizeof(buf)-1,"%d",objectn);
	if (objectn == 1)
		message = g_strconcat((const gchar*)&buf," object deleted from the directory",NULL);
	else
		message = g_strconcat((const gchar*)&buf," objects deleted from the directory",NULL);
	app_set_status(message);
	g_free(message);
	return wasthereanerror;
}

void app_delete_dir_entry(char*dn) {

    g_assert(dn);
    cached_dir_entries_remove_bydn (dn);
    objectview_fill();
//    objectview_select_first();

//    objectview_remove_bydn (dn);

}

void app_add_dir_entry (dir_entry* d) {
    g_assert(d);

    g_print("\nThe following entry was just added to the directory:");
    dir_entry_dump(d);
    cached_dir_entries_add (d);
    objectview_fill ();

}

void cached_dir_entries_add(dir_entry*d) {

cached_dir_entries = g_list_append(cached_dir_entries,d);
cached_dir_entries = g_list_sort(cached_dir_entries,(GCompareFunc)
                             dir_entry_compare);

}

void cached_dir_entries_remove_bydn(char*dn) {

GList* a;
dir_entry* b;


g_assert(dn);

//g_print("\nDeleting entry %s from directory cache\n",dn);
//g_print("\nLooping through directory cache");
for (a= g_list_first(cached_dir_entries);a;a=g_list_next(a))
{
  b = a->data;
  g_assert(b);
//  g_print("\n   Current entry DN: %s",dir_entry_get_dn(b));
  if (g_strcasecmp (dn,dir_entry_get_dn(b)) == 0) {
//    g_print("\n      Matched entry %s, deleting...",dn);
    cached_dir_entries = g_list_remove(cached_dir_entries,b);
    dir_entry_destroy(b);
    break;
  }
}

}

void cached_dir_entries_refetch(connection_profile* c) {

g_list_foreach (cached_dir_entries,(GFunc) dir_entry_destroy, NULL);
g_list_free (cached_dir_entries);
cached_dir_entries = NULL;
cached_dir_entries = refresh_directory_data(c);
cached_dir_entries = g_list_sort(cached_dir_entries,(GCompareFunc)
                             dir_entry_compare);

//dir_entry_list_dump(cached_dir_entries);

//g_print("\nThis was just brought in from the directory:");
//dir_entry_list_dump(cached_dir_entries);

}


void app_enable_editing_controls (void ) {

      gtk_widget_set_sensitive (lookup_widget
                                (GTK_WIDGET (app),
                                 "button_modifyselection"), TRUE);
      gtk_widget_set_sensitive (lookup_widget
                                (GTK_WIDGET (app),
                                 "button_removeselection"), TRUE);
      gtk_widget_set_sensitive (lookup_widget
                                (GTK_WIDGET (app), "modify1"),
                                TRUE);
      gtk_widget_set_sensitive (lookup_widget
                                (GTK_WIDGET (app), "remove1"),
                                TRUE);
}
void app_disable_editing_controls (void ) {

      gtk_widget_set_sensitive (lookup_widget
                                (GTK_WIDGET (app),
                                 "button_modifyselection"), FALSE);
      gtk_widget_set_sensitive (lookup_widget
                                (GTK_WIDGET (app),
                                 "button_removeselection"), FALSE);
      gtk_widget_set_sensitive (lookup_widget
                                (GTK_WIDGET (app), "modify1"),
                                FALSE);
      gtk_widget_set_sensitive (lookup_widget
                                (GTK_WIDGET (app), "remove1"),
                                FALSE);
}

dir_entry* cached_dir_entries_getbydn(char* dn){
g_assert(dn);
  return dir_entry_list_getbydn(cached_dir_entries,dn);
}
dir_entry* cached_dir_entries_getbyuid(char* uid){
g_assert(uid);
  return dir_entry_list_getbyuid(cached_dir_entries,uid);
}
dir_entry* cached_dir_entries_getbygidnumber(int gid){
  return dir_entry_list_getbygidnumber(cached_dir_entries,gid);
}
dir_entry* cached_dir_entries_getgroupbygidnumber(int gid){
  return dir_entry_list_getgroupbygidnumber(cached_dir_entries,gid);
}
gboolean cached_dir_entries_has_groups(void){
  if (dir_entry_list_getfirstgroup(cached_dir_entries)) return TRUE;
  return FALSE;
}
gboolean cached_dir_entries_has_ous(void){
  if (dir_entry_list_getfirstou(cached_dir_entries)) return TRUE;
  return FALSE;
}

dir_entry* cached_dir_entries_getgroupbycn(gchar*cn){
  return dir_entry_list_getgroupbycn(cached_dir_entries,cn);
}


syntax highlighted by Code2HTML, v. 0.9.1