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

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

#include <glib.h>
#include "profile.h"
#include "appglobals.h"
#include "support.h"

connection_profile *
connection_profile_new (gchar * name, gchar * dn, gchar * pw, gchar * server,
			gint tls, gchar * treeroot)
{
  //creates new connection profile but doesn't connect yet
  connection_profile *newconn;
  newconn = g_new (connection_profile, 1);

  newconn->name = NULL;
  newconn->dn = NULL;
  newconn->pw = NULL;
  newconn->server = NULL;
  newconn->treeroot = NULL;
  newconn->connid = NULL;
  newconn->tls = tls;

  newconn->lastuserou = NULL;
  newconn->lastgroupou = NULL;

  connection_profile_set_name (newconn, name);
  connection_profile_set_dn (newconn, dn);
  connection_profile_set_password (newconn, pw);
  connection_profile_set_server (newconn, server);
  connection_profile_set_treeroot (newconn, treeroot);

  return newconn;
}

connection_profile *
connection_profile_duplicate (connection_profile * tobeduped)
{
  //creates new connection profile but doesn't connect yet
  connection_profile *newconn;
  newconn = g_new (connection_profile, 1);

  newconn->name = g_strdup (tobeduped->name);
  newconn->dn = g_strdup (tobeduped->dn);
  newconn->pw = g_strdup (tobeduped->pw);
  newconn->server = g_strdup (tobeduped->server);
  newconn->tls = tobeduped->tls;
  newconn->treeroot = g_strdup (tobeduped->treeroot);
  newconn->connid = NULL;

  newconn->lastuserou = g_strdup (tobeduped->lastuserou);
  newconn->lastgroupou = g_strdup (tobeduped->lastgroupou);

  return newconn;
}

void
connection_profile_destroy (connection_profile * todestroy)
{

  if (todestroy)
    {
      //frees all data structures, disconnects from the server, and frees the structure itself
      g_free (todestroy->name);
      g_free (todestroy->dn);
      g_free (todestroy->pw);
      g_free (todestroy->server);
      g_free (todestroy->treeroot);

      g_free (todestroy->lastuserou);
      g_free (todestroy->lastgroupou);

      //disconnect just in case
      connection_profile_disconnect (todestroy);
      g_free (todestroy);
      todestroy = NULL;
    }
  else
    {
//    g_print("destroy: connection profile is null... returning...\n"); return;
    }

}

void
connection_profile_set_name (connection_profile * conn, gchar * name)
{
  g_free (conn->name);
  if (name && strlen (name) > 0)
    conn->name = g_strdup (name);
}

void
connection_profile_set_dn (connection_profile * conn, gchar * dn)
{
  g_free (conn->dn);
  if (dn && strlen (dn) > 0)
    conn->dn = g_strdup (dn);
}

void
connection_profile_set_password (connection_profile * conn, gchar * pw)
{
  g_free (conn->pw);
  if (pw && strlen (pw) > 0)
    conn->pw = g_strdup (pw);
}

void
connection_profile_set_server (connection_profile * conn, gchar * server)
{
  g_free (conn->server);
  if (server && strlen (server) > 0)
    conn->server = g_strdup (server);
}

void
connection_profile_set_treeroot (connection_profile * conn, gchar * treeroot)
{
  g_free (conn->treeroot);
  if (treeroot && strlen (treeroot) > 0)
    conn->treeroot = g_strdup (treeroot);
}

// get functions

gchar *
connection_profile_get_name (connection_profile * conn)
{
  return conn->name;
}

gchar *
connection_profile_get_server (connection_profile * conn)
{
  return conn->server;
}

gint 
connection_profile_get_tls (connection_profile * conn)
{
  return conn->tls;
}

gchar *
connection_profile_get_dn (connection_profile * conn)
{
  return conn->dn;
}

gchar *
connection_profile_get_password (connection_profile * conn)
{
  return conn->pw;
}

gchar *
connection_profile_get_treeroot (connection_profile * conn)
{
  if (conn->treeroot == NULL)
    return (NULL);
  if (g_strcasecmp (conn->treeroot, "") == 0)
    return (NULL);
  return conn->treeroot;
}

void
connection_profile_set_last_user_ou (connection_profile * conn, gchar * ou)
{
  g_free (conn->lastuserou);
  if (ou && strlen (ou) > 0)
    conn->lastuserou = g_strdup (ou);
}

void
connection_profile_set_last_group_ou (connection_profile * conn, gchar * ou)
{
  g_free (conn->lastgroupou);
  if (ou && strlen (ou) > 0)
    conn->lastgroupou = g_strdup (ou);
}

gchar *
connection_profile_get_last_user_ou (connection_profile * conn)
{
  g_print ("%s", conn->lastuserou);
  return conn->lastuserou;
}

gchar *
connection_profile_get_last_group_ou (connection_profile * conn)
{
  return conn->lastgroupou;
}


LDAP *
connection_profile_get_ldap_handler (connection_profile * conn)
{
  g_assert (conn);
  return conn->connid;
}


//connection functions

void
connection_profile_disconnect (connection_profile * conn)
{
  if (conn)
    {
      if (conn->connid == NULL)
	return;
      ldap_unbind (conn->connid);
      conn->connid = NULL;
    }
}

gboolean
connection_profile_is_connected (connection_profile * conn)
{
  if (conn)
    if (conn->connid)
      return (TRUE);
  return (FALSE);
}

/* connection_profile_connect
   tries to connect to profile, the returns LDAP error value  */

int
connection_profile_connect (connection_profile * conn)
{
  LDAP *connectionhandler = NULL;
  int ldap_errors;
  gchar *userid;
  gchar *pw;
  gchar *root;
  gchar *server;
      int version;

// for testing if an user exists
  gchar *filter = NULL;
  LDAPMessage *results = NULL;
  LDAPMessage *entry = NULL;
  gchar *attributetoreturn[2];
/*  char **value_collection;
  char **oc_collection;
  int oc_iterator;*/

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

  server = connection_profile_get_server (conn);
  userid = connection_profile_get_dn (conn);
  pw = connection_profile_get_password (conn);
  root = connection_profile_get_treeroot (conn);

  if (connection_profile_is_connected (conn))
    connection_profile_disconnect (conn);

  connectionhandler = ldap_init (server, LDAP_PORT);

  // for tls connection
  if (conn->tls)
  {
#   ifdef HAVE_TLS
    version = LDAP_VERSION3;
    if (ldap_set_option(connectionhandler, LDAP_OPT_PROTOCOL_VERSION,
        &version) == LDAP_OPT_SUCCESS)
    {
      ldap_errors = ldap_start_tls_s(connectionhandler, NULL, NULL);
      if (ldap_errors != LDAP_SUCCESS)
      {
        ldap_unbind(connectionhandler);
		connectionhandler = NULL;
        g_print("Error enabling TLS on the LDAP connection\n");
        return(ldap_errors);
      }
    }
    else
    {
      g_print("Error: cannot set protocol to LDAPv3\n");
      return (LDAP_PROTOCOL_ERROR);
    }
#   else
    g_print("TLS was not found by configure to be supported by ");
    g_print("your ldap libraries.\n");
#   endif
  }

  if (userid && strlen(userid) > 0 && strchr(userid,'=') == NULL) {
   // nos pasaron un UNIX user ID - tratemos de buscarlo
     ldap_errors = ldap_simple_bind_s (connectionhandler, NULL, NULL);

    if (ldap_errors)
      {
   // oops no pudimos pegarnos al dir.
        connection_profile_disconnect (conn);
        return (ldap_errors);
      }
    else
      {

        //a buscar el uid
        filter = g_strconcat("(&(|(objectClass=account)(objectClass=posixAccount))(uid=",userid,"))",NULL);
        ldap_errors =
         ldap_search_s (connectionhandler, root, LDAP_SCOPE_SUBTREE, filter, attributetoreturn, 0, &results);
        g_free(filter);

        if (ldap_count_entries (connectionhandler,results) == 0) {
          ldap_msgfree (results);
          connection_profile_disconnect (conn);
          return (LDAP_INVALID_CREDENTIALS);
        }

        // parece que si hay usuario
        entry=ldap_first_entry(connectionhandler,results);
        userid = ldap_get_dn(connectionhandler,entry);

        ldap_msgfree (results);
        connection_profile_disconnect (conn);

      }

  }

  ldap_errors = ldap_simple_bind_s (connectionhandler,
				    userid,
				    connection_profile_get_password (conn));
    version = LDAP_VERSION3;
    if (ldap_set_option(connectionhandler, LDAP_OPT_PROTOCOL_VERSION,
        &version)!= LDAP_OPT_SUCCESS) g_print("Could not set protocol version 3, continuing anyway\n" );

  if (ldap_errors)
    {
      connection_profile_disconnect (conn);
      return (ldap_errors);
    }
  else
    {
      conn->connid = connectionhandler;
      return (0);
    }

}

connection_profile *
connection_profile_list_getbyname (GList * connec, gchar * nombre)
{

  GList *loopix = g_list_first (connec);
  connection_profile *now = NULL;


  while (loopix != NULL)
    {
      g_assert (connection_profile_get_name (loopix->data));
      if (g_strcasecmp (nombre, connection_profile_get_name (loopix->data)) ==
	  0)
	{
	  now = loopix->data;
//              g_print("\nconnection_profile_list_getbyname: found a match! ");
//              g_print(connection_profile_get_name(loopix->data));
	  g_print ("\n");
	}
      loopix = g_list_next (loopix);
    }
  return (now);

}



GList *
connection_profile_list_remove (GList * connec, connection_profile * nombre)
{

  g_assert (connec);
  g_assert (nombre);
  connec = g_list_remove (connec, nombre);
  connection_profile_destroy (nombre);
  return connec;

}

GList *
connection_profile_list_add (GList * connec, connection_profile * nombre)
{

  g_assert (nombre);
  connec = g_list_append (connec, nombre);
  return connec;

}


// ldap utility functions - maybe temporarily here

void
dump_mods (LDAPMod ** mods)
{
  LDAPMod *mod;
  int cmod, cval;

  cmod = 0;
  while (mods[cmod])
    {
      mod = mods[cmod];
      switch (mod->mod_op)
	{
	case LDAP_MOD_ADD:
	  g_print ("LDAP_MOD_ADD");
	  break;
	case LDAP_MOD_DELETE:
	  g_print ("LDAP_MOD_DELETE");
	  break;
	case LDAP_MOD_REPLACE:
	  g_print ("LDAP_MOD_REPLACE");
	  break;
	case LDAP_MOD_BVALUES:
	  g_print ("LDAP_MOD_BVALUES");
	  break;
	}
      g_print (" %s\n", mod->mod_type);
      cval = 0;
      while (mod->mod_values && mod->mod_values[cval])
	{
	  g_print ("\t%s\n", mod->mod_values[cval]);
	  cval++;
	}

      cmod++;
    }

}

int
connection_profile_commit_modifications (connection_profile * conn,
					 LDAPMod ** modifications, char *dn)
{
  int ldap_errors;
  g_assert (connection_profile_get_ldap_handler (conn));
  g_assert (modifications);
  g_assert (dn);
  ldap_errors = ldap_modify_s (connection_profile_get_ldap_handler (conn),
			       dn, modifications);
  /*g_print ("modifications have been done:\n\n");
  dump_mods (modifications);*/
  return (ldap_errors);

}

int
connection_profile_create_record (connection_profile * conn,
				  LDAPMod ** modifications, char *dn)
{
  int ldap_errors;

  g_print ("\ncalled: ldap_create_record\n");
  g_assert (connection_profile_get_ldap_handler (conn));
  g_assert (modifications);
  g_assert (dn);
  ldap_errors = ldap_add_s (connection_profile_get_ldap_handler (conn),
			    dn, modifications);
  dump_mods (modifications);
  g_print (ldap_err2string (ldap_errors));
  return (ldap_errors);

}


void connection_profile_invalidate(connection_profile * d) {
		d->connid = NULL;
		if (d==current_connection_profile) {
      gtk_toggle_button_set_active ((GtkToggleButton *)
				    lookup_widget (app,   "button_connect"),   FALSE);
		}


}




syntax highlighted by Code2HTML, v. 0.9.1