+2007-07-09 [colin] 2.10.0cvs12
+
+ * src/Makefile.am
+ * src/addritem.c
+ * src/addritem.h
+ * src/editaddress.c
+ * src/editaddress_other_attributes_ldap.c
+ * src/editaddress_other_attributes_ldap.h
+ * src/editldap.c
+ * src/ldapctrl.c
+ * src/ldapctrl.h
+ * src/ldapupdate.c
+ Add capability to edit all inetOrgPerson
+ attributes on LDAP. Patch by Michael
+ Rasmussen
+
2007-07-09 [colin] 2.10.0cvs11
* src/Makefile.am
( cvs diff -u -r 1.5.10.5 -r 1.5.10.6 COPYING; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 manual/claws-mail-manual.xml; cvs diff -u -r 1.1.2.13 -r 1.1.2.14 po/fi.po; ) > 2.10.0cvs9.patchset
( cvs diff -u -r 1.30.2.33 -r 1.30.2.34 src/prefs_toolbar.c; ) > 2.10.0cvs10.patchset
( cvs diff -u -r 1.155.2.66 -r 1.155.2.67 src/Makefile.am; cvs diff -u -r 1.5.2.19 -r 1.5.2.20 src/exporthtml.c; cvs diff -u -r 1.28.2.35 -r 1.28.2.36 src/mbox.c; cvs diff -u -r 1.16.2.51 -r 1.16.2.52 src/msgcache.c; cvs diff -u -r 1.1.2.44 -r 1.1.2.45 src/prefs_summaries.c; cvs diff -u -r 1.3.2.48 -r 1.3.2.49 src/prefs_themes.c; cvs diff -u -r 1.47.2.43 -r 1.47.2.44 src/procheader.c; cvs diff -u -r 1.24.2.14 -r 1.24.2.15 src/common/Makefile.am; cvs diff -u -r 1.6.2.11 -r 1.6.2.12 src/common/log.c; cvs diff -u -r 1.1.2.7 -r 1.1.2.8 src/common/timing.h; cvs diff -u -r 1.36.2.104 -r 1.36.2.105 src/common/utils.c; cvs diff -u -r 1.20.2.46 -r 1.20.2.47 src/common/utils.h; diff -u /dev/null src/common/w32_account.c; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/common/w32lib.h; cvs diff -u -r 1.20.2.14 -r 1.20.2.15 src/gtk/Makefile.am; cvs diff -u -r 1.2.2.18 -r 1.2.2.19 src/gtk/colorlabel.c; cvs diff -u -r 1.1.2.8 -r 1.1.2.9 src/plugins/pgpcore/Makefile.am; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/plugins/pgpcore/claws.def; cvs diff -u -r 1.1.2.26 -r 1.1.2.27 src/plugins/pgpcore/passphrase.c; cvs diff -u -r 1.1.2.11 -r 1.1.2.12 src/plugins/pgpcore/pgp_viewer.c; cvs diff -u -r 1.1.2.2 -r 1.1.2.3 src/plugins/pgpcore/plugin.def; cvs diff -u -r 1.1.2.45 -r 1.1.2.46 src/plugins/pgpcore/sgpgme.c; cvs diff -u -r 1.1.2.7 -r 1.1.2.8 src/plugins/pgpinline/Makefile.am; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/plugins/pgpinline/claws.def; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/plugins/pgpinline/mypgpcore.def; cvs diff -u -r 1.1.2.2 -r 1.1.2.3 src/plugins/pgpinline/plugin.def; cvs diff -u -r 1.1.2.9 -r 1.1.2.10 src/plugins/pgpmime/Makefile.am; cvs diff -u -r 1.1.2.2 -r 1.1.2.3 src/plugins/pgpmime/claws.def; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/plugins/pgpmime/mypgpcore.def; cvs diff -u -r 1.1.2.2 -r 1.1.2.3 src/plugins/pgpmime/plugin.def; ) > 2.10.0cvs11.patchset
+( cvs diff -u -r 1.155.2.67 -r 1.155.2.68 src/Makefile.am; cvs diff -u -r 1.13.2.11 -r 1.13.2.12 src/addritem.c; cvs diff -u -r 1.12.2.9 -r 1.12.2.10 src/addritem.h; cvs diff -u -r 1.14.2.24 -r 1.14.2.25 src/editaddress.c; diff -u /dev/null src/editaddress_other_attributes_ldap.c; diff -u /dev/null src/editaddress_other_attributes_ldap.h; cvs diff -u -r 1.8.2.21 -r 1.8.2.22 src/editldap.c; cvs diff -u -r 1.2.2.9 -r 1.2.2.10 src/ldapctrl.c; cvs diff -u -r 1.1.4.10 -r 1.1.4.11 src/ldapctrl.h; cvs diff -u -r 1.1.2.7 -r 1.1.2.8 src/ldapupdate.c; ) > 2.10.0cvs12.patchset
MICRO_VERSION=0
INTERFACE_AGE=0
BINARY_AGE=0
-EXTRA_VERSION=11
+EXTRA_VERSION=12
EXTRA_RELEASE=
EXTRA_GTK2_VERSION=
customheader.c \
displayheader.c \
editaddress.c \
+ editaddress_other_attributes_ldap.c \
editbook.c \
editgroup.c \
editjpilot.c \
customheader.h \
displayheader.h \
editaddress.h \
+ editaddress_other_attributes_ldap.h \
editbook.h \
editgroup.h \
editjpilot.h \
person->listAttrib = g_list_append( person->listAttrib, attrib );
}
+/**
+ * Remove user attribute from specified person.
+ * \param person Person.
+ * \param attrib Attribute to remove.
+ */
+void addritem_person_remove_attribute( ItemPerson *person, const gchar *attrib ) {
+ g_return_if_fail( person != NULL || attrib != NULL );
+ GList *attrib_list;
+
+ attrib_list = person->listAttrib;
+ while (attrib_list) {
+ UserAttribute *user_attrib = attrib_list->data;
+ if (strcmp(user_attrib->name, attrib) == 0) {
+ person->listAttrib = g_list_remove(person->listAttrib, (gconstpointer) user_attrib);
+ break;
+ }
+ attrib_list = g_list_next(attrib_list);
+ }
+}
+
+/**
+ * find out if a user attribute already exists in the specified person.
+ * \param person Person.
+ * \param attrib Attribute to remove.
+ * \return <i>TRUE</i> if attribute exists
+ */
+gboolean addritem_person_has_attribute( ItemPerson *person, const gchar *attrib ) {
+ g_return_val_if_fail( person != NULL || attrib != NULL, FALSE );
+ GList *attrib_list = NULL;
+
+ attrib_list = person->listAttrib;
+ while (attrib_list) {
+ UserAttribute *user_attrib = attrib_list->data;
+ if (strcmp(user_attrib->name, attrib) == 0) {
+ return TRUE;
+ }
+ attrib_list = g_list_next(attrib_list);
+ }
+ return FALSE;
+}
+
/**
* Create new address book group object.
* \return Initialized group object.
ItemEMail *addritem_person_remove_email ( ItemPerson *person, ItemEMail *email );
void addritem_person_add_attribute ( ItemPerson *person, UserAttribute *attrib );
+void addritem_person_remove_attribute ( ItemPerson *person, const gchar *attrib );
+gboolean addritem_person_has_attribute ( ItemPerson *person, const gchar *attrib );
ItemFolder *addritem_create_item_folder ( void );
ItemFolder *addritem_copy_item_folder ( ItemFolder *item );
#include "gtkutils.h"
#include "codeconv.h"
#include "editaddress.h"
-
+#include "editaddress_other_attributes_ldap.h"
#include "prefs_common.h"
-static struct _PersonEdit_dlg {
- GtkWidget *container;
- GtkWidget *notebook;
- GtkWidget *ok_btn;
- GtkWidget *cancel_btn;
- GtkWidget *statusbar; /* used when prefs_common.addressbook_use_editaddress_dialog is TRUE */
- GtkWidget *title; /* used when prefs_common.addressbook_use_editaddress_dialog is FALSE */
- gint status_cid;
-
- /* User data tab */
- GtkWidget *entry_name;
- GtkWidget *entry_first;
- GtkWidget *entry_last;
- GtkWidget *entry_nick;
-
- /* EMail data tab */
- GtkWidget *entry_email;
- GtkWidget *entry_alias;
- GtkWidget *entry_remarks;
- GtkWidget *clist_email;
- GtkWidget *email_up;
- GtkWidget *email_down;
- GtkWidget *email_del;
- GtkWidget *email_mod;
- GtkWidget *email_add;
-
- /* Attribute data tab */
- GtkWidget *entry_atname;
- GtkWidget *entry_atvalue;
- GtkWidget *clist_attrib;
- GtkWidget *attrib_add;
- GtkWidget *attrib_del;
- GtkWidget *attrib_mod;
-
- gint rowIndEMail;
- gint rowIndAttrib;
- gboolean editNew;
- gboolean read_only;
- gboolean ldap;
-} personeditdlg;
-
/* transient data */
+static struct _PersonEdit_dlg personeditdlg;
static AddressBookFile *current_abf = NULL;
static ItemPerson *current_person = NULL;
static ItemFolder *current_parent_folder = NULL;
}
static void edit_person_attrib_clear( gpointer data ) {
- gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atname), "" );
- gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atvalue), "" );
+ if (!personeditdlg.ldap) {
+ gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atname), "" );
+ gtk_entry_set_text( GTK_ENTRY(personeditdlg.entry_atvalue), "" );
+ }
}
static void edit_person_switch_page( GtkNotebook *notebook, GtkNotebookPage *page,
addressbook_edit_person_widgetset_create( parent, cancelled );
addressbook_edit_person_page_basic( PAGE_BASIC, _( "_User Data" ) );
addressbook_edit_person_page_email( PAGE_EMAIL, _( "_Email Addresses" ) );
- addressbook_edit_person_page_attrib( PAGE_ATTRIBUTES, _( "O_ther Attributes" ) );
+ if (personeditdlg.ldap)
+ addressbook_edit_person_page_attrib_ldap(&personeditdlg, PAGE_ATTRIBUTES, _("O_ther Attributes"));
+ else
+ addressbook_edit_person_page_attrib( PAGE_ATTRIBUTES, _( "O_ther Attributes" ) );
gtk_widget_show_all( personeditdlg.container );
}
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 && !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);
+ 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);
}
static void addressbook_edit_person_flush_transient( void )
gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_nick), person->nickName );
edit_person_load_email( person );
edit_person_load_attrib( person );
+ gtk_entry_set_text(GTK_ENTRY(personeditdlg.entry_atvalue), "");
}
else {
personeditdlg.editNew = TRUE;
--- /dev/null
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-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.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef USE_LDAP
+
+#include "defs.h"
+
+#include "mgutils.h"
+#include "addressbook.h"
+#include "addressitem.h"
+#include "addritem.h"
+#include "addrbook.h"
+#include "manage_window.h"
+#include "gtkutils.h"
+#include "codeconv.h"
+#include "editaddress.h"
+#include "editaddress_other_attributes_ldap.h"
+#include "prefs_common.h"
+
+#define ATTRIB_COL_NAME 0
+#define ATTRIB_COL_VALUE 1
+#define ATTRIB_N_COLS 2
+#define EMAIL_N_COLS 3
+#define ATTRIB_COL_WIDTH_NAME 120
+#define ATTRIB_COL_WIDTH_VALUE 180
+
+PersonEditDlg *personEditDlg;
+gboolean attrib_adding = FALSE, attrib_saving = FALSE;
+
+int get_attribute_index(const gchar *string_literal) {
+ int i = 0;
+ /*int count = sizeof(ATTRIBUTE) / sizeof(*ATTRIBUTE);*/
+ const gchar **attribute = ATTRIBUTE;
+
+ g_return_val_if_fail(string_literal != NULL, -1);
+ while (*attribute) {
+ debug_print("Comparing %s to %s\n", *attribute, string_literal);
+ if (strcmp(*attribute++, string_literal) == 0)
+ return i;
+ i++;
+ }
+ return -1;
+}
+
+static void edit_person_status_show(gchar *msg) {
+ if (personEditDlg->statusbar != NULL) {
+ gtk_statusbar_pop(GTK_STATUSBAR(personEditDlg->statusbar), personEditDlg->status_cid);
+ if(msg) {
+ gtk_statusbar_push(GTK_STATUSBAR(personEditDlg->statusbar), personEditDlg->status_cid, msg);
+ }
+ }
+}
+
+static void edit_person_attrib_clear(gpointer data) {
+ gtk_option_menu_set_history(GTK_OPTION_MENU(personEditDlg->entry_atname), 0);
+ gtk_entry_set_text(GTK_ENTRY(personEditDlg->entry_atvalue), "");
+}
+
+static gboolean list_find_attribute(const gchar *attr)
+{
+ GtkCList *clist = GTK_CLIST(personEditDlg->clist_attrib);
+ UserAttribute *attrib;
+ gint row = 0;
+ while((attrib = gtk_clist_get_row_data(clist, row))) {
+ if (!g_ascii_strcasecmp(attrib->name, attr)) {
+ gtk_clist_select_row(clist, row, 0);
+ return TRUE;
+ }
+ row++;
+ }
+ return FALSE;
+}
+
+/*
+* Comparison using cell contents (text in first column). Used for sort
+* address index widget.
+*/
+static gint edit_person_attrib_compare_func(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2) {
+ GtkCell *cell1 = ((GtkCListRow *)ptr1)->cell;
+ GtkCell *cell2 = ((GtkCListRow *)ptr2)->cell;
+ gchar *name1 = NULL, *name2 = NULL;
+
+ if (cell1) name1 = cell1->u.text;
+ if (cell2) name2 = cell2->u.text;
+ if (!name1) return (name2 != NULL);
+ if (!name2) return -1;
+ return g_utf8_collate(name1, name2);
+}
+
+static void edit_person_option_menu_changed(GtkOptionMenu *opt_menu, gpointer data) {
+ GtkCList *clist = GTK_CLIST(data);
+ gint row = personEditDlg->rowIndAttrib;
+ UserAttribute *attrib = gtk_clist_get_row_data(clist, row);
+ gint option = gtk_option_menu_get_history(opt_menu);
+
+ /* A corresponding attribute in contact does not match selected option */
+ if (strcmp(ATTRIBUTE[option], attrib->name) != 0) {
+ gtk_widget_set_sensitive(personEditDlg->attrib_add, TRUE);
+ gtk_widget_set_sensitive(personEditDlg->attrib_mod, TRUE);
+ gtk_widget_set_sensitive(personEditDlg->attrib_del, FALSE);
+ gtk_entry_set_text(GTK_ENTRY(personEditDlg->entry_atvalue), "");
+ gtk_widget_grab_focus(personEditDlg->entry_atvalue);
+ edit_person_status_show(NULL);
+ }
+}
+
+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) {
+ int index = get_attribute_index(attrib->name);
+ /*fprintf(stderr, "Row: %d -> %s = %s\n", index, attrib->name, attrib->value);*/
+ if (index == -1)
+ index = 0;
+ gtk_option_menu_set_history(GTK_OPTION_MENU(personEditDlg->entry_atname), index);
+ gtk_entry_set_text( GTK_ENTRY(personEditDlg->entry_atvalue), attrib->value );
+ gtk_widget_set_sensitive(personEditDlg->attrib_del, TRUE);
+ }
+ else {
+ /*fprintf(stderr, "Row: %d -> empty attribute\n", row);*/
+ gtk_entry_set_text( GTK_ENTRY(personEditDlg->entry_atvalue), "");
+ gtk_widget_set_sensitive(personEditDlg->attrib_del, FALSE);
+ }
+ personEditDlg->rowIndAttrib = row;
+ edit_person_status_show(NULL);
+}
+
+static void edit_person_attrib_delete(gpointer data) {
+ GtkCList *clist = GTK_CLIST(personEditDlg->clist_attrib);
+ gint row = personEditDlg->rowIndAttrib;
+ UserAttribute *attrib = gtk_clist_get_row_data(clist, row);
+ edit_person_attrib_clear(NULL);
+ if (attrib) {
+ /* Remove list entry */
+ gtk_clist_remove(clist, row);
+ addritem_free_attribute(attrib);
+ attrib = NULL;
+ }
+
+ /* Position hilite bar */
+ attrib = gtk_clist_get_row_data(clist, row);
+ if (!attrib) {
+ personEditDlg->rowIndAttrib = -1 + row;
+ }
+
+ if (!personEditDlg->read_only)
+ gtk_widget_set_sensitive(personEditDlg->attrib_del, gtk_clist_get_row_data(clist, 0) != NULL);
+
+ edit_person_status_show(NULL);
+}
+
+static UserAttribute *edit_person_attrib_edit(gboolean *error, UserAttribute *attrib) {
+ UserAttribute *retVal = NULL;
+ gchar *sName, *sValue, *sName_, *sValue_;
+ gint index;
+
+ *error = TRUE;
+ index = gtk_option_menu_get_history(GTK_OPTION_MENU(personEditDlg->entry_atname));
+ sName_ = (gchar *) ATTRIBUTE[index];
+ sValue_ = gtk_editable_get_chars(GTK_EDITABLE(personEditDlg->entry_atvalue), 0, -1);
+ sName = mgu_email_check_empty(sName_);
+ sValue = mgu_email_check_empty(sValue_);
+ g_free(sValue_);
+
+ if (sName && sValue) {
+ if (attrib == NULL) {
+ attrib = addritem_create_attribute();
+ }
+ addritem_attrib_set_name(attrib, sName);
+ addritem_attrib_set_value(attrib, sValue);
+ retVal = attrib;
+ *error = FALSE;
+ }
+ else {
+ edit_person_status_show(N_( "A Name and Value must be supplied." ));
+ gtk_widget_grab_focus(personEditDlg->entry_atvalue);
+ }
+
+ g_free(sName);
+ g_free(sValue);
+
+ return retVal;
+}
+
+static void edit_person_attrib_modify(gpointer data) {
+ gboolean errFlg = FALSE;
+ GtkCList *clist = GTK_CLIST(personEditDlg->clist_attrib);
+ gint row = personEditDlg->rowIndAttrib;
+ UserAttribute *attrib = gtk_clist_get_row_data(clist, row);
+ if (attrib) {
+ edit_person_attrib_edit(&errFlg, attrib);
+ if (!errFlg) {
+ gtk_clist_set_text(clist, row, ATTRIB_COL_NAME, attrib->name);
+ gtk_clist_set_text(clist, row, ATTRIB_COL_VALUE, attrib->value);
+ edit_person_attrib_clear(NULL);
+ }
+ }
+}
+
+static void edit_person_attrib_add(gpointer data) {
+ GtkCList *clist = GTK_CLIST(personEditDlg->clist_attrib);
+ gboolean errFlg = FALSE;
+ UserAttribute *attrib = NULL;
+ gint row = personEditDlg->rowIndAttrib;
+ if (gtk_clist_get_row_data(clist, row) == NULL) row = 0;
+
+ attrib = edit_person_attrib_edit(&errFlg, NULL);
+ if (!errFlg) {
+ gchar *text[EMAIL_N_COLS];
+ text[ATTRIB_COL_NAME] = attrib->name;
+ text[ATTRIB_COL_VALUE] = attrib->value;
+
+ row = gtk_clist_insert(clist, 1 + row, text);
+ gtk_clist_set_row_data(clist, row, attrib);
+ gtk_clist_select_row(clist, row, 0);
+ edit_person_attrib_clear(NULL);
+ }
+}
+
+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;
+ const gchar *sName;
+ int index;
+
+ if (personEditDlg->read_only)
+ return;
+
+ index = gtk_option_menu_get_history(GTK_OPTION_MENU(personEditDlg->entry_atname));
+ sName = ATTRIBUTE[index];
+ if (list_find_attribute(sName)) {
+ gtk_widget_set_sensitive(personEditDlg->attrib_add,FALSE);
+ gtk_widget_set_sensitive(personEditDlg->attrib_mod,non_empty);
+ attrib_adding = FALSE;
+ attrib_saving = non_empty;
+ }
+ else {
+ gtk_widget_set_sensitive(personEditDlg->attrib_add,TRUE);
+ gtk_widget_set_sensitive(personEditDlg->attrib_mod,non_empty);
+ attrib_adding = TRUE;
+ attrib_saving = non_empty;
+ }
+}
+
+static gboolean edit_person_entry_att_pressed(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+ if (event && (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter)) {
+ if (attrib_saving)
+ edit_person_attrib_modify(NULL);
+ else if (attrib_adding)
+ edit_person_attrib_add(NULL);
+ }
+ return FALSE;
+}
+
+void addressbook_edit_person_page_attrib_ldap(PersonEditDlg *dialog, gint pageNum, gchar *pageLbl) {
+ GtkWidget *option_menu;
+ GtkMenu *names_menu;
+
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *vboxl;
+ GtkWidget *vboxb;
+ GtkWidget *vbuttonbox;
+ GtkWidget *buttonDel;
+ GtkWidget *buttonMod;
+ GtkWidget *buttonAdd;
+
+ GtkWidget *table;
+ GtkWidget *label;
+ GtkWidget *clist_swin;
+ GtkWidget *clist;
+ GtkWidget *entry_value;
+ gint top;
+
+ personEditDlg = dialog;
+
+ gchar *titles[ATTRIB_N_COLS];
+ gint i;
+
+ titles[ATTRIB_COL_NAME] = N_("Name");
+ titles[ATTRIB_COL_VALUE] = N_("Value");
+
+ vbox = gtk_vbox_new(FALSE, 8);
+ gtk_widget_show(vbox);
+ gtk_container_add(GTK_CONTAINER(personEditDlg->notebook), vbox);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), BORDER_WIDTH);
+
+ label = gtk_label_new_with_mnemonic(pageLbl);
+ gtk_widget_show(label);
+ gtk_notebook_set_tab_label(
+ GTK_NOTEBOOK(personEditDlg->notebook),
+ gtk_notebook_get_nth_page(GTK_NOTEBOOK(personEditDlg->notebook), pageNum), label);
+
+ /* Split into two areas */
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(vbox), hbox);
+
+ /* Attribute list */
+ vboxl = gtk_vbox_new(FALSE, 4);
+ gtk_container_add(GTK_CONTAINER(hbox), vboxl);
+ gtk_container_set_border_width(GTK_CONTAINER(vboxl), 4);
+
+ clist_swin = gtk_scrolled_window_new(NULL, NULL);
+ gtk_container_add(GTK_CONTAINER(vboxl), clist_swin);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(clist_swin),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ clist = gtk_clist_new_with_titles(ATTRIB_N_COLS, titles);
+ gtk_container_add(GTK_CONTAINER(clist_swin), clist);
+ gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_BROWSE);
+ gtk_clist_set_column_width(GTK_CLIST(clist), ATTRIB_COL_NAME, ATTRIB_COL_WIDTH_NAME);
+ gtk_clist_set_column_width(GTK_CLIST(clist), ATTRIB_COL_VALUE, ATTRIB_COL_WIDTH_VALUE);
+ gtk_clist_set_compare_func(GTK_CLIST(clist), edit_person_attrib_compare_func);
+ gtk_clist_set_auto_sort(GTK_CLIST(clist), TRUE);
+
+ for (i = 0; i < ATTRIB_N_COLS; i++)
+ GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist)->column[i].button, GTK_CAN_FOCUS);
+
+ /* Data entry area */
+ table = gtk_table_new(4, 2, FALSE);
+ gtk_box_pack_start(GTK_BOX(vboxl), table, FALSE, FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(table), 4);
+ gtk_table_set_row_spacings(GTK_TABLE(table), 4);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 4);
+
+ /* First row */
+ top = 0;
+ label = gtk_label_new(N_("Name"));
+ gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+
+ names_menu = g_object_new(GTK_TYPE_MENU, NULL);
+ gchar **attribute = (gchar **) ATTRIBUTE;
+
+ while (*attribute) {
+ gtk_menu_shell_append(GTK_MENU_SHELL(names_menu),
+ gtk_menu_item_new_with_label(*attribute++));
+ }
+ option_menu = GTK_WIDGET(g_object_new(GTK_TYPE_OPTION_MENU, "menu", names_menu, NULL));
+ gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), 0);
+
+ gtk_table_attach(GTK_TABLE(table), option_menu, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
+
+ /* Next row */
+ ++top;
+ label = gtk_label_new(N_("Value"));
+ gtk_table_attach(GTK_TABLE(table), label, 0, 1, top, (top + 1), GTK_FILL, 0, 0, 0);
+ gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+
+ entry_value = gtk_entry_new();
+ gtk_table_attach(GTK_TABLE(table), entry_value, 1, 2, top, (top + 1), GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
+
+ /* Button box */
+ vboxb = gtk_vbox_new(FALSE, 4);
+ gtk_box_pack_start(GTK_BOX(hbox), vboxb, FALSE, FALSE, 2);
+
+ vbuttonbox = gtk_vbutton_box_new();
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(vbuttonbox), GTK_BUTTONBOX_START);
+ gtk_box_set_spacing(GTK_BOX(vbuttonbox), 8);
+ gtk_container_set_border_width(GTK_CONTAINER(vbuttonbox), 4);
+ gtk_container_add(GTK_CONTAINER(vboxb), vbuttonbox);
+
+ /* Buttons */
+ buttonDel = gtk_button_new_from_stock(GTK_STOCK_DELETE);
+ gtk_container_add(GTK_CONTAINER(vbuttonbox), buttonDel);
+
+ buttonMod = gtk_button_new_from_stock(GTK_STOCK_SAVE);
+ gtk_container_add(GTK_CONTAINER(vbuttonbox), buttonMod);
+
+ buttonAdd = gtk_button_new_from_stock(GTK_STOCK_ADD);
+ gtk_container_add(GTK_CONTAINER(vbuttonbox), buttonAdd);
+
+ gtk_widget_set_sensitive(buttonDel,FALSE);
+ gtk_widget_set_sensitive(buttonMod,FALSE);
+ gtk_widget_set_sensitive(buttonAdd,FALSE);
+
+ gtk_widget_show_all(vbox);
+
+ /* Event handlers */
+ g_signal_connect(G_OBJECT(clist), "select_row",
+ G_CALLBACK( edit_person_attrib_list_selected), NULL);
+ g_signal_connect(G_OBJECT(buttonDel), "clicked",
+ G_CALLBACK(edit_person_attrib_delete), NULL);
+ g_signal_connect(G_OBJECT(buttonMod), "clicked",
+ G_CALLBACK(edit_person_attrib_modify), NULL);
+ g_signal_connect(G_OBJECT(buttonAdd), "clicked",
+ G_CALLBACK(edit_person_attrib_add), NULL);
+ g_signal_connect(G_OBJECT(option_menu), "changed",
+ G_CALLBACK(edit_person_entry_att_changed), NULL);
+ g_signal_connect(G_OBJECT(entry_value), "key_press_event",
+ G_CALLBACK(edit_person_entry_att_pressed), NULL);
+ g_signal_connect(G_OBJECT(option_menu), "changed",
+ G_CALLBACK(edit_person_option_menu_changed), clist);
+
+ personEditDlg->clist_attrib = clist;
+ personEditDlg->entry_atname = option_menu;
+ personEditDlg->entry_atvalue = entry_value;
+ personEditDlg->attrib_add = buttonAdd;
+ personEditDlg->attrib_del = buttonDel;
+ personEditDlg->attrib_mod = buttonMod;
+}
+
+#endif /* USE_LDAP */
+
+
--- /dev/null
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-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.
+ */
+
+/*
+ * Edit address item data.
+ */
+
+#ifndef __EDITADDRESS_OTHER_ATTRIBUTES_LDAP_H__
+#define __EDITADDRESS_OTHER_ATTRIBUTES_LDAP_H__
+
+#ifdef USE_LDAP
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkwindow.h>
+#include <gtk/gtksignal.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtktable.h>
+
+typedef struct _PersonEdit_dlg PersonEditDlg;
+struct _PersonEdit_dlg {
+ GtkWidget *container;
+ GtkWidget *notebook;
+ GtkWidget *ok_btn;
+ GtkWidget *cancel_btn;
+ GtkWidget *statusbar; /* used when prefs_common.addressbook_use_editaddress_dialog is TRUE */
+ GtkWidget *title; /* used when prefs_common.addressbook_use_editaddress_dialog is FALSE */
+ gint status_cid;
+
+ /* User data tab */
+ GtkWidget *entry_name;
+ GtkWidget *entry_first;
+ GtkWidget *entry_last;
+ GtkWidget *entry_nick;
+
+ /* EMail data tab */
+ GtkWidget *entry_email;
+ GtkWidget *entry_alias;
+ GtkWidget *entry_remarks;
+ GtkWidget *clist_email;
+ GtkWidget *email_up;
+ GtkWidget *email_down;
+ GtkWidget *email_del;
+ GtkWidget *email_mod;
+ GtkWidget *email_add;
+
+ /* Attribute data tab */
+ GtkWidget *entry_atname;
+ GtkWidget *entry_atvalue;
+ GtkWidget *clist_attrib;
+ GtkWidget *attrib_add;
+ GtkWidget *attrib_del;
+ GtkWidget *attrib_mod;
+
+ gint rowIndEMail;
+ gint rowIndAttrib;
+ gboolean editNew;
+ gboolean read_only;
+ gboolean ldap;
+};
+
+static const char *ATTRIBUTE[] = {
+ "telephoneNumber",
+ /*"description (Remarks)",*/
+ "title",
+ "telexNumber",
+ "facsimileTelephoneNumber",
+ "street",
+ "postOfficeBox",
+ "postalCode",
+ "postalAddress",
+ "st", /* state or province */
+ "departmentNumber",
+ "homePhone",
+ "homePostalAddress",
+ "initials",
+ "labeledURI",
+ "mobile",
+ "pager",
+ "roomNumber",
+ NULL
+};
+
+static const int ATTRIBUTE_SIZE = (sizeof(ATTRIBUTE) / sizeof(*ATTRIBUTE)) - 1;
+
+/* Function proto types */
+void addressbook_edit_person_page_attrib_ldap(PersonEditDlg *personEditDlg, gint pageNum, gchar *pageLbl);
+int get_attribute_index(const gchar *string_literal);
+
+#endif /* USE_LDAP */
+
+#endif /* __EDITADDRESS_OTHER_ATTRIBUTES_LDAP_H__ */
g_free( sPass );
}
-static void edit_ldap_search_reset( void ) {
- gtk_entry_set_text(GTK_ENTRY(ldapedit.entry_criteria), LDAPCTL_DFL_ATTR_LIST );
+static void edit_ldap_search_reset() {
+ gtk_entry_set_text(GTK_ENTRY(ldapedit.entry_criteria), ldapctl_get_default_criteria());
}
static void addressbook_edit_ldap_dialog_create( gboolean *cancelled ) {
gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
entry_criteria = gtk_entry_new();
+ gtk_editable_set_editable(GTK_EDITABLE(entry_criteria), FALSE);
gtk_table_attach(GTK_TABLE(table), entry_criteria, 1, 2, top, (top + 1),
GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0, 0);
/**
* Clear entry fields to reasonable defaults (for a new server entry).
*/
-static void edit_ldap_clear_fields( void ) {
+static void edit_ldap_clear_fields() {
gtk_entry_set_text(
GTK_ENTRY(ldapedit.entry_name), ADDRESSBOOK_GUESS_LDAP_NAME );
gtk_entry_set_text(
gtk_spin_button_set_value(
GTK_SPIN_BUTTON( ldapedit.spinbtn_maxentry ), LDAPCTL_DFL_TIMEOUT );
gtk_entry_set_text(
- GTK_ENTRY(ldapedit.entry_criteria), LDAPCTL_DFL_ATTR_LIST );
+ GTK_ENTRY(ldapedit.entry_criteria), ldapctl_get_default_criteria());
gtk_spin_button_set_value(
GTK_SPIN_BUTTON(ldapedit.spinbtn_queryage), LDAPCTL_DFL_QUERY_AGE );
gtk_toggle_button_set_active(
GTK_WINDOW(ldapedit.window), _("Edit LDAP Server"));
}
else {
- edit_ldap_clear_fields();
+ edit_ldap_clear_fields(NULL);
gtk_window_set_title(
GTK_WINDOW(ldapedit.window), _("Add New LDAP Server"));
}
#include "ldapctrl.h"
#include "mgutils.h"
+#include "editaddress_other_attributes_ldap.h"
/**
* Create new LDAP control block object.
*/
char **ldapctl_attribute_array( LdapControl *ctl ) {
char **ptrArray;
- GList *node;
+ GList *node, *def;
gint cnt, i;
g_return_val_if_fail( ctl != NULL, NULL );
+ def = ldapctl_get_default_criteria_list();
+ /* check if this servers config is updated to the new
+ * default list of search criteria. If not update the list */
+ if (! ldapctl_compare_list(ctl->listCriteria, def)) {
+ /* Deep copy search criteria */
+ ldapctl_criteria_list_clear(ctl);
+ while(def) {
+ ctl->listCriteria = g_list_append(
+ ctl->listCriteria, g_strdup(def->data));
+ def = g_list_next(def);
+ }
+ }
+ node = ctl->listCriteria;
cnt = g_list_length( ctl->listCriteria );
ptrArray = g_new0( char *, 1 + cnt );
i = 0;
- node = ctl->listCriteria;
while( node ) {
ptrArray[ i++ ] = node->data;
node = g_list_next( node );
}
}
+/**
+ * Return the default LDAP search criteria string.
+ * \return Formatted string or <i>""</i>. Should be g_free() when done.
+ */
+gchar *ldapctl_get_default_criteria() {
+ gchar *retVal = LDAPCTL_DFL_ATTR_LIST;
+ const gchar **attrs = ATTRIBUTE;
+
+ while (*attrs) {
+ retVal = g_strdup_printf("%s, %s", retVal, *attrs++);
+ }
+ return retVal;
+}
+
+/**
+ * Return the default LDAP search criteria list.
+ * \return GList or <i>NULL</i>.
+ */
+GList *ldapctl_get_default_criteria_list() {
+ gchar *criteria, *item;
+ gchar **c_list, **w_list;
+ GList *attr_list = NULL;
+
+ criteria = ldapctl_get_default_criteria();
+ c_list = g_strsplit(criteria, " ", 0);
+ g_free(criteria);
+ criteria = NULL;
+ w_list = c_list;
+ while ((criteria = *w_list++) != 0) {
+ /* copy string elimination <,> */
+ if (*w_list)
+ item = g_strndup(criteria, strlen(criteria) - 1);
+ else
+ item = g_strdup(criteria);
+ attr_list = g_list_append(attr_list, g_strdup(item));
+ g_free(item);
+ }
+ g_strfreev(c_list);
+ return attr_list;
+}
+
+/**
+ * Compare to GList for equality.
+ * \param l1 First GList
+ * \param l2 Second GList
+ * \Return TRUE or FALSE
+ */
+gboolean ldapctl_compare_list(GList *l1, GList *l2) {
+ gchar *first, *second;
+ if (! l1 && ! l2)
+ return TRUE;
+ if ((! l1 && l2) || (l1 && ! l2))
+ return FALSE;
+ while (l1 && l2) {
+ first = (gchar *) l1->data;
+ second = (gchar *) l2->data;
+ if ( ! (first && second) || strcmp(first, second) != 0) {
+ return FALSE;
+ }
+ l1 = g_list_next(l1);
+ l2 = g_list_next(l2);
+ }
+ return TRUE;
+}
+
#endif /* USE_LDAP */
/*
#define LDAPCTL_ATTR_PHONE "telephoneNumber"
#define LDAPCTL_ATTR_DISPLAYNAME "displayName"
-#define LDAPCTL_DFL_ATTR_LIST "mail, cn, givenName, sn, displayName, telephoneNumber"
+#define LDAPCTL_DFL_ATTR_LIST "mail, cn, givenName, sn, displayName"
/*
* Search matching options.
char **ldapctl_attribute_array ( LdapControl *ctl );
void ldapctl_free_attribute_array( char **ptrArray );
void ldapctl_parse_ldap_search ( LdapControl *ctl, gchar *criteria );
+gchar *ldapctl_get_default_criteria(void);
+GList *ldapctl_get_default_criteria_list();
+gboolean ldapctl_compare_list(GList *l1, GList *l2);
#endif /* USE_LDAP */
#include "ldaputil.h"
#include "utils.h"
#include "adbookbase.h"
+#include "editaddress_other_attributes_ldap.h"
/**
* Structure to hold user defined attributes
return buf;
}
+/**
+ * Free created AttrKeyValue structure
+ * \param akv AttrKeyValue structure to free
+ */
+void attrkeyvalue_free(AttrKeyValue *akv) {
+ if (akv->key) {
+ g_free(akv->key);
+ akv->key = NULL;
+ }
+ if (akv->value) {
+ g_free(akv->value);
+ akv->value = NULL;
+ }
+ g_free(akv);
+ akv = NULL;
+}
+
/**
* Retrieve E-Mail address object for update.
* \param item ItemEmail to update.
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)
+ 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;
}
* \param list List of GHashTable
*/
void ldapsvr_free_hashtable(GList *list) {
- while (list) {
- g_hash_table_destroy(list->data);
- list = g_list_next(list);
+ GList *tmp = list;
+ while (tmp) {
+ g_hash_table_destroy(tmp->data);
+ tmp->data = NULL;
+ tmp = g_list_next(tmp);
}
g_list_free(list);
+ list = NULL;
}
/**
return buf;
}
+/**
+ * Free a created Rdn structure
+ * \param rdn Structure to free
+ */
+void rdn_free(Rdn *rdn) {
+ if (rdn->attribute) {
+ g_free(rdn->attribute);
+ rdn->attribute = NULL;
+ }
+ if (rdn->value) {
+ g_free(rdn->value);
+ rdn->value = NULL;
+ }
+ if (rdn->new_dn) {
+ g_free(rdn->new_dn);
+ rdn->new_dn = NULL;
+ }
+ g_free(rdn);
+ rdn = NULL;
+}
+
/**
* update Rdn structure
*
else {
/* We cannot remove dn */
g_free(compare);
+ rdn_free(rdn);
return NULL;
}
}
}
else {
/* We cannot remove dn */
+ rdn_free(rdn);
return NULL;
}
}
+ rdn_free(rdn);
return NULL;
}
}
if (ld)
ldapsvr_disconnect(ld);
-/* ldapsvr_force_refresh(server);
- ldapsvr_free_all_query(server);*/
}
/**
cn = attrkeyvalue_create();
start = g_strstr_len(dn, strlen(dn), "cn");
- if (start == NULL)
+ if (start == NULL) {
+ attrkeyvalue_free(cn);
return NULL;
+ }
end = g_strstr_len(start, strlen(start), ",");
item = g_strndup(start, end - start);
- if (item == NULL)
+ if (item == NULL) {
+ attrkeyvalue_free(cn);
return NULL;
+ }
key_value = g_strsplit(item, "=", 2);
cn->key = g_strdup(key_value[0]);
cn->value = g_strdup(key_value[1]);
return cn;
}
+/**
+ * Get mail attribute from dn
+ *
+ * \param dn Distinguesh Name for current object
+ * \return AttrKeyValue, or <i>NULL</i> if none created
+ */
+AttrKeyValue *get_mail(gchar *dn) {
+ AttrKeyValue *mail;
+ gchar *start;
+ gchar *end;
+ gchar *item;
+ gchar **key_value;
+ g_return_val_if_fail(dn != NULL, NULL);
+
+ mail = attrkeyvalue_create();
+ start = g_strstr_len(dn, strlen(dn), "mail");
+ if (start == NULL) {
+ attrkeyvalue_free(mail);
+ return NULL;
+ }
+ end = g_strstr_len(start, strlen(start), ",");
+ item = g_strndup(start, end - start);
+ if (item == NULL) {
+ attrkeyvalue_free(mail);
+ return NULL;
+ }
+ key_value = g_strsplit(item, "=", 2);
+ mail->key = g_strdup(key_value[0]);
+ mail->value = g_strdup(key_value[1]);
+ g_strfreev(key_value);
+ g_free(item);
+ return mail;
+}
+
/**
* Get ou or o attribute from dn
*
start = g_strstr_len(dn, strlen(dn), ",o=");
if (start == NULL)
start = g_strstr_len(dn, strlen(dn), ",ou=");
- if (start == NULL)
+ if (start == NULL) {
+ attrkeyvalue_free(ou);
return NULL;
+ }
start++;
end = g_strstr_len(start, strlen(start), ",");
item = g_strndup(start, end - start);
- if (item == NULL)
+ if (item == NULL) {
+ attrkeyvalue_free(ou);
return NULL;
+ }
key_value = g_strsplit(item, "=", 2);
ou->key = g_strdup(key_value[0]);
ou->value = g_strdup(key_value[1]);
g_return_if_fail(ld != NULL || dn != NULL || cnt >= 0 || mods != NULL);
for (i = 0; i < cnt; i++) {
- rc = ldap_compare_s(ld, dn, mods[i]->mod_type, mods[i]->mod_vals.modv_strvals[0]);
+ gchar *value = g_strdup(mods[i]->mod_vals.modv_strvals[0]);
+ if (!value || strcmp(value, "") == 0)
+ value = g_strdup("thisisonlyadummy");
+ rc = ldap_compare_s(ld, dn, mods[i]->mod_type, value);
fprintf(stderr, "ldap_compare for (%s:%s)\" failed[0x%x]: %s\n",
- mods[i]->mod_type, mods[i]->mod_vals.modv_strvals[0], rc, ldap_err2string(rc));
+ mods[i]->mod_type, value, rc, ldap_err2string(rc));
+ g_free(value);
+ }
+}
+
+/**
+ * compare attribute to LDAP in case of LDAP_INAPPROPRIATE_MATCHING
+ *
+ * \param ld AddressBook resource
+ * \param server Reference to server
+ * \param dn dn for the entry
+ * \param attr Attribute
+ * \param value New value
+ * \return int, return will be LDAP_MOD_ADD, LDAP_MOD_REPLACE, or LDAP_MOD_DELETE
+ */
+int ldapsvr_compare_manual_attr(LDAP *ld, LdapServer *server, gchar *dn, char *attr, char *value) {
+ LDAPMessage *res, *e = NULL;
+ BerElement *ber;
+ struct berval **vals;
+ int rc;
+ LdapControl *ctl;
+ gchar *filter;
+ gchar *attribute;
+ int retVal, i;
+ AttrKeyValue *mail;
+
+ g_return_val_if_fail(ld != NULL || server != NULL || attr != NULL, -1);
+ ctl = server->control;
+ mail = get_mail(dn);
+ if (! mail)
+ return -2;
+ filter = g_strdup_printf("(&(mail=%s)(%s=*))", mail->value, attr);
+ attrkeyvalue_free(mail);
+ if (ctl) {
+ rc = ldap_search_s(ld, ctl->baseDN, /*LDAP_SCOPE_SUBTREE*/LDAP_SCOPE_ONELEVEL, filter, NULL, 0, &res);
+ if (rc) {
+ fprintf(stderr, "ldap_search for attr=%s\" failed[0x%x]: %s\n",attr, rc, ldap_err2string(rc));
+ retVal = -2;
+ }
+ else {
+ e = ldap_first_entry(ld, res);
+ /* entry has this attribute */
+ if (e) {
+ attribute = ldap_first_attribute( ld, e, &ber );
+ if (attribute) {
+ if (value) {
+ if( ( vals = ldap_get_values_len( ld, e, attr ) ) != NULL ) {
+ for( i = 0; vals[i] != NULL; i++ ) {
+ debug_print("Compare: %s=%s\n", attr, vals[i]->bv_val);
+ /* attribute has same value */
+ if (strcmp(vals[i]->bv_val, value) == 0)
+ retVal = -1;
+ /* attribute has new value */
+ else
+ retVal = LDAP_MOD_REPLACE;
+ }
+ }
+ ldap_value_free_len(vals);
+ }
+ else
+ retVal = LDAP_MOD_DELETE;
+ }
+ if( ber != NULL ) {
+ ber_free( ber, 0 );
+ }
+ ldap_memfree(attribute);
+ }
+ /* entry does not have this attribute */
+ else {
+ /* Only add if this is a real attribute */
+ if (value)
+ retVal = LDAP_MOD_ADD;
+ /* This is dummy value used to avoid ldap_compare error */
+ else
+ retVal = -1;
+ }
+ }
+ }
+ else
+ retVal = -2;
+ g_free(filter);
+ return retVal;
+}
+
+/**
+ * Deside which kind of operation is required to handle
+ * updating the specified attribute
+ *
+ * \param ld AddressBook resource
+ * \param server Reference to server
+ * \param dn dn for the entry
+ * \param attr Attribute
+ * \param value New value
+ * \return int, return will be LDAP_MOD_ADD, LDAP_MOD_REPLACE, or LDAP_MOD_DELETE
+ */
+int ldapsvr_deside_operation(LDAP *ld, LdapServer *server, char *dn, char *attr, char *value) {
+ int rc;
+ gboolean dummy = FALSE;
+
+ g_return_val_if_fail(ld != NULL || server != NULL || dn != NULL || attr != NULL, -1);
+ if (value == NULL)
+ return -1;
+ /* value containing empty string cause invalid syntax. A bug in
+ * the LDAP library? Therefore we add a dummy value
+ */
+ if (strcmp(value,"") == 0) {
+ value = g_strdup("thisisonlyadummy");
+ dummy = TRUE;
+ }
+ rc = ldap_compare_s(ld, dn, attr, value);
+ debug_print("ldap_compare for (%s:%s)\" error_code[0x%x]: %s\n",
+ attr, value, rc, ldap_err2string(rc));
+ switch (rc) {
+ case LDAP_COMPARE_FALSE:
+ if (dummy)
+ return LDAP_MOD_DELETE;
+ else
+ return LDAP_MOD_REPLACE;
+ case LDAP_COMPARE_TRUE: return -1;
+ case LDAP_NO_SUCH_ATTRIBUTE: return LDAP_MOD_ADD;
+ /* LDAP_INAPPROPRIATE_MATCHING needs extensive testing because I
+ * am not aware off the condition causing this return value!
+ */
+ case LDAP_INAPPROPRIATE_MATCHING:
+ if (dummy)
+ value = NULL;
+ return ldapsvr_compare_manual_attr(ld, server, dn, attr, value);
+ case LDAP_UNDEFINED_TYPE: return -2;
+ case LDAP_INVALID_SYNTAX: return -2;
+ default: return -2;
+ }
+}
+
+/**
+ * Check if attribute is part of the current search criteria
+ *
+ * \param list Array containing attributes in the current search criteria
+ * \param attr Attribute to check
+ * \result <i>TRUE</i> if attribute is found in the current search criteria
+ */
+gboolean ldapsvr_check_search_attributes(char **list, char *attr) {
+ while (*list) {
+ if (strcmp(*list++, attr) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Deside which other attributes needs updating
+ *
+ * \param ld LDAP resource
+ * \param server AddressBook resource
+ * \param dn dn for the entry
+ * \param contact GHashTable with information for the current contact
+ */
+void ldapsvr_handle_other_attributes(LDAP *ld, LdapServer *server, char *dn, GHashTable *contact) {
+ GList *node;
+ gboolean CHECKED_ATTRIBUTE[ATTRIBUTE_SIZE];
+ LDAPMod *mods[ATTRIBUTE_SIZE + 1];
+ LDAPMod modarr[ATTRIBUTE_SIZE];
+ gint cnt = 0;
+ char *attr[] = {NULL, NULL};
+ int mod_op, rc, i;
+
+ g_return_if_fail(server != NULL || dn != NULL || contact != NULL);
+ for (i = 0; i < ATTRIBUTE_SIZE; i++)
+ CHECKED_ATTRIBUTE[i] = FALSE;
+ node = g_hash_table_lookup(contact , "attribute");
+ while (node) {
+ AttrKeyValue *item = node->data;
+ if (item) {
+ int index = get_attribute_index(item->key);
+ if (index >= 0) {
+ debug_print("Found other attribute: %s = %s\n", item->key, item->value);
+ mod_op = ldapsvr_deside_operation(ld, server, dn, item->key, item->value);
+ /* Only consider attributes which we no how to handle.
+ * Set to TRUE in CHECKED_ATTRIBUTE array to indicate no further action
+ */
+ if (mod_op < 0) {
+ CHECKED_ATTRIBUTE[index] = TRUE;
+ node = g_list_next(node);
+ continue;
+ }
+ if (mod_op == LDAP_MOD_DELETE) {
+ /* Setting param to NULL instructs OpenLDAP to remove any
+ * value stored for this attribute and remove the attribute
+ * completely. Should multiple instances of an attribute be
+ * allowed in the future param is required to have the value
+ * store for the attribute which is going to be deleted
+ */
+ item->value = NULL;
+ }
+ if (mod_op == LDAP_MOD_REPLACE && strcmp(item->value, "") == 0) {
+ /* Having an empty string is considered a syntax error in
+ * ldap. E.g attributes with empty strings are not allowed
+ * in which case we treate this as a request for deleting
+ * the attribute.
+ */
+ mod_op = LDAP_MOD_DELETE;
+ item->value = NULL;
+ }
+ if (mod_op == LDAP_MOD_ADD && strcmp(item->value, "") == 0) {
+ /* Adding an empty string is considered a syntax error in
+ * ldap. E.g attributes with empty strings are not allowed
+ * in which case we silently refuse to add this entry
+ */
+ }
+ else {
+ SETMOD(mods[cnt], modarr[cnt], mod_op, g_strdup(item->key), attr, g_strdup(item->value));
+ cnt++;
+ CHECKED_ATTRIBUTE[index] = TRUE;
+ }
+ }
+ }
+ node = g_list_next(node);
+ }
+ char **attribs = ldapctl_attribute_array(server->control);
+ for (i = 0; i < ATTRIBUTE_SIZE; i++) {
+ /* Attributes which holds no information are to be removed */
+ if (CHECKED_ATTRIBUTE[i] == FALSE) {
+ /* Only consider those attributes which is currently part of the search criteria.
+ * If attributes are not part of the search criteria they would seem to hold
+ * no information since their values will not be populated in the GUI
+ */
+ if (ldapsvr_check_search_attributes(attribs, (char *) ATTRIBUTE[i])) {
+ mod_op = ldapsvr_deside_operation(ld, server, dn, (char *) ATTRIBUTE[i], "");
+ if (mod_op == LDAP_MOD_DELETE) {
+ SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_DELETE, g_strdup((char *) ATTRIBUTE[i]), attr, NULL);
+ cnt++;
+ }
+ }
+ }
+ }
+ ldapctl_free_attribute_array(attribs);
+ mods[cnt] = NULL;
+ if (debug_get_mode())
+ ldapsvr_print_ldapmod(mods);
+ server->retVal = LDAPRC_SUCCESS;
+ rc = ldap_modify_ext_s(ld, 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",dn, rc, ldap_err2string(rc));
+ if (rc == 0x8)
+ server->retVal = LDAPRC_STRONG_AUTH;
+ else
+ server->retVal = LDAPRC_NAMING_VIOLATION;
+ }
+ }
+ else {
+ /* Only consider those attributes which is currently part of the search criteria.
+ * If attributes are not part of the search criteria they would seem to hold
+ * no information since their values will not be populated in the GUI
+ */
+ char **attribs = ldapctl_attribute_array(server->control);
+ for (i = 0; i < ATTRIBUTE_SIZE; i++) {
+ if (ldapsvr_check_search_attributes(attribs, (char *) ATTRIBUTE[i])) {
+ if (CHECKED_ATTRIBUTE[i] == FALSE) {
+ AddrItemObject *aio = addrcache_get_object(server->addressCache, g_hash_table_lookup(contact , "uid"));
+ ItemPerson *person = (ItemPerson *) aio;
+ addritem_person_remove_attribute(person, (const gchar *) ATTRIBUTE[i]);
+ }
+ }
+ }
+ ldapctl_free_attribute_array(attribs);
}
}
cnt++;
ou = get_ou(base_dn);
if (ou != NULL) {
- SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, ou->key, org, ou->value);
+ SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, g_strdup(ou->key), org, g_strdup(ou->value));
cnt++;
+ attrkeyvalue_free(ou);
}
commonName = get_cn(base_dn);
}
}
else {
- SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, commonName->key, cn, commonName->value);
+ SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, g_strdup(commonName->key), cn, g_strdup(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);
+ attrkeyvalue_free(commonName);
}
cnt++;
param = g_hash_table_lookup(contact , "givenName");
server->retVal = LDAPRC_NAMING_VIOLATION;
}
}
+ ldapsvr_handle_other_attributes(ld, server, base_dn, contact);
g_free(base_dn);
clean_up(ld, server, contact);
}
-/**
- * Deside which kind of operation is required to handle
- * updating the specified attribute
- *
- * \param ld AddressBook resource
- * \param dn dn for the entry
- * \param attr Attribute
- * \param value New value
- * \return int, return will be LDAP_MOD_ADD, LDAP_MOD_REPLACE, or LDAP_MOD_DELETE
- */
-int ldapsvr_deside_operation(LDAP *ld, char *dn, char *attr, char *value) {
- int rc;
- gboolean dummy = FALSE;
-
- g_return_val_if_fail(ld != NULL || dn != NULL || attr != NULL, -1);
- if (value == NULL)
- return -1;
- /* value containing empty string cause invalid syntax. A bug in
- * the LDAP library? Therefore we add a dummy value
- */
- if (strcmp(value,"") == 0) {
- value = g_strdup("thisisonlyadummy");
- dummy = TRUE;
- }
- rc = ldap_compare_s(ld, dn, attr, value);
- debug_print("ldap_compare for (%s:%s)\" error_code[0x%x]: %s\n",
- attr, value, rc, ldap_err2string(rc));
- switch (rc) {
- case LDAP_COMPARE_FALSE:
- if (dummy)
- return LDAP_MOD_DELETE;
- else
- return LDAP_MOD_REPLACE;
- case LDAP_COMPARE_TRUE: return -1;
- case LDAP_NO_SUCH_ATTRIBUTE: return LDAP_MOD_ADD;
- case LDAP_UNDEFINED_TYPE: return -2;
- case LDAP_INVALID_SYNTAX: return -2;
- default: return -2;
- }
-}
-
/**
* Update contact to LDAP
*
return;
}
param = g_hash_table_lookup(contact , "cn");
- mod_op = ldapsvr_deside_operation(ld, dn, "displayName", param);
+ mod_op = ldapsvr_deside_operation(ld, server, dn, "displayName", param);
if (mod_op >= 0 && (strcmp(param, NoRemove->value) != 0 && strcmp("cn", NoRemove->attribute) != 0)) {
if (mod_op == LDAP_MOD_DELETE) {
/* Setting param to NULL instructs OpenLDAP to remove any
}
}
param = g_hash_table_lookup(contact , "givenName");
- mod_op = ldapsvr_deside_operation(ld, dn, "givenName", param);
+ mod_op = ldapsvr_deside_operation(ld, server, dn, "givenName", param);
if (mod_op >= 0 && (strcmp(param, NoRemove->value) != 0 && strcmp("givenName", NoRemove->attribute) != 0)) {
if (mod_op == LDAP_MOD_DELETE) {
/* Setting param to NULL instructs OpenLDAP to remove any
*/
}
param = g_hash_table_lookup(contact , "sn");
- mod_op = ldapsvr_deside_operation(ld, dn, "sn", param);
+ mod_op = ldapsvr_deside_operation(ld, server, dn, "sn", param);
if (mod_op >= 0 && (strcmp(param, NoRemove->value) != 0 && strcmp("sn", NoRemove->attribute) != 0)) {
if (mod_op == LDAP_MOD_DELETE) {
/* Setting param to NULL instructs OpenLDAP to remove any
}
debug_print("newDN: %s\n", dn);
if (NoRemove)
- g_free(NoRemove);
+ rdn_free(NoRemove);
server->retVal = LDAPRC_SUCCESS;
if (cnt > 0) {
int rc;
if (mail)
g_free(mail);
}
+ ldapsvr_handle_other_attributes(ld, server, dn, contact);
/* If we do not make changes persistent at this point then changes
* will be lost if the user makes new search on the same server since
* changes are only present in Claws' internal cache. This issue has to