2007-04-17 [wwp] 2.9.0cvs3
authorTristan Chabredier <wwp@claws-mail.org>
Tue, 17 Apr 2007 09:16:46 +0000 (09:16 +0000)
committerTristan Chabredier <wwp@claws-mail.org>
Tue, 17 Apr 2007 09:16:46 +0000 (09:16 +0000)
* src/Makefile.am
* src/addressadd.c
* src/addressbook.c
* src/addrindex.c
* src/addritem.c
* src/addritem.h
* src/editaddress.c
* src/ldapctrl.c
* src/ldapctrl.h
* src/ldapquery.c
* src/ldapserver.c
* src/ldapserver.h
* src/ldapupdate.c
* src/ldapupdate.h
Add LDAP write support. Patch mostly by
Michael <mir at datanom dot net>

17 files changed:
ChangeLog
PATCHSETS
configure.ac
src/Makefile.am
src/addressadd.c
src/addressbook.c
src/addrindex.c
src/addritem.c
src/addritem.h
src/editaddress.c
src/ldapctrl.c
src/ldapctrl.h
src/ldapquery.c
src/ldapserver.c
src/ldapserver.h
src/ldapupdate.c [new file with mode: 0644]
src/ldapupdate.h [new file with mode: 0644]

index ac6f66b15eda41b27bcee72802ddf0c9ed5c1b54..355d39f1615e2e6e92d99daaa4273b1c5a800e52 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2007-04-17 [wwp]       2.9.0cvs3
+
+       * src/Makefile.am
+       * src/addressadd.c
+       * src/addressbook.c
+       * src/addrindex.c
+       * src/addritem.c
+       * src/addritem.h
+       * src/editaddress.c
+       * src/ldapctrl.c
+       * src/ldapctrl.h
+       * src/ldapquery.c
+       * src/ldapserver.c
+       * src/ldapserver.h
+       * src/ldapupdate.c
+       * src/ldapupdate.h
+               Add LDAP write support. Patch mostly by 
+               Michael <mir at datanom dot net>
+
 2007-04-17 [wwp]       2.9.0cvs2
 
        * src/compose.c
index f89e02740395005194d7bf7bef2ed9dde10339bb..cc061c85f8224f39e13461c935415694a27d8054 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.42.2.30 -r 1.42.2.31 po/fr.po;  ) > 2.8.1cvs102.patchset
 ( cvs diff -u -r 1.1.2.35 -r 1.1.2.36 src/gtk/authors.h;  ) > 2.9.0cvs1.patchset
 ( cvs diff -u -r 1.382.2.369 -r 1.382.2.370 src/compose.c;  ) > 2.9.0cvs2.patchset
+( cvs diff -u -r 1.155.2.60 -r 1.155.2.61 src/Makefile.am;  cvs diff -u -r 1.9.2.13 -r 1.9.2.14 src/addressadd.c;  cvs diff -u -r 1.60.2.84 -r 1.60.2.85 src/addressbook.c;  cvs diff -u -r 1.28.2.25 -r 1.28.2.26 src/addrindex.c;  cvs diff -u -r 1.13.2.10 -r 1.13.2.11 src/addritem.c;  cvs diff -u -r 1.12.2.8 -r 1.12.2.9 src/addritem.h;  cvs diff -u -r 1.14.2.23 -r 1.14.2.24 src/editaddress.c;  cvs diff -u -r 1.2.2.8 -r 1.2.2.9 src/ldapctrl.c;  cvs diff -u -r 1.1.4.9 -r 1.1.4.10 src/ldapctrl.h;  cvs diff -u -r 1.3.2.17 -r 1.3.2.18 src/ldapquery.c;  cvs diff -u -r 1.4.2.8 -r 1.4.2.9 src/ldapserver.c;  cvs diff -u -r 1.2.2.7 -r 1.2.2.8 src/ldapserver.h;  diff -u /dev/null src/ldapupdate.c;  diff -u /dev/null src/ldapupdate.h;  ) > 2.9.0cvs3.patchset
index 90cad19f15e7d74250a0af5c01a2a433cf051932..b9e25ad95c7d7880e9b98e853678d31ba974f248 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=9
 MICRO_VERSION=0
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=2
+EXTRA_VERSION=3
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
index 78878ecd03002d286319d38b45750c48d79f87e4..9760e738f742d08e29df05011d6974c3668a858b 100644 (file)
@@ -73,6 +73,7 @@ claws_mail_SOURCES = \
        ldaplocate.c \
        ldapquery.c \
        ldapserver.c \
+       ldapupdate.c \
        ldaputil.c \
        ldif.c \
        localfolder.c \
@@ -214,6 +215,7 @@ claws_mailinclude_HEADERS = \
        ldaplocate.h \
        ldapquery.h \
        ldapserver.h \
+       ldapupdate.h \
        ldaputil.h \
        ldif.h \
        localfolder.h \
@@ -318,7 +320,7 @@ EXTRA_DIST = \
        pixmaps/dir_close.xpm \
        pixmaps/dir_close_hrm.xpm \
        pixmaps/dir_noselect.xpm \
-        pixmaps/dir_open_hrm.xpm \
+    pixmaps/dir_open_hrm.xpm \
        pixmaps/dir_open.xpm \
        pixmaps/down_arrow.xpm \
        pixmaps/drafts_close.xpm \
index 71165c3f1dec05b82b90396a09204a8a7cce271c..8631a0541c45c1da3368727dd02426159ef94337 100644 (file)
@@ -46,6 +46,9 @@
 #include "addrbook.h"
 #include "addrindex.h"
 #include "manage_window.h"
+#include "ldapserver.h"
+#include "ldapupdate.h"
+#include "alertpanel.h"
 
 typedef struct {
        AddressBookFile *book;
@@ -339,7 +342,8 @@ static void addressadd_load_data( AddressIndex *addrIndex ) {
        list = addrindex_get_interface_list( addrIndex );
        while( list ) {
                AddressInterface *interface = list->data;
-               if( interface->type == ADDR_IF_BOOK ) {
+               if( interface->type == ADDR_IF_BOOK || 
+                               interface->type == ADDR_IF_LDAP ) {
                        nodeDS = interface->listSource;
                        while( nodeDS ) {
                                ds = nodeDS->data;
@@ -378,6 +382,7 @@ gboolean addressadd_selection( AddressIndex *addrIndex, const gchar *name, const
        ItemPerson *person = NULL;
        FolderInfo *fi = NULL;
        addressadd_cancelled = FALSE;
+
        if( ! addressadd_dlg.window ) addressadd_create();
        gtk_widget_grab_focus(addressadd_dlg.ok_btn);
        gtk_widget_show(addressadd_dlg.window);
@@ -415,6 +420,18 @@ gboolean addressadd_selection( AddressIndex *addrIndex, const gchar *name, const
                                                        returned_name, 
                                                        address, 
                                                        returned_remarks);
+                       person->status = ADD_ENTRY;
+                       if (fi->book->type == ADBOOKTYPE_LDAP) {
+                               LdapServer *server = (LdapServer *) fi->book;
+                               ldapsvr_set_modified(server, TRUE);
+                               ldapsvr_update_book(server, person);
+                               if (server->retVal != LDAPRC_SUCCESS) {
+                                       alertpanel( _("Add address(es)"),
+                                               _("Can't add the specified address"),
+                                               GTK_STOCK_CLOSE, NULL, NULL );
+                                       return server->retVal;
+                               }
+                       }
                        g_free(returned_name);
                        g_free(returned_remarks);
                        if( person ) retVal = TRUE;
index cfb0c1bce628a1e35c8b4d95c609381a8f420ded..eb6d0c9fdaf3723a48429a7b5b5eb8f7abd5ac29 100644 (file)
@@ -89,6 +89,7 @@
 #include <pthread.h>
 #include "ldapserver.h"
 #include "editldap.h"
+#include "ldapupdate.h"
 
 #define ADDRESSBOOK_LDAP_BUSYMSG "Busy"
 #endif
@@ -534,17 +535,21 @@ static ErrMsgTableEntry _lutErrorsGeneral_[] = {
  * Lookup table of error messages for LDAP errors.
  */
 static ErrMsgTableEntry _lutErrorsLDAP_[] = {
-       { LDAPRC_SUCCESS,       N_("Success") },
-       { LDAPRC_CONNECT,       N_("Error connecting to LDAP server") },
-       { LDAPRC_INIT,          N_("Error initializing LDAP") },
-       { LDAPRC_BIND,          N_("Error binding to LDAP server") },
-       { LDAPRC_SEARCH,        N_("Error searching LDAP database") },
-       { LDAPRC_TIMEOUT,       N_("Timeout performing LDAP operation") },
-       { LDAPRC_CRITERIA,      N_("Error in LDAP search criteria") },
-       { LDAPRC_NOENTRIES,     N_("No LDAP entries found for search criteria") },
-       { LDAPRC_STOP_FLAG,     N_("LDAP search terminated on request") },
-       { LDAPRC_TLS,           N_("Error starting TLS connection") },
-       { 0,                    NULL }
+       { LDAPRC_SUCCESS,                       N_("Success") },
+       { LDAPRC_CONNECT,                       N_("Error connecting to LDAP server") },
+       { LDAPRC_INIT,                          N_("Error initializing LDAP") },
+       { LDAPRC_BIND,                          N_("Error binding to LDAP server") },
+       { LDAPRC_SEARCH,                        N_("Error searching LDAP database") },
+       { LDAPRC_TIMEOUT,                       N_("Timeout performing LDAP operation") },
+       { LDAPRC_CRITERIA,                      N_("Error in LDAP search criteria") },
+       { LDAPRC_NOENTRIES,                     N_("No LDAP entries found for search criteria") },
+       { LDAPRC_STOP_FLAG,                     N_("LDAP search terminated on request") },
+       { LDAPRC_TLS,                           N_("Error starting TLS connection") },
+       { LDAPRC_NODN,                          N_("Distinguised Name (dn) is missing") },
+       { LDAPRC_NAMING_VIOLATION,              N_("Missing required information") },
+       { LDAPRC_ALREADY_EXIST,                 N_("Another contact exists with that key") },
+       { LDAPRC_STRONG_AUTH,                   N_("Strong(er) authentication required") },
+       { 0,                                    NULL }
 };
 #endif
 
@@ -1456,10 +1461,16 @@ static void addressbook_del_clicked(GtkButton *button, gpointer data)
                        }
                        else if( aio->type == ADDR_ITEM_PERSON ) {
                                ItemPerson *item = ( ItemPerson * ) aio;
+                               item->status = DELETE_ENTRY; 
                                addressbook_folder_remove_one_person( clist, item );
                                if (pobj->type == ADDR_ITEM_FOLDER)
                                        addritem_folder_remove_person(ADAPTER_FOLDER(pobj)->itemFolder, item);
                                item = addrbook_remove_person( abf, item );
+                               if (ds->type == ADDR_IF_LDAP) {
+                                       LdapServer *server = ds->rawDataSource;
+                                       ldapsvr_set_modified(server, TRUE);
+                                       ldapsvr_update_book(server, item);
+                               }
                                if( item ) {
                                        addritem_free_item_person( item );
                                }
@@ -1881,7 +1892,8 @@ static void addressbook_list_menu_setup( void ) {
                iface = ds->interface;
                if( ! iface->readOnly ) {
                        menu_set_sensitive( addrbook.list_factory, "/New Address", TRUE );
-                       menu_set_sensitive( addrbook.list_factory, "/New Group", TRUE );
+                       if (iface->type != ADDR_IF_LDAP)
+                               menu_set_sensitive( addrbook.list_factory, "/New Group", TRUE );
                        gtk_widget_set_sensitive( addrbook.reg_btn, TRUE );
                        if( ! addrclip_is_empty( _clipBoard_ ) ) canPaste = TRUE;
                        if( ! addrselect_test_empty( _addressSelect_ ) ) canCut = TRUE;
@@ -1902,7 +1914,8 @@ static void addressbook_list_menu_setup( void ) {
                        }
                        /* Folder */
                        if( pobj->type == ADDR_ITEM_FOLDER ) {
-                               menu_set_sensitive( addrbook.list_factory, "/New Group", TRUE );
+                               if (iface->type != ADDR_IF_LDAP)
+                                       menu_set_sensitive( addrbook.list_factory, "/New Group", TRUE );
                                if( obj ) canEdit = TRUE;
                        }
                        if( ! addrclip_is_empty( _clipBoard_ ) ) canPaste = TRUE;
@@ -1912,7 +1925,7 @@ static void addressbook_list_menu_setup( void ) {
                if( iface->type == ADDR_IF_LDAP ) {
                        if( obj ) canBrowse = TRUE;
                        canEdit = TRUE;
-                       canDelete = FALSE;
+                       canDelete = TRUE;
                }
        }
        if( ! addrselect_test_empty( _addressSelect_ ) ) canCopy = TRUE;
@@ -2849,6 +2862,7 @@ static void addressbook_treenode_delete_cb(
 static void addressbook_new_address_from_book_post_cb( ItemPerson *person )
 {
        if( person && addrbook.treeSelected == addrbook.opened ) {
+               person->status = ADD_ENTRY;
                gtk_clist_unselect_all( GTK_CLIST(addrbook.clist) );
                addressbook_folder_refresh_one_person(
                        GTK_CTREE(addrbook.clist), person );
@@ -2859,6 +2873,7 @@ static void addressbook_new_address_from_book_post_cb( ItemPerson *person )
 static void addressbook_new_address_from_folder_post_cb( ItemPerson *person )
 {
        if( person && addrbook.treeSelected == addrbook.opened) {
+               person->status = ADD_ENTRY;
                gtk_sctree_select( GTK_SCTREE(addrbook.ctree), addrbook.opened );
                addressbook_set_clist(
                        gtk_ctree_node_get_row_data(GTK_CTREE(addrbook.ctree),
@@ -2872,22 +2887,43 @@ static void addressbook_new_address_cb( gpointer data, guint action, GtkWidget *
        AddressObject *pobj = NULL;
        AddressDataSource *ds = NULL;
        AddressBookFile *abf = NULL;
-
+       debug_print("adding address\n");
        pobj = gtk_ctree_node_get_row_data(GTK_CTREE(addrbook.ctree), addrbook.treeSelected);
-       if( pobj == NULL ) return;
+       if( pobj == NULL ) {
+               debug_print("no row data\n");
+               return;
+       }
        ds = addressbook_find_datasource( GTK_CTREE_NODE(addrbook.treeSelected) );
-       if( ds == NULL ) return;
+       if( ds == NULL ) {
+               debug_print("no datasource\n");
+               return;
+       }
 
        abf = ds->rawDataSource;
-       if( abf == NULL ) return;
+       if( abf == NULL ) {
+               printf("no addressbook file\n");
+               return;
+       }
 
        if( pobj->type == ADDR_DATASOURCE ) {
-               if( ADAPTER_DSOURCE(pobj)->subType == ADDR_BOOK ) {
+               if (ADAPTER_DSOURCE(pobj)->subType == ADDR_BOOK ||
+                   ADAPTER_DSOURCE(pobj)->subType == ADDR_LDAP) {
                        /* New address */
                        ItemPerson *person = addressbook_edit_person( abf, NULL, NULL, FALSE,
-                                                                                                                 addrbook.editaddress_vbox,
-                                                                                                                 addressbook_new_address_from_book_post_cb,
-                                                                                                                 TRUE );
+                                                                 addrbook.editaddress_vbox,
+                                                                 addressbook_new_address_from_book_post_cb,
+                                                                 TRUE );
+                       if (abf->type == ADDR_IF_LDAP) {
+                               LdapServer *server = ds->rawDataSource;
+                               ldapsvr_set_modified(server, TRUE);
+                               ldapsvr_update_book(server, NULL);
+                               if (server->retVal != LDAPRC_SUCCESS) {
+                                       alertpanel( _("Add address(es)"),
+                                               addressbook_err2string(_lutErrorsLDAP_, server->retVal),
+                                               GTK_STOCK_CLOSE, NULL, NULL );
+                                       return;
+                               }
+                       }
                        if (prefs_common.addressbook_use_editaddress_dialog)
                                addressbook_new_address_from_book_post_cb( person );
                }
@@ -2896,9 +2932,20 @@ static void addressbook_new_address_cb( gpointer data, guint action, GtkWidget *
                /* New address */
                ItemFolder *folder = ADAPTER_FOLDER(pobj)->itemFolder;
                ItemPerson *person = addressbook_edit_person( abf, folder, NULL, FALSE,
-                                                                                                         addrbook.editaddress_vbox,
-                                                                                                         addressbook_new_address_from_folder_post_cb,
-                                                                                                         TRUE );
+                                                         addrbook.editaddress_vbox,
+                                                         addressbook_new_address_from_folder_post_cb,
+                                                         TRUE );
+               if (abf->type == ADDR_IF_LDAP) {
+                       LdapServer *server = ds->rawDataSource;
+                       ldapsvr_set_modified(server, TRUE);
+                       ldapsvr_update_book(server, NULL);
+                       if (server->retVal != LDAPRC_SUCCESS) {
+                               alertpanel( _("Add address(es)"),
+                                               addressbook_err2string(_lutErrorsLDAP_, server->retVal),
+                                       GTK_STOCK_CLOSE, NULL, NULL );
+                               return;
+                       }
+               }
                if (prefs_common.addressbook_use_editaddress_dialog)
                        addressbook_new_address_from_folder_post_cb( person );
        }
@@ -2951,7 +2998,7 @@ static AddressBookFile *addressbook_get_book_file() {
 
        ds = addressbook_find_datasource( addrbook.treeSelected );
        if( ds == NULL ) return NULL;
-       if( ds->type == ADDR_IF_BOOK ) abf = ds->rawDataSource;
+       if( ds->type == ADDR_IF_BOOK || ds->type == ADDR_IF_LDAP ) abf = ds->rawDataSource;
        return abf;
 }
 
@@ -2984,6 +3031,7 @@ static void addressbook_move_nodes_up( GtkCTree *ctree, GtkCTreeNode *node ) {
 static void addressbook_edit_address_post_cb( ItemPerson *person )
 {
        if( person ) {
+
                addressbook_folder_refresh_one_person( GTK_CTREE(addrbook.clist), person );
                invalidate_address_completion();
        }
@@ -3057,7 +3105,11 @@ static void addressbook_edit_address( gpointer data, guint action, GtkWidget *wi
                        if  ( addressbook_edit_person( abf, NULL, person, TRUE, addrbook.editaddress_vbox,
                                                                                   addressbook_edit_address_post_cb,
                                                                                   (prefs_common.addressbook_use_editaddress_dialog||force_focus) )
-                                 != NULL ) {
+                                 != NULL ) { 
+                               if (abf->type == ADDR_IF_LDAP) {
+                                       ldapsvr_set_modified( (LdapServer *) abf, TRUE );
+                                       person->status = UPDATE_ENTRY;
+                               }
                                if (prefs_common.addressbook_use_editaddress_dialog)
                                        addressbook_edit_address_post_cb( person );
                        }
@@ -3071,8 +3123,12 @@ static void addressbook_edit_address( gpointer data, guint action, GtkWidget *wi
                                                                          addressbook_edit_address_post_cb,
                                                                          (prefs_common.addressbook_use_editaddress_dialog||force_focus) )
                        != NULL ) {
-                       if (prefs_common.addressbook_use_editaddress_dialog)
-                               addressbook_edit_address_post_cb( person );
+                               if (abf->type == ADDR_IF_LDAP) {
+                                       ldapsvr_set_modified( (LdapServer *) abf, TRUE );
+                                       person->status = UPDATE_ENTRY;
+                               }
+                               if (prefs_common.addressbook_use_editaddress_dialog)
+                                       addressbook_edit_address_post_cb( person );
                }
                return;
        }
@@ -3208,6 +3264,9 @@ static void addressbook_folder_load_one_person(
                        if( str ) {
                                text[COL_NAME] = str;
                        }
+                       else if( person->nickName ) {
+                               text[COL_NAME] = person->nickName;
+                       }
                        else {
                                text[COL_NAME] = ADDRITEM_NAME(person);
                        }
index 8b05033c7a84a9ad4cdb23a67c6a816c2a5fce81..e2955ef0dd7782cbb4fd9cddae29f84c8d894fac 100644 (file)
@@ -40,6 +40,7 @@
 #include "addrquery.h"
 #include "addr_compl.h"
 #include "utils.h"
+#include "alertpanel.h"
 
 #ifndef DEV_STANDALONE
 #include "prefs_gtk.h"
@@ -56,6 +57,7 @@
 #include "ldapserver.h"
 #include "ldapctrl.h"
 #include "ldapquery.h"
+#include "ldapupdate.h"
 #include "ldaputil.h"
 #endif
 
@@ -290,14 +292,15 @@ static void addrindex_build_if_list( AddressIndex *addrIndex ) {
        iface = addrindex_create_interface(
                        ADDR_IF_LDAP, "LDAP", TAG_IF_LDAP, TAG_DS_LDAP );
 #ifdef USE_LDAP
+       iface->readOnly = FALSE;
        /* iface->haveLibrary = ldapsvr_test_ldap_lib(); */
        iface->haveLibrary = ldaputil_test_ldap_lib();
        iface->useInterface = iface->haveLibrary;
-       /* iface->getModifyFlag = ( void * ) ldapsvr_get_modified; */
+       iface->getModifyFlag = ( void * ) ldapsvr_get_modified;
        iface->getAccessFlag = ( void * ) ldapsvr_get_accessed;
-       /* iface->getReadFlag   = ( void * ) ldapsvr_get_read_flag; */
+       iface->getReadFlag   = ( void * ) ldapsvr_get_read_flag;
        iface->getStatusCode = ( void * ) ldapsvr_get_status;
-       /* iface->getReadData   = ( void * ) ldapsvr_read_data; */
+       iface->getReadData   = ( void * ) ldapsvr_read_data;
        iface->getRootFolder = ( void * ) ldapsvr_get_root_folder;
        iface->getListFolder = ( void * ) ldapsvr_get_list_folder;
        iface->getListPerson = ( void * ) ldapsvr_get_list_person;
@@ -1713,7 +1716,39 @@ static gint addrindex_write_to( AddressIndex *addrIndex, const gchar *newFile )
 * return: Status code, from addrIndex->retVal.
 */
 gint addrindex_save_data( AddressIndex *addrIndex ) {
+       GList *nodeIf, *nodeDS;
+
        g_return_val_if_fail( addrIndex != NULL, -1 );
+       nodeIf = addrIndex->interfaceList;
+
+       /* save LDAP interfaces */
+       while ( nodeIf ) {
+               AddressInterface *iface = nodeIf->data;
+               if( iface->type == ADDR_IF_LDAP ) {
+                       nodeDS = iface->listSource;
+                       while( nodeDS ) {
+                               AddressDataSource *ds = nodeDS->data;
+                               LdapServer *abf = ds->rawDataSource;
+                               if( ldapsvr_get_read_flag( abf ) ) {
+                                       if( ldapsvr_get_modified( abf ) ) {
+                                               ldapsvr_update_book( abf, NULL );
+                                               if( abf->retVal != LDAPRC_SUCCESS ) {
+                                                       alertpanel( _("Address(es) update"),
+                                                               _("Update failed. Changes not written to Directory."),
+                                                               GTK_STOCK_CLOSE, NULL, NULL );
+                                               }
+                                               else {
+                                                       abf->retVal = MGU_SUCCESS;
+                                                       ldapsvr_set_modified( abf, FALSE );
+                                               }
+                                       }
+                               }
+                               nodeDS = g_list_next( nodeDS );
+                       }
+                       break;
+               }
+               nodeIf = g_list_next( nodeIf );
+       }
 
        addrIndex->retVal = MGU_NO_FILE;
        if( addrIndex->fileName == NULL || *addrIndex->fileName == '\0' ) return addrIndex->retVal;
index fb3d6e6df6e6e01d024c38020d7b4e164193b842..8a1bbec90bc6c3c25b4e19be6375c76812046c11 100644 (file)
@@ -224,6 +224,7 @@ ItemPerson *addritem_create_item_person( void ) {
        person->listAttrib = NULL;
        person->externalID = NULL;
        person->isOpened = FALSE;
+       person->status = NONE;
        return person;
 }
 
@@ -243,6 +244,7 @@ ItemPerson *addritem_copy_item_person( ItemPerson *item ) {
                itemNew->lastName = g_strdup( item->lastName );
                itemNew->nickName = g_strdup( item->nickName );
                itemNew->externalID = g_strdup( item->externalID );
+               itemNew->status = item->status;
        }
        return itemNew;
 }
@@ -463,6 +465,17 @@ void addritem_print_item_person( ItemPerson *person, FILE *stream ) {
                addritem_print_attribute( node->data, stream );
                node = g_list_next( node );
        }
+       gchar *current_status;
+       switch (person->status) {
+               case NONE: current_status = g_strdup("Unchanged"); break;
+               case ADD_ENTRY: current_status = g_strdup("New"); break;
+               case UPDATE_ENTRY: current_status = g_strdup("Updated"); break;
+               case DELETE_ENTRY: current_status = g_strdup("Deleted"); break;
+               default: current_status = g_strdup("Unknown");
+       }
+       fprintf( stream, "\t\tStatus: %s\n", current_status );
+       if ( current_status )
+               g_free(current_status);
        fprintf( stream, "\t===\n" );
 }
 
index 6f8bf7814ee7552a4628eec83d412d87ce99646c..e5b8d231d75ceba502ca43c892f6db47a520bb32 100644 (file)
@@ -53,6 +53,13 @@ typedef enum {
        ADDRFOLDER_QUERY_RESULTS
 } AddressFolderType;
 
+typedef enum {
+       NONE,
+       ADD_ENTRY,
+       UPDATE_ENTRY,
+       DELETE_ENTRY
+} ContactStatus;
+
 typedef struct _AddrItemObject AddrItemObject;
 struct _AddrItemObject {
        ItemObjectType type;
@@ -72,6 +79,7 @@ struct _ItemPerson {
        GList    *listEMail;
        GList    *listAttrib;
        gboolean isOpened;
+       ContactStatus status;
 };
 
 typedef struct _ItemEMail ItemEMail;
index 9518f226c10f656c8321b83633702b9a5f24324a..2874f78c22812fdd0cfb37d7e5b9211d9f501d16 100644 (file)
@@ -83,6 +83,7 @@ static struct _PersonEdit_dlg {
        gint rowIndAttrib;
        gboolean editNew;
        gboolean read_only;
+       gboolean ldap;
 } personeditdlg;
 
 /* transient data */
@@ -471,7 +472,7 @@ static void edit_person_load_attrib( ItemPerson *person ) {
 
 static void edit_person_attrib_list_selected( GtkCList *clist, gint row, gint column, GdkEvent *event, gpointer data ) {
        UserAttribute *attrib = gtk_clist_get_row_data( clist, row );
-       if( attrib && !personeditdlg.read_only) {
+       if( attrib && !personeditdlg.read_only && !personeditdlg.ldap ) {
                gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atname), attrib->name );
                gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atvalue), attrib->value );
                gtk_widget_set_sensitive(personeditdlg.attrib_del, TRUE);
@@ -500,7 +501,7 @@ static void edit_person_attrib_delete( gpointer data ) {
                personeditdlg.rowIndAttrib = -1 + row;
        } 
        
-       if (!personeditdlg.read_only)
+       if (!personeditdlg.read_only && !personeditdlg.ldap)
                gtk_widget_set_sensitive(personeditdlg.attrib_del, gtk_clist_get_row_data(clist, 0) != NULL);
        
        edit_person_status_show( NULL );
@@ -986,7 +987,7 @@ static void edit_person_entry_att_changed (GtkWidget *entry, gpointer data)
 {
        gboolean non_empty = gtk_clist_get_row_data(GTK_CLIST(personeditdlg.clist_attrib), 0) != NULL;
 
-       if (personeditdlg.read_only)
+       if (personeditdlg.read_only || personeditdlg.ldap)
                return;
 
        if (gtk_entry_get_text(GTK_ENTRY(personeditdlg.entry_atname)) == NULL
@@ -1201,20 +1202,20 @@ static void update_sensitivity(void)
        gtk_widget_set_sensitive(personeditdlg.entry_name,    !personeditdlg.read_only);
        gtk_widget_set_sensitive(personeditdlg.entry_first,   !personeditdlg.read_only);
        gtk_widget_set_sensitive(personeditdlg.entry_last,    !personeditdlg.read_only);
-       gtk_widget_set_sensitive(personeditdlg.entry_nick,    !personeditdlg.read_only);
+       gtk_widget_set_sensitive(personeditdlg.entry_nick,    !personeditdlg.read_only && !personeditdlg.ldap);
        gtk_widget_set_sensitive(personeditdlg.entry_email,   !personeditdlg.read_only);
-       gtk_widget_set_sensitive(personeditdlg.entry_alias,   !personeditdlg.read_only);
-       gtk_widget_set_sensitive(personeditdlg.entry_remarks, !personeditdlg.read_only);
+       gtk_widget_set_sensitive(personeditdlg.entry_alias,   !personeditdlg.read_only && !personeditdlg.ldap);
+       gtk_widget_set_sensitive(personeditdlg.entry_remarks, !personeditdlg.read_only && !personeditdlg.ldap);
        gtk_widget_set_sensitive(personeditdlg.email_up,      !personeditdlg.read_only);
        gtk_widget_set_sensitive(personeditdlg.email_down,    !personeditdlg.read_only);
        gtk_widget_set_sensitive(personeditdlg.email_del,     !personeditdlg.read_only);
        gtk_widget_set_sensitive(personeditdlg.email_mod,     !personeditdlg.read_only);
        gtk_widget_set_sensitive(personeditdlg.email_add,     !personeditdlg.read_only);
-       gtk_widget_set_sensitive(personeditdlg.entry_atname,  !personeditdlg.read_only);
-       gtk_widget_set_sensitive(personeditdlg.entry_atvalue, !personeditdlg.read_only);
-       gtk_widget_set_sensitive(personeditdlg.attrib_add,    !personeditdlg.read_only);
-       gtk_widget_set_sensitive(personeditdlg.attrib_del,    !personeditdlg.read_only);
-       gtk_widget_set_sensitive(personeditdlg.attrib_mod,    !personeditdlg.read_only);
+       gtk_widget_set_sensitive(personeditdlg.entry_atname,  !personeditdlg.read_only && !personeditdlg.ldap);
+       gtk_widget_set_sensitive(personeditdlg.entry_atvalue, !personeditdlg.read_only && !personeditdlg.ldap);
+       gtk_widget_set_sensitive(personeditdlg.attrib_add,    !personeditdlg.read_only && !personeditdlg.ldap);
+       gtk_widget_set_sensitive(personeditdlg.attrib_del,    !personeditdlg.read_only && !personeditdlg.ldap);
+       gtk_widget_set_sensitive(personeditdlg.attrib_mod,    !personeditdlg.read_only && !personeditdlg.ldap);
 }
 
 static void addressbook_edit_person_flush_transient( void )
@@ -1343,6 +1344,7 @@ ItemPerson *addressbook_edit_person( AddressBookFile *abf, ItemFolder *parent_fo
        current_person = person;
        current_parent_folder = parent_folder;
        edit_person_close_post_update_cb = post_update_cb;
+       personeditdlg.ldap = (abf->type == ADBOOKTYPE_LDAP)? TRUE : FALSE;
 
        if( !personeditdlg.container )
                addressbook_edit_person_create(parent_container, &cancelled);
index ea5dbd20c3612a4c3331aaee99ff982d9273082e..ed4e1aff1b93d4116b019087c8703623ed324c67 100644 (file)
@@ -52,6 +52,7 @@ LdapControl *ldapctl_create( void ) {
        ctl->attribCName = g_strdup( LDAPCTL_ATTR_COMMONNAME );
        ctl->attribFName = g_strdup( LDAPCTL_ATTR_GIVENNAME );
        ctl->attribLName = g_strdup( LDAPCTL_ATTR_SURNAME );
+       ctl->attribDName = g_strdup( LDAPCTL_ATTR_DISPLAYNAME );
        ctl->maxEntries = LDAPCTL_MAX_ENTRIES;
        ctl->timeOut = LDAPCTL_DFL_TIMEOUT;
        ctl->maxQueryAge = LDAPCTL_DFL_QUERY_AGE;
@@ -256,6 +257,7 @@ static void ldapctl_clear( LdapControl *ctl ) {
        g_free( ctl->attribCName );
        g_free( ctl->attribFName );
        g_free( ctl->attribLName );
+       g_free( ctl->attribDName );
 
        ldapctl_criteria_list_clear( ctl );
 
@@ -269,6 +271,7 @@ static void ldapctl_clear( LdapControl *ctl ) {
        ctl->attribCName = NULL;
        ctl->attribFName = NULL;
        ctl->attribLName = NULL;
+       ctl->attribDName = NULL;
        ctl->maxEntries = 0;
        ctl->timeOut = 0;
        ctl->maxQueryAge = 0;
@@ -316,6 +319,7 @@ void ldapctl_print( const LdapControl *ctl, FILE *stream ) {
        fprintf( stream, "attr comn: '%s'\n", ctl->attribCName );
        fprintf( stream, "attr frst: '%s'\n", ctl->attribFName );
        fprintf( stream, "attr last: '%s'\n", ctl->attribLName );
+       fprintf( stream, "attr disn: '%s'\n", ctl->attribDName );
        fprintf( stream, "max entry: %d\n",   ctl->maxEntries );
        fprintf( stream, "  timeout: %d\n",   ctl->timeOut );
        fprintf( stream, "  max age: %d\n",   ctl->maxQueryAge );
@@ -361,6 +365,7 @@ void ldapctl_copy( const LdapControl *ctlFrom, LdapControl *ctlTo ) {
        ctlTo->attribCName = g_strdup( ctlFrom->attribCName );
        ctlTo->attribFName = g_strdup( ctlFrom->attribFName );
        ctlTo->attribLName = g_strdup( ctlFrom->attribLName );
+       ctlTo->attribDName = g_strdup( ctlFrom->attribDName );
 
        /* Copy search criteria */
        node = ctlFrom->listCriteria;
index c7ca21d47a3bef68c93a864f7fcf53b49f5c415b..2f515b6f4f19118773885f0c027cfc0f4655d8f3 100644 (file)
@@ -45,8 +45,9 @@
 #define LDAPCTL_ATTR_GIVENNAME  "givenName"
 #define LDAPCTL_ATTR_SURNAME    "sn"
 #define LDAPCTL_ATTR_PHONE     "telephoneNumber"
+#define LDAPCTL_ATTR_DISPLAYNAME "displayName"
 
-#define LDAPCTL_DFL_ATTR_LIST   "mail, cn, givenName, sn, telephoneNumber"
+#define LDAPCTL_DFL_ATTR_LIST   "mail, cn, givenName, sn, displayName, telephoneNumber"
 
 /*
  * Search matching options.
@@ -75,6 +76,7 @@ struct _LdapControl {
        gchar     *attribCName;
        gchar     *attribFName;
        gchar     *attribLName;
+       gchar     *attribDName;
        GList     *listCriteria;
        pthread_mutex_t *mutexCtl;
 };
index 5c7f83759dd34ad428d49af9c133d2e78d32cb35..cfef3ece45a60976f5eb92409ad25f545892e466 100644 (file)
@@ -353,13 +353,14 @@ void ldapqry_free( LdapQuery *qry ) {
  */
 static void ldapqry_free_lists(
                GSList *listName, GSList *listAddr, GSList *listFirst,
-               GSList *listLast, GSList *other_attrs )
+               GSList *listLast, GSList *listDisplay, GSList *other_attrs )
 {
        GSList *cur = other_attrs;
        mgu_free_list( listName );
        mgu_free_list( listAddr );
        mgu_free_list( listFirst );
        mgu_free_list( listLast );
+       mgu_free_list( listDisplay );
        for(;cur; cur = cur->next)
                addritem_free_attribute((UserAttribute *)cur->data);
        g_slist_free(other_attrs);
@@ -434,7 +435,7 @@ static GSList *ldapqry_add_single_value( LDAP *ld, LDAPMessage *entry, char *att
 static GList *ldapqry_build_items_fl(
                AddressCache *cache, LdapQuery *qry, gchar *dn,
                GSList *listName, GSList *listAddr, GSList *listFirst,
-               GSList *listLast, GSList *attributes )
+               GSList *listLast, GSList *listDisplay, GSList *attributes )
 {
        GSList *nodeAddress, *cur;
        gchar *firstName = NULL, *lastName = NULL, *fullName = NULL;
@@ -448,6 +449,11 @@ static GList *ldapqry_build_items_fl(
        if( folder == NULL ) return listReturn;
        if( listAddr == NULL ) return listReturn;
 
+       if ( listDisplay ) {
+               allocated = FALSE;
+               fullName = listDisplay->data;
+       }
+
        /* Find longest first name in list */
        firstName = mgu_slist_longest_entry( listFirst );
 
@@ -456,28 +462,30 @@ static GList *ldapqry_build_items_fl(
                lastName = listLast->data;
        }
 
-       /* Find longest common name */
-       allocated = FALSE;
-       fullName = mgu_slist_longest_entry( listName );
-       if( fullName == NULL ) {
-               /* Format a full name from first and last names */
-               if( firstName ) {
-                       if( lastName ) {
-                               fullName = g_strdup_printf( "%s %s", firstName, lastName );
+       if ( fullName == NULL ) {
+               /* Find longest common name */
+               allocated = FALSE;
+               fullName = mgu_slist_longest_entry( listName );
+               if( fullName == NULL ) {
+                       /* Format a full name from first and last names */
+                       if( firstName ) {
+                               if( lastName ) {
+                                       fullName = g_strdup_printf( "%s %s", firstName, lastName );
+                               }
+                               else {
+                                       fullName = g_strdup_printf( "%s", firstName );
+                               }
                        }
                        else {
-                               fullName = g_strdup_printf( "%s", firstName );
+                               if( lastName ) {
+                                       fullName = g_strdup_printf( "%s", lastName );
+                               }
                        }
-               }
-               else {
-                       if( lastName ) {
-                               fullName = g_strdup_printf( "%s", lastName );
+                       if( fullName ) {
+                               g_strchug( fullName ); g_strchomp( fullName );
+                               allocated = TRUE;
                        }
                }
-               if( fullName ) {
-                       g_strchug( fullName ); g_strchomp( fullName );
-                       allocated = TRUE;
-               }
        }
 
        /* Add person into folder */            
@@ -485,6 +493,7 @@ static GList *ldapqry_build_items_fl(
        addritem_person_set_common_name( person, fullName );
        addritem_person_set_first_name( person, firstName );
        addritem_person_set_last_name( person, lastName );
+       addritem_person_set_nick_name( person, fullName );
        addrcache_id_person( cache, person );
        addritem_person_set_external_id( person, dn );
        
@@ -505,6 +514,7 @@ static GList *ldapqry_build_items_fl(
                addrcache_id_email( cache, email );
                addrcache_person_add_email( cache, person, email );
                addritem_person_add_email( person, email );
+               /*addritem_print_item_email(email, stdout);*/
                listReturn = g_list_append( listReturn, email );
                nodeAddress = g_slist_next( nodeAddress );
        }
@@ -535,6 +545,7 @@ static GList *ldapqry_process_single_entry(
        BerElement *ber;
        GSList *listName = NULL, *listAddress = NULL;
        GSList *listFirst = NULL, *listLast = NULL;
+       GSList *listDisplay = NULL;
        GSList *other_attrs = NULL;
        GList *listReturn;
 
@@ -557,6 +568,8 @@ static GList *ldapqry_process_single_entry(
                }
                else if( strcasecmp( attribute, ctl->attribLName ) == 0 ) {
                        listLast = ldapqry_add_single_value( ld, e, attribute );
+               } else if( strcasecmp( attribute, ctl->attribDName ) == 0 ) {
+                       listDisplay = ldapqry_add_single_value( ld, e, attribute );
                } else {
                        GSList *attlist = ldapqry_add_single_value( ld, e, attribute );
                        UserAttribute *attrib = addritem_create_attribute();
@@ -574,11 +587,11 @@ static GList *ldapqry_process_single_entry(
 
        /* Format and add items to cache */
        listReturn = ldapqry_build_items_fl(
-               cache, qry, dnEntry, listName, listAddress, listFirst, listLast, other_attrs );
+               cache, qry, dnEntry, listName, listAddress, listFirst, listLast, listDisplay, other_attrs );
 
        /* Free up */
-       ldapqry_free_lists( listName, listAddress, listFirst, listLast, other_attrs );
-       listName = listAddress = listFirst = listLast = other_attrs = NULL;
+       ldapqry_free_lists( listName, listAddress, listFirst, listLast, listDisplay, other_attrs );
+       listName = listAddress = listFirst = listLast = listDisplay = other_attrs = NULL;
 
        if( ber != NULL ) {
                ber_free( ber, 0 );
@@ -845,6 +858,11 @@ static gint ldapqry_search_retrieve( LdapQuery *qry ) {
                        qry->callBackEntry( qry, ADDRQUERY_ID(qry), listEMail, qry->data );
                }
                else {
+                       /*GList *node = listEMail;
+                       while (node) {
+                               addritem_print_item_email(node->data, stdout);
+                               node = g_list_next(node);
+                       }*/
                        g_list_free( listEMail );
                }
                pthread_mutex_unlock( qry->mutexEntry );
index 2fb27aac9a657c347827e107ace1b317d21b6c36..1c932d50036a0057f6a4c3ba9bd45c0bf7b59bb6 100644 (file)
@@ -39,6 +39,7 @@
 #include "ldapctrl.h"
 #include "ldapquery.h"
 #include "ldapserver.h"
+#include "ldaputil.h"
 #include "utils.h"
 #include "adbookbase.h"
 
@@ -695,6 +696,20 @@ LdapQuery *ldapsvr_new_explicit_search(
        return qry;
 }
 
+gint ldapsvr_read_data( LdapServer *server )
+{
+       g_return_val_if_fail( server != NULL, -1 );
+
+       //printf( "...addrbook_read_data :%s:\n", addrcache_get_name( server->addressCache ) );
+       
+       addrcache_clear(server->addressCache);
+       server->addressCache->modified = FALSE;
+       server->addressCache->accessFlag = FALSE;
+       server->addressCache->dataRead = TRUE;
+       addrcache_set_dirty(server->addressCache, FALSE);
+       return 0;
+}
+
 #endif /* USE_LDAP */
 
 /*
index 93ff5dc848b603a4c0897c5afab9cd618d05d7b5..ac5b1fc582a818208ea1064b673d0586c6d34396 100644 (file)
 #define LDAPRC_NOENTRIES  -7
 #define LDAPRC_STOP_FLAG  -8
 #define LDAPRC_TLS        -9
+#define LDAPRC_NODN              -10
+#define LDAPRC_NAMING_VIOLATION  -11
+#define LDAPRC_ALREADY_EXIST -12
+#define LDAPRC_STRONG_AUTH -13
 
 typedef struct _LdapServer LdapServer;
 struct _LdapServer {
@@ -72,6 +76,7 @@ void ldapsvr_set_modified     ( LdapServer *server, const gboolean value );
 gboolean ldapsvr_get_read_flag ( LdapServer *server );
 gboolean ldapsvr_get_search_flag( LdapServer *server );
 void ldapsvr_set_search_flag   ( LdapServer *server, const gboolean value );
+gint ldapsvr_read_data ( LdapServer *server );
 
 void ldapsvr_print_data                ( LdapServer *server, FILE *stream );
 void ldapsvr_cancel_read       ( LdapServer *server );
diff --git a/src/ldapupdate.c b/src/ldapupdate.c
new file mode 100644 (file)
index 0000000..e6f7269
--- /dev/null
@@ -0,0 +1,961 @@
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2003-2007 Michael Rasmussen and the Claws Mail team
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * Functions necessary to access LDAP servers.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#ifdef USE_LDAP
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <sys/time.h>
+#include <string.h>
+#include <ldap.h>
+#include <lber.h>
+
+#include "ldapupdate.h"
+#include "mgutils.h"
+#include "addritem.h"
+#include "addrcache.h"
+#include "ldapctrl.h"
+#include "ldapquery.h"
+#include "ldapserver.h"
+#include "ldaputil.h"
+#include "utils.h"
+#include "adbookbase.h"
+
+/**
+ * Structure to hold user defined attributes
+ * from contacts
+ */
+typedef struct _AttrKeyValue AttrKeyValue;
+struct _AttrKeyValue {
+       gchar *key;
+       gchar *value;
+};
+
+/**
+ * Structure to hold contact information.
+ * Each addressbook will have 0..N contacts.
+ */
+typedef struct _EmailKeyValue EmailKeyValue;
+struct _EmailKeyValue {
+       gchar *mail;
+       gchar *alias;
+       gchar *remarks;
+};
+
+/**
+ * Structure to hold information about RDN.
+ */
+typedef struct _Rdn Rdn;
+struct _Rdn {
+       gchar *attribute;
+       gchar *value;
+       gchar *new_dn;
+};
+
+/**
+ * Retrieve address group item for update.
+ * \param group  Group to print.
+ * \param array  GHashTAble of item_group, or <i>NULL</i> if none created.
+ */
+void ldapsvr_retrieve_item_group(ItemGroup *group, GHashTable *array) {
+       /* Not implemented in this release */
+       g_return_if_fail(group != NULL);
+}
+
+/**
+ * Create an initial EmailKeyValue structure
+ * \return empty structure
+ */
+EmailKeyValue *emailkeyvalue_create() {
+       EmailKeyValue *buf;
+
+       buf = g_new0(EmailKeyValue, 1);
+       buf->alias = NULL;
+       buf->mail = NULL;
+       buf->remarks = NULL;
+       return buf;
+}
+
+/**
+ * Create an initial AttrKeyValue structure
+ * \return empty structure
+ */
+AttrKeyValue *attrkeyvalue_create() {
+       AttrKeyValue *buf;
+
+       buf = g_new0(AttrKeyValue, 1);
+       buf->key = NULL;
+       buf->value = NULL;
+       return buf;
+}
+
+/**
+ * Retrieve E-Mail address object for update.
+ * \param item   ItemEmail to update.
+ * \return object, or <i>NULL</i> if none created.
+ */
+EmailKeyValue *ldapsvr_retrieve_item_email(ItemEMail *item) {
+       EmailKeyValue *newItem;
+       g_return_val_if_fail(item != NULL, NULL);
+       newItem = emailkeyvalue_create();               
+       newItem->alias = g_strdup(ADDRITEM_NAME(item));
+       newItem->mail = g_strdup(item->address);
+       newItem->remarks = g_strdup(item->remarks);
+       return newItem;
+}
+
+/**
+ * Retrieve user attribute object for update.
+ * \param item   UserAttribute to update.
+ * \return object, or <i>NULL</i> if none created.
+ */
+AttrKeyValue *ldapsvr_retrieve_attribute(UserAttribute *item) {
+       AttrKeyValue *newItem;
+       g_return_val_if_fail(item != NULL, NULL);
+       newItem = attrkeyvalue_create();
+       newItem->key = g_strdup(item->name);
+       newItem->value = g_strdup(item->value);
+       return newItem;
+}
+
+/**
+ * Retrieve person object for update.
+ * \param person ItemPerson to update.
+ * \param array GHashTable with user input.
+ * \return false if update is not needed, or true if update is needed.
+ */
+gboolean ldapsvr_retrieve_item_person(ItemPerson *person, GHashTable *array) {
+       GList *node, *attr;
+
+       g_return_val_if_fail(person != NULL, FALSE);
+       switch (person->status) {
+               case NONE: return FALSE;
+               case ADD_ENTRY: g_hash_table_insert(array, "status", "new"); break;
+               case UPDATE_ENTRY: g_hash_table_insert(array, "status", "update"); break;
+               case DELETE_ENTRY: g_hash_table_insert(array, "status", "delete"); break;
+               default: g_critical(_("ldapsvr_retrieve_item_person->Unknown status: %d"), person->status);
+       }
+       g_hash_table_insert(array, "uid", ADDRITEM_ID(person));
+       g_hash_table_insert(array, "cn", ADDRITEM_NAME(person));
+       g_hash_table_insert(array, "givenName", person->firstName);
+       g_hash_table_insert(array, "sn", person->lastName);
+       g_hash_table_insert(array, "nickName", person->nickName);
+       g_hash_table_insert(array, "dn", person->externalID);
+       node = person->listEMail;
+       attr = NULL;
+       while (node) {
+               EmailKeyValue *newEmail = ldapsvr_retrieve_item_email(node->data);
+               if (newEmail)
+                       attr = g_list_append(attr, newEmail);
+               node = g_list_next(node);
+       }
+       g_hash_table_insert(array, "mail", attr);
+/* Not implemented in this release.
+       node = person->listAttrib;
+       attr = NULL;
+       while (node) {
+               AttrKeyValue *newAttr = ldapsvr_retrieve_attribute(node->data)
+               if (newAttr)
+                       attr = g_list_append(attr, newAttr);
+               node = g_list_next(node);
+       }
+       g_hash_table_insert(array, "attribute", attr);
+*/
+       return TRUE;
+}
+
+/**
+ * Print contents of contacts hashtable for debug.
+ * This function must be called with g_hash_table_foreach.
+ * \param key Key to process.
+ * \param data Data to process.
+ * \param fd Output stream.
+ */
+void ldapsvr_print_contacts_hashtable(gpointer key, gpointer data, gpointer fd) {
+       gchar *keyName = (gchar *) key;
+       GList *node;
+
+       if (g_ascii_strcasecmp("mail", keyName) == 0) {
+               node = (GList *) data;
+               while (node) {
+                       EmailKeyValue *item = node->data;
+                       if (debug_get_mode()) {
+                               debug_print("\t\talias = %s\n", item->alias);
+                               debug_print("\t\tmail = %s\n", item->mail);
+                               debug_print("\t\tremarks = %s\n", item->remarks);
+                       }
+                       else if (fd) {
+                               FILE *stream = (FILE *) fd;
+                               fprintf(stream, "\t\talias = %s\n", item->alias);
+                               fprintf(stream, "\t\tmail = %s\n", item->mail);
+                               fprintf(stream, "\t\tremarks = %s\n", item->remarks);
+                       }
+                       node = g_list_next(node);
+               }
+       }
+       else if (g_ascii_strcasecmp("attribute", keyName) == 0) {
+               node = (GList *) data;
+               while (node) {
+                       AttrKeyValue *item = node->data;
+                       if (debug_get_mode()) {
+                               debug_print("\t\t%s = %s\n", item->key, item->value);
+                       }
+                       else if (fd) {
+                               FILE *stream = (FILE *) fd;
+                               fprintf(stream, "\t\t%s = %s\n", item->key, item->value);
+                       }
+                       node = g_list_next(node);
+               }
+       }
+       else {
+               if (debug_get_mode())
+                       debug_print("\t\t%s = %s\n", keyName, (gchar *) data);
+               else if (fd) {
+                       FILE *stream = (FILE *) fd;
+                       fprintf(stream, "\t\t%s = %s\n", keyName, (gchar *) data);
+               }
+       }
+}
+
+/**
+ * Free list of changed contacts
+ *
+ * \param list List of GHashTable
+ */
+void ldapsvr_free_hashtable(GList *list) {
+       while (list) {
+               g_hash_table_destroy(list->data);
+               list = g_list_next(list);
+       }
+       g_list_free(list);
+}
+
+/**
+ * Get person object from cache
+ *
+ * \param server Resource to LDAP
+ * \param uid PersonID in cache
+ * \return person object, or <i>NULL</i> if fail
+ */
+ItemPerson *ldapsvr_get_contact(LdapServer *server, gchar *uid) {
+       AddrItemObject *aio;
+       g_return_val_if_fail(server != NULL || uid != NULL, NULL);
+       aio = addrcache_get_object(server->addressCache, uid);
+       if (aio) {
+               if(aio->type == ITEMTYPE_PERSON) {
+                       return (ItemPerson *) aio;
+               }
+       }
+       return NULL;
+}
+
+/**
+ * Connect to LDAP server.
+ * \param  ctl Control object to process.
+ * \return LDAP Resource to LDAP.
+ */
+LDAP *ldapsvr_connect(LdapControl *ctl) {
+       LDAP *ld = NULL;
+       gint rc;
+       gint version;
+       gchar *uri = NULL;
+
+       g_return_val_if_fail(ctl != NULL, NULL);
+
+       uri = g_strdup_printf("ldap%s://%s:%d",
+                               ctl->enableSSL?"s":"",
+                               ctl->hostName, ctl->port);
+       ldap_initialize(&ld, uri);
+       g_free(uri);
+
+       if (ld == NULL)
+               return NULL;
+
+       debug_print("connected to LDAP host %s on port %d\n", ctl->hostName, ctl->port);
+
+#ifdef USE_LDAP_TLS
+       /* Handle TLS */
+       version = LDAP_VERSION3;
+       rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version);
+       if (rc == LDAP_OPT_SUCCESS) {
+               ctl->version = LDAP_VERSION3;
+       }
+
+       if (ctl->version == LDAP_VERSION3) {
+               if (ctl->enableTLS && !ctl->enableSSL) {
+                       rc = ldap_start_tls_s(ld, NULL, NULL);
+                       
+                       if (rc != LDAP_SUCCESS) {
+                               fprintf(stderr, "LDAP Error(tls): ldap_simple_bind_s: %s\n",
+                                       ldap_err2string(rc));
+                               return NULL;
+                       }
+               }
+       }
+#endif
+
+       /* Bind to the server, if required */
+       if (ctl->bindDN) {
+               if (* ctl->bindDN != '\0') {
+                       rc = claws_ldap_simple_bind_s(ld, ctl->bindDN, ctl->bindPass);
+                       if (rc != LDAP_SUCCESS) {
+                               fprintf(stderr, "bindDN: %s, bindPass: %s\n", ctl->bindDN, ctl->bindPass);
+                               fprintf(stderr, "LDAP Error(bind): ldap_simple_bind_s: %s\n",
+                                       ldap_err2string(rc));
+                               return NULL;
+                       }
+               }
+       }
+       return ld;
+}
+
+/**
+ * Disconnect to LDAP server.
+ * \param ld Resource to LDAP.
+ */
+void ldapsvr_disconnect(LDAP *ld) {
+       /* Disconnect */
+       g_return_if_fail(ld != NULL);
+       ldap_unbind_ext(ld, NULL, NULL);
+}
+
+/**
+ * Create an initial Rdn structure
+ *
+ * \return empty structure
+ */
+Rdn *rdn_create() {
+       Rdn *buf;
+
+       buf = g_new0(Rdn, 1);
+       buf->attribute = NULL;
+       buf->value = NULL;
+       buf->new_dn = NULL;
+       return buf;
+}
+
+/**
+ * update Rdn structure
+ *
+ * \param rdn Rdn structure to update
+ * \param head Uniq part of dn
+ * \param tail Common part of dn
+ */
+void update_rdn(Rdn *rdn, gchar *head, gchar *tail) {
+       rdn->value = g_strdup(head);
+       rdn->new_dn = g_strdup_printf("mail=%s%s", head, tail);
+}
+
+/**
+ * Deside if dn needs to be changed
+ *
+ * \param hash GHashTable with user input.
+ * \param dn dn for current object
+ * \return Rdn structure
+ */
+Rdn *ldapsvr_modify_dn(GHashTable *hash, gchar *dn) {
+       Rdn *rdn;
+       gchar *pos, *compare;
+       g_return_val_if_fail(hash != NULL || dn != NULL, NULL);
+       
+       pos = g_strstr_len(dn, strlen(dn), "=");
+       compare = g_strndup(dn, pos - dn);
+
+       if (!pos)
+               return NULL;
+       pos++;
+       gchar *rest = g_strstr_len(pos, strlen(pos), ",");
+       gchar *val = g_strndup(pos, rest - pos);
+       if (val == NULL) {
+               if (compare)
+                       g_free(compare);
+               return NULL;
+       }
+       rdn = rdn_create();
+       rdn->value = g_strdup(val);
+       rdn->attribute = g_strdup(compare);
+       g_free(val);
+       if (strcmp("mail", rdn->attribute) == 0) {
+               GList *list = g_hash_table_lookup(hash, rdn->attribute);
+               while (list) {
+                       EmailKeyValue *item = list->data;
+                       compare = g_strdup((gchar *) item->mail);
+                       if (strcmp(compare, rdn->value) == 0) {
+                               update_rdn(rdn, compare, rest);
+                               g_free(compare);
+                               return rdn;
+                       }
+                       list = g_list_next(list);
+               }
+               /* if compare and rdn->attribute are equal then last email removed/empty  */
+               if (strcmp(compare, rdn->attribute) != 0) {
+                       /* RDN changed. Find new */
+                       update_rdn(rdn, compare, rest);
+                       g_free(compare);
+                       return rdn;
+               }
+               else {
+                       /* We cannot remove dn */
+                       g_free(compare);
+                       return NULL;
+               }
+       }
+       else {
+               compare = g_hash_table_lookup(hash, rdn->attribute);
+               /* if compare and rdn->attribute are equal then dn removed/empty */
+               if (strcmp(compare, rdn->attribute) != 0) {
+                       update_rdn(rdn, compare, rest);
+                       return rdn;
+               }
+               else {
+                       /* We cannot remove dn */
+                       return NULL;
+               }
+       }
+       return NULL;
+}
+
+/**
+ * This macro is borrowed from the Balsa project
+ * Creates a LDAPMod structure
+ *
+ * \param mods Empty LDAPMod structure
+ * \param modarr Array with values to insert
+ * \param op Operation to perform on LDAP
+ * \param attr Attribute to insert
+ * \param strv Empty array which is NULL terminated
+ * \param val Value for attribute
+ */
+#define SETMOD(mods,modarr,op,attr,strv,val) \
+   do { (mods) = &(modarr); (modarr).mod_type=attr; (modarr).mod_op=op;\
+        (strv)[0]=(val); (modarr).mod_values=strv; \
+      } while(0)
+
+/**
+ * Creates a LDAPMod structure
+ *
+ * \param mods Empty LDAPMod structure
+ * \param modarr Array with values to insert
+ * \param op Operation to perform on LDAP
+ * \param attr Attribute to insert
+ * \param strv Array with values to insert. Must be NULL terminated
+ */
+#define SETMODS(mods,modarr,op,attr,strv) \
+   do { (mods) = &(modarr); (modarr).mod_type=attr; \
+               (modarr).mod_op=op; (modarr).mod_values=strv; \
+      } while(0)
+#define MODSIZE 10
+
+/**
+ * Clean up, close LDAP connection, and refresh cache
+ *
+ * \param ld Resource to LDAP
+ * \param server AddressBook resource
+ * \param contact GHashTable with current changed object
+ */
+void clean_up(LDAP *ld, LdapServer *server, GHashTable *contact) {
+       ItemPerson *person = 
+               ldapsvr_get_contact(server, g_hash_table_lookup(contact , "uid"));
+       if (person) {
+               gchar *displayName;
+               person->status = NONE;
+               displayName = g_hash_table_lookup(contact, "displayName");
+               if (displayName)
+                       person->nickName = g_strdup(displayName);
+       }
+       if (ld)
+               ldapsvr_disconnect(ld);
+       ldapsvr_force_refresh(server);
+/*     ldapsvr_free_all_query(server);*/
+}
+
+/**
+ * Get cn attribute from dn
+ *
+ * \param dn Distinguesh Name for current object
+ * \return AttrKeyValue, or <i>NULL</i> if none created
+ */
+AttrKeyValue *get_cn(gchar *dn) {
+       AttrKeyValue *cn;
+       gchar *start;
+       gchar *end;
+       gchar *item;
+       gchar **key_value;
+       g_return_val_if_fail(dn != NULL, NULL);
+       
+       cn = attrkeyvalue_create();
+       start = g_strstr_len(dn, strlen(dn), "cn");
+       if (start == NULL)
+               return NULL;
+       end = g_strstr_len(start, strlen(start), ",");
+       item = g_strndup(start, end - start);
+       if (item == NULL)
+               return NULL;
+       key_value = g_strsplit(item, "=", 2);
+       cn->key = g_strdup(key_value[0]);
+       cn->value = g_strdup(key_value[1]);
+       g_strfreev(key_value);
+       g_free(item);
+       return cn;
+}
+
+/**
+ * Get ou or o attribute from dn
+ *
+ * \param dn Distinguesh Name for current object
+ * \return AttrKeyValue, or <i>NULL</i> if none created
+ */
+AttrKeyValue *get_ou(gchar *dn) {
+       AttrKeyValue *ou;
+       gchar *start;
+       gchar *end;
+       gchar *item;
+       gchar **key_value;
+       
+       g_return_val_if_fail(dn != NULL, NULL);
+       ou = attrkeyvalue_create();
+       start = g_strstr_len(dn, strlen(dn), ",o=");
+       if (start == NULL)
+               start = g_strstr_len(dn, strlen(dn), ",ou=");
+       if (start == NULL)
+               return NULL;
+       start++;
+       end = g_strstr_len(start, strlen(start), ",");
+       item = g_strndup(start, end - start);
+       if (item == NULL)
+               return NULL;
+       key_value = g_strsplit(item, "=", 2);
+       ou->key = g_strdup(key_value[0]);
+       ou->value = g_strdup(key_value[1]);
+       g_strfreev(key_value);
+       g_free(item);
+       return ou;
+}
+
+/**
+ * Print the contents of a LDAPMod structure for debuging purposes
+ *
+ * \param mods LDAPMod structure
+ */
+void ldapsvr_print_ldapmod(LDAPMod *mods[]) {
+       gchar *mod_op;
+       int i;
+
+       fprintf( stderr, "Type\n");
+       for (i = 0; NULL != mods[i]; i++) {
+               LDAPMod *mod = (LDAPMod *) mods[i];
+               gchar **vals;
+               switch (mod->mod_op) {
+                       case LDAP_MOD_ADD: mod_op = g_strdup("ADD"); break;
+                       case LDAP_MOD_REPLACE: mod_op = g_strdup("MODIFY"); break;
+                       case LDAP_MOD_DELETE: mod_op = g_strdup("DELETE"); break;
+                       default: mod_op = g_strdup("UNKNOWN");
+               }
+               fprintf( stderr, "Operation: %s\tType:%s\nValues:\n", mod_op, mod->mod_type);
+               vals = mod->mod_vals.modv_strvals;
+               while (*vals) {
+                       fprintf( stderr, "\t%s\n", *vals++);
+               }
+       }
+}
+
+/**
+ * Add new contact to LDAP
+ *
+ * \param server AddressBook resource
+ * \param contact GHashTable with object to add
+ */
+void ldapsvr_add_contact(LdapServer *server, GHashTable *contact) {
+       gchar *email = NULL, *param = NULL;
+       LDAP *ld = NULL;
+       LDAPMod *mods[MODSIZE];
+       LDAPMod modarr[7];
+       gint cnt = 0;
+       char *cn[] = {NULL, NULL};
+       char *displayName[] = {NULL, NULL};
+       char *givenName[] = {NULL, NULL};
+       char **mail = NULL;
+       char *sn[] = {NULL, NULL};
+       char *org[] = {NULL, NULL};
+       char *obj[] = {/*"top",*/ "person", "organizationalPerson", "inetOrgPerson", NULL}; 
+       int rc=0;
+       GList *node;
+       AttrKeyValue *ou, *commonName;
+       ItemPerson *person;
+       gchar *base_dn;
+       GList *mailList;
+
+       g_return_if_fail(server != NULL || contact != NULL);
+       node = g_hash_table_lookup(contact , "mail");
+       if (node) {
+               EmailKeyValue *newEmail = node->data;
+               email = g_strdup(newEmail->mail);
+       }
+       if (email == NULL) {
+               server->retVal = LDAPRC_NODN;
+               return;
+       }
+       base_dn = g_strdup_printf("mail=%s,%s", email, server->control->baseDN);
+       g_free(email);
+       person = 
+               ldapsvr_get_contact(server, g_hash_table_lookup(contact , "uid"));
+       person->externalID = g_strdup(base_dn);
+       debug_print("dn: %s\n", base_dn);
+       ld = ldapsvr_connect(server->control);
+       if (ld == NULL) {
+               clean_up(ld, server, contact);
+               debug_print("no ldap found\n");
+               return;
+       }
+       SETMODS(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "objectClass", obj);
+       cnt++;
+       ou = get_ou(base_dn);
+       if (ou != NULL) {
+               SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, ou->key, org, ou->value);
+               cnt++;
+       }
+       
+       commonName = get_cn(base_dn);
+       if (commonName == NULL) {
+               param = g_hash_table_lookup(contact , "cn");
+               if (param) {
+                       SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "cn", cn, param);
+               }
+               else {
+                       clean_up(ld, server, contact);
+                       debug_print("no CN found\n");
+                       return;
+               }
+       }
+       else {
+               SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, commonName->key, cn, commonName->value);
+               cnt++;
+               param = g_hash_table_lookup(contact , "cn");
+               SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "displayName", displayName, param);
+               g_hash_table_insert(contact, "displayName", param);
+       }
+       cnt++;
+       param = g_hash_table_lookup(contact , "givenName");
+       if (param) {
+               SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "givenName", givenName, param);
+               cnt++;
+       }
+       mailList = g_hash_table_lookup(contact , "mail");
+       if (mailList) {
+               mail = g_malloc(sizeof(*mail));
+               char **tmp = g_malloc(sizeof(*tmp));
+               mail = tmp;
+               while (mailList) {
+                       EmailKeyValue *item = mailList->data;
+                       *tmp++ = g_strdup((gchar *) item->mail);
+                       mailList = g_list_next(mailList);
+               }
+               *tmp = NULL;
+               SETMODS(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "mail", mail);
+               cnt++;
+       }
+       param = g_hash_table_lookup(contact, "sn");
+       if (param == NULL)
+               param = g_strdup(N_("Some SN"));
+       SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "sn", sn, param);
+       cnt++;
+       mods[cnt] = NULL;
+       if (debug_get_mode()) {
+               ldapsvr_print_ldapmod(mods);
+       }
+       server->retVal = LDAPRC_SUCCESS;
+       rc = ldap_add_ext_s(ld, base_dn, mods, NULL, NULL);
+       if (rc) {
+               switch (rc) {
+                       case LDAP_ALREADY_EXISTS: 
+                               server->retVal = LDAPRC_ALREADY_EXIST;
+                               break;
+                       default:
+                               fprintf(stderr, "ldap_modify for dn=%s\" failed[0x%x]: %s\n",base_dn, rc, ldap_err2string(rc));
+                               if (rc == 0x8)
+                                       server->retVal = LDAPRC_STRONG_AUTH;
+                               else
+                                       server->retVal = LDAPRC_NAMING_VIOLATION;
+               }
+       }
+       g_free(base_dn);
+       clean_up(ld, server, contact);
+}
+
+/**
+ * Update contact to LDAP
+ *
+ * \param server AddressBook resource
+ * \param contact GHashTable with object to update
+ */
+void ldapsvr_update_contact(LdapServer *server, GHashTable *contact) {
+       LDAP *ld = NULL;
+       LDAPMod *mods[MODSIZE];
+       LDAPMod modarr[4];
+       gint cnt = 0;
+       gchar *param, *dn;
+       Rdn *NoRemove = NULL;
+       char *cn[] = {NULL, NULL};
+       char *givenName[] = {NULL, NULL};
+       char **mail = NULL;
+       char *sn[] = {NULL, NULL};
+       GList *mailList;
+
+       g_return_if_fail(server != NULL || contact != NULL);
+       ld = ldapsvr_connect(server->control);
+       if (ld == NULL) {
+               clean_up(ld, server, contact);
+               return;
+       }
+       dn = g_hash_table_lookup(contact, "dn");
+       if (dn == NULL) {
+               clean_up(ld, server, contact);
+               return;
+       }
+       NoRemove = ldapsvr_modify_dn(contact, dn);
+       if (NoRemove) {
+               /* We are trying to change RDN */
+               gchar *newRdn = g_strdup_printf("%s=%s", NoRemove->attribute, NoRemove->value);
+               int rc = ldap_modrdn2_s(ld, dn, newRdn, 1);
+               if(rc != LDAP_SUCCESS) {
+                       if (rc ==  LDAP_ALREADY_EXISTS) {
+                               /* We are messing with a contact with more than one listed email
+                                * address and the email we are changing is not the one used for dn
+                                */
+                               /* It needs to be able to handle renaming errors to an already defined
+                                * dn. For now we just refuse the update. It will be caught later on as
+                                * a LDAPRC_NAMING_VIOLATION error.
+                                */
+                       }
+                       else {
+                               fprintf(stderr, "Current dn: %s\n", dn);
+                               fprintf(stderr, "new dn: %s\n", newRdn);
+                               fprintf(stderr, "LDAP Error(ldap_modrdn2_s) failed[0x%x]: %s\n", rc, ldap_err2string(rc));
+                               g_free(newRdn);
+                               return;
+                       }
+               }
+               else {
+                       g_free(newRdn);
+                       dn = g_strdup(NoRemove->new_dn);
+               }
+       }
+       else {
+               server->retVal = LDAPRC_NODN;
+               clean_up(ld, server, contact);
+               return;
+       }
+       param = g_hash_table_lookup(contact , "cn");
+       if (param && (strcmp(param, NoRemove->value) != 0 && strcmp("cn", NoRemove->attribute) != 0)) {
+               SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_REPLACE, "displayName", cn, param);
+               cnt++;
+               g_hash_table_insert(contact, "displayName", param);
+       }
+       param = g_hash_table_lookup(contact , "givenName");
+       if (param && (strcmp(param, NoRemove->value) != 0 && strcmp("givenName", NoRemove->attribute) != 0)) {
+               SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_REPLACE, "givenName", givenName, param);
+               cnt++;
+       }
+       mailList = g_hash_table_lookup(contact , "mail");
+       if (mailList) {
+               if (!(strcmp("mail", NoRemove->attribute) == 0 && g_list_length(mailList) == 1)) {
+                       mail = g_malloc(sizeof(*mail));
+                       char **tmp = g_malloc(sizeof(*tmp));
+                       mail = tmp;
+                       while (mailList) {
+                               EmailKeyValue *item = mailList->data;
+                               *tmp++ = g_strdup((gchar *) item->mail);
+                               mailList = g_list_next(mailList);
+                       }
+                       *tmp = NULL;
+                       SETMODS(mods[cnt], modarr[cnt], LDAP_MOD_REPLACE, "mail", mail);
+                       cnt++;
+               }
+       }
+       param = g_hash_table_lookup(contact , "sn");
+       if (param && (strcmp(param, NoRemove->value) != 0 && strcmp("sn", NoRemove->attribute) != 0)) {
+               SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_REPLACE, "sn", sn, param);
+               cnt++;
+       }
+       debug_print("newDN: %s\n", dn);
+       if (NoRemove)
+               g_free(NoRemove);
+       server->retVal = LDAPRC_SUCCESS;
+       if (cnt > 0) {
+               int rc;
+               mods[cnt] = NULL;
+               rc = ldap_modify_ext_s(ld, dn, mods, NULL, NULL);
+               if (rc) {
+                       fprintf(stderr, "ldap_modify for dn=%s\" failed[0x%x]: %s\n",
+                    dn, rc, ldap_err2string(rc));
+                       server->retVal = LDAPRC_NAMING_VIOLATION;
+               }
+               if (mail)
+                       g_free(mail);
+       }
+       clean_up(ld, server, contact);
+}
+
+/**
+ * Delete contact from LDAP
+ *
+ * \param server AddressBook resource
+ * \param contact GHashTable with object to delete
+ */
+void ldapsvr_delete_contact(LdapServer *server, GHashTable *contact) {
+       LDAP *ld = NULL;
+       gchar *dn;
+       int rc;
+
+       g_return_if_fail(server != NULL || contact != NULL);
+       ld = ldapsvr_connect(server->control);
+       if (ld == NULL) {
+               clean_up(ld, server, contact);
+               return;
+       }
+       dn = g_hash_table_lookup(contact, "dn");
+       if (dn == NULL) {
+               clean_up(ld, server, contact);
+               return;
+       }
+       rc = ldap_delete_ext_s(ld, dn, NULL, NULL);
+       if (rc) {
+               fprintf(stderr, "ldap_modify for dn=%s\" failed[0x%x]: %s\n",
+                               dn, rc, ldap_err2string(rc));
+               server->retVal = LDAPRC_NODN;
+       }
+       clean_up(ld, server, contact);
+}
+
+/**
+ * Update any changes to the server.
+ *
+ * \param server AddressBook resource.
+ * \param person ItemPerson holding user input.
+ */
+void ldapsvr_update_book(LdapServer *server, ItemPerson *item) {
+       GList *node = NULL;
+       GHashTable *contact = NULL;
+       GList *contacts = NULL, *head = NULL;
+
+       g_return_if_fail(server != NULL);
+       debug_print("updating ldap addressbook\n");
+
+       contact = g_hash_table_new(g_str_hash, g_str_equal);
+       if (item) {
+               gboolean result = ldapsvr_retrieve_item_person(item, contact);
+               debug_print("Found contact to update: %s\n", result? "Yes" : "No");
+               if (result) {
+                       if (debug_get_mode()) {
+                               addritem_print_item_person(item, stdout);
+                       }
+                       contacts = g_list_append(contacts, contact);
+               }
+       }
+       else {
+               ItemFolder *folder = server->addressCache->rootFolder;
+               node = folder->listFolder;
+               if (node)
+                       node = g_list_copy(node);
+               node = g_list_prepend(node, server->addressCache->rootFolder);
+               if (node) {
+                       while (node) {
+                               AddrItemObject *aio = node->data;
+                               if (aio) {
+                                       if (aio->type == ITEMTYPE_FOLDER) {
+                                               ItemFolder *folder = (ItemFolder *) aio;
+                                               GList *persons = folder->listPerson;
+                                               while (persons) {
+                                                       AddrItemObject *aio = persons->data;
+                                                       if (aio) {
+                                                               if (aio->type == ITEMTYPE_PERSON) {
+                                                                       ItemPerson *item = (ItemPerson *) aio;
+                                                                       gboolean result = ldapsvr_retrieve_item_person(item, contact);
+                                                                       debug_print("Found contact to update: %s\n", result? "Yes" : "No");
+                                                                       if (result) {
+                                                                               if (debug_get_mode()) {
+                                                                                       gchar *uid = g_hash_table_lookup(contact, "uid");
+                                                                                       item = ldapsvr_get_contact(server, uid);
+                                                                                       addritem_print_item_person(item, stdout);
+                                                                               }
+                                                                               contacts = g_list_append(contacts, contact);
+                                                                       }
+                                                               }
+                                                       }
+                                                       persons = g_list_next(persons);
+                                               }
+                                       }
+                               }
+                               else {
+                                       fprintf(stderr, "\t\tpid : ???\n");
+                               }
+                               node = g_list_next(node);
+                       }
+                       g_list_free(node);
+               }
+       }
+       head = contacts;
+       if (debug_get_mode()) {
+               if (contacts)
+                       debug_print("Contacts which must be updated in LDAP:\n");
+               while (contacts) {
+                       debug_print("\tContact:\n");
+                       g_hash_table_foreach(contacts->data, 
+                               ldapsvr_print_contacts_hashtable, stderr);
+                       contacts = g_list_next(contacts);
+               }
+       }
+       if (contacts == NULL)
+               contacts = head;
+       while (contacts) {
+               gchar *status;
+               contact = (GHashTable *) contacts->data;
+               status = (gchar *) g_hash_table_lookup(contact, "status");
+               if (status == NULL)
+                       status = g_strdup("NULL");
+               if (g_ascii_strcasecmp(status, "new") == 0) {
+                       ldapsvr_add_contact(server, contact);
+               }
+               else if (g_ascii_strcasecmp(status, "update") == 0) {
+                       ldapsvr_update_contact(server, contact);
+               }
+               else if (g_ascii_strcasecmp(status, "delete") == 0) {
+                       ldapsvr_delete_contact(server, contact);
+               }
+               else
+                       g_critical(_("ldapsvr_update_book->Unknown status: %s\n"), status);
+               contacts = g_list_next(contacts);
+       }
+       ldapsvr_free_hashtable(head);
+}
+
+#endif /* USE_LDAP */
+
+/*
+ * End of Source.
+ */
+
diff --git a/src/ldapupdate.h b/src/ldapupdate.h
new file mode 100644 (file)
index 0000000..8b895c3
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2003-2007 Michael Rasmussen and the Claws Mail team
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * Definitions necessary to update LDAP servers.
+ */
+
+#ifndef __LDAPUPDATE_H__
+#define __LDAPUPDATE_H__
+
+#ifdef USE_LDAP
+
+#include <glib.h>
+
+#include "ldapserver.h"
+
+/* Function proto types */
+void ldapsvr_update_book(LdapServer *server, ItemPerson *item);
+
+#endif /* USE_LDAP */
+
+#endif /* __LDAPUPDATE_H__ */
+