diff options
Diffstat (limited to 'addressbook')
-rw-r--r-- | addressbook/backend/pas/pas-backend-ldap.c | 519 | ||||
-rw-r--r-- | addressbook/backend/pas/pas-backend-ldap.h | 32 |
2 files changed, 551 insertions, 0 deletions
diff --git a/addressbook/backend/pas/pas-backend-ldap.c b/addressbook/backend/pas/pas-backend-ldap.c new file mode 100644 index 0000000000..0f95aa5484 --- /dev/null +++ b/addressbook/backend/pas/pas-backend-ldap.c @@ -0,0 +1,519 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Author: + * Nat Friedman (nat@helixcode.com) + * + * Copyright 2000, Helix Code, Inc. + */ + +#include "config.h" +#include <gtk/gtksignal.h> +#include <fcntl.h> +#include <time.h> +#include <lber.h> +#include <ldap.h> + +#include "pas-backend-ldap.h" +#include "pas-book.h" +#include "pas-card-cursor.h" + +static PASBackendClass *pas_backend_ldap_parent_class; +typedef struct _PASBackendLDAPCursorPrivate PASBackendLDAPCursorPrivate; + +struct _PASBackendLDAPPrivate { + gboolean connected; + GList *clients; + LDAP *ldap; +}; + +struct _PASBackendLDAPCursorPrivate { + PASBackend *backend; + PASBook *book; + + GList *elements; + int num_elements; +}; + +static long +get_length(PASCardCursor *cursor, gpointer data) +{ + PASBackendLDAPCursorPrivate *cursor_data = (PASBackendLDAPCursorPrivate *) data; + + return cursor_data->num_elements; +} + +static char * +get_nth(PASCardCursor *cursor, long n, gpointer data) +{ + return g_strdup(""); +} + +static void +cursor_destroy(GtkObject *object, gpointer data) +{ + CORBA_Environment ev; + Evolution_Book corba_book; + PASBackendLDAPCursorPrivate *cursor_data = (PASBackendLDAPCursorPrivate *) data; + + corba_book = bonobo_object_corba_objref(BONOBO_OBJECT(cursor_data->book)); + + CORBA_exception_init(&ev); + + Evolution_Book_unref(corba_book, &ev); + + if (ev._major != CORBA_NO_EXCEPTION) { + g_warning("cursor_destroy: Exception unreffing " + "corba book.\n"); + } + + CORBA_exception_free(&ev); + + /* free the ldap specific cursor information */ + + + g_free(cursor_data); +} + +static char * +pas_backend_ldap_create_unique_id (char *vcard) +{ + /* use a 32 counter and the 32 bit timestamp to make an id. + it's doubtful 2^32 id's will be created in a second, so we + should be okay. */ + static guint c = 0; + return g_strdup_printf ("pas-id-%08lX%08X", time(NULL), c++); +} + +static void +pas_backend_ldap_process_create_card (PASBackend *backend, + PASBook *book, + PASRequest *req) +{ + PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); + LDAP *ldap = bl->priv->ldap; + int ldap_error; + char *id; + + id = pas_backend_ldap_create_unique_id (req->vcard); + + /* XXX use ldap_add_s */ + + if (LDAP_SUCCESS == ldap_error) { + pas_book_notify_add(book, id); + + pas_book_respond_create ( + book, + Evolution_BookListener_Success, + id); + } + else { + /* XXX need a different call status for this case, i + think */ + pas_book_respond_create ( + book, + Evolution_BookListener_CardNotFound, + ""); + } + + g_free (id); + g_free (req->vcard); +} + +static void +pas_backend_ldap_process_remove_card (PASBackend *backend, + PASBook *book, + PASRequest *req) +{ + PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); + LDAP *ldap = bl->priv->ldap; + int ldap_error; + + /* XXX use ldap_delete_s */ + + if (LDAP_SUCCESS == ldap_error) { + pas_book_notify_remove (book, req->id); + + pas_book_respond_remove ( + book, + Evolution_BookListener_Success); + } + else { + pas_book_respond_remove ( + book, + Evolution_BookListener_CardNotFound); + } + + g_free (req->id); +} + +static void +pas_backend_ldap_build_all_cards_list(PASBackend *backend, + PASBackendLDAPCursorPrivate *cursor_data) +{ + PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); + LDAP *ldap = bl->priv->ldap; + int ldap_error; + LDAPMessage *res, *e; + + + if (ldap_search_s (ldap, NULL, LDAP_SCOPE_ONELEVEL, + "(objectclass=*)", + NULL, 0, &res) == -1) { + ldap_perror (ldap, "ldap_search"); + } + + cursor_data->elements = NULL; + + cursor_data->num_elements = ldap_count_entries (ldap, res); + + e = ldap_first_entry(ldap, res); + + while (NULL != e) { + + /* for now just make a list of the dn's */ +#if 0 + for ( a = ldap_first_attribute( ldap, e, &ber ); a != NULL; + a = ldap_next_attribute( ldap, e, ber ) ) { + } +#else + cursor_data->elements = g_list_prepend(cursor_data->elements, + g_strdup(ldap_get_dn(ldap, e))); +#endif + + e = ldap_next_entry(ldap, e); + } + + ldap_msgfree(res); +} + +static void +pas_backend_ldap_process_modify_card (PASBackend *backend, + PASBook *book, + PASRequest *req) +{ + PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); + LDAP *ldap = bl->priv->ldap; + int ldap_error; + + /* XXX use ldap_modify_s */ + + if (LDAP_SUCCESS == ldap_error) { + + pas_book_notify_change (book, req->id); + + pas_book_respond_modify ( + book, + Evolution_BookListener_Success); + } + else { + pas_book_respond_modify ( + book, + Evolution_BookListener_CardNotFound); + } + + g_free (req->vcard); +} + +static void +pas_backend_ldap_process_get_all_cards (PASBackend *backend, + PASBook *book, + PASRequest *req) +{ + CORBA_Environment ev; + PASBackendLDAPCursorPrivate *cursor_data; + int ldap_error = 0; + PASCardCursor *cursor; + Evolution_Book corba_book; + + cursor_data = g_new(PASBackendLDAPCursorPrivate, 1); + cursor_data->backend = backend; + cursor_data->book = book; + + pas_backend_ldap_build_all_cards_list(backend, cursor_data); + + corba_book = bonobo_object_corba_objref(BONOBO_OBJECT(book)); + + CORBA_exception_init(&ev); + + Evolution_Book_ref(corba_book, &ev); + + if (ev._major != CORBA_NO_EXCEPTION) { + g_warning("pas_backend_file_process_get_all_cards: Exception reffing " + "corba book.\n"); + } + + CORBA_exception_free(&ev); + + cursor = pas_card_cursor_new(get_length, + get_nth, + cursor_data); + + gtk_signal_connect(GTK_OBJECT(cursor), "destroy", + GTK_SIGNAL_FUNC(cursor_destroy), cursor_data); + + pas_book_respond_get_cursor ( + book, + (ldap_error == 0 + ? Evolution_BookListener_Success + : Evolution_BookListener_CardNotFound), + cursor); +} + +static void +pas_backend_ldap_process_check_connection (PASBackend *backend, + PASBook *book, + PASRequest *req) +{ + PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); + + pas_book_report_connection (book, bl->priv->connected); +} + +static void +pas_backend_ldap_process_client_requests (PASBook *book) +{ + PASBackend *backend; + PASRequest *req; + + backend = pas_book_get_backend (book); + + req = pas_book_pop_request (book); + if (req == NULL) + return; + + switch (req->op) { + case CreateCard: + pas_backend_ldap_process_create_card (backend, book, req); + break; + + case RemoveCard: + pas_backend_ldap_process_remove_card (backend, book, req); + break; + + case ModifyCard: + pas_backend_ldap_process_modify_card (backend, book, req); + break; + + case CheckConnection: + pas_backend_ldap_process_check_connection (backend, book, req); + break; + + case GetAllCards: + pas_backend_ldap_process_get_all_cards (backend, book, req); + break; + } + + g_free (req); +} + +static void +pas_backend_ldap_book_destroy_cb (PASBook *book) +{ + PASBackendLDAP *backend; + + backend = PAS_BACKEND_LDAP (pas_book_get_backend (book)); + + pas_backend_remove_client (PAS_BACKEND (backend), book); +} + +static char * +pas_backend_ldap_get_vcard (PASBook *book, const char *id) +{ + PASBackendLDAP *bl; + LDAP *ldap; + int ldap_error; + + bl = PAS_BACKEND_LDAP (pas_book_get_backend (book)); + ldap = bl->priv->ldap; + + /* XXX use ldap_search */ + + if (LDAP_SUCCESS == ldap_error) { + /* success */ + return g_strdup (""); + } + else { + return g_strdup (""); + } +} + +static void +pas_backend_ldap_load_uri (PASBackend *backend, + const char *uri) +{ + PASBackendLDAP *bl = PAS_BACKEND_LDAP (backend); + LDAPURLDesc *lud; + int ldap_error; + + g_assert (bl->priv->connected == FALSE); + +#if 0 + ldap_error = ldap_url_parse (uri, &lud); + if (LDAP_SUCCESS == ldap_error) { + bl->priv->ldap = ldap_open (lud->lud_host, lud->lud_port); + if (NULL != bl->priv->ldap) + bl->priv->connected = TRUE; + else + g_warning ("pas_backend_ldap_load_uri failed for '%s' (error %s)\n", + uri, ldap_err2string(ldap_error)); + + ldap_free_urldesc(lud); + } + else { + g_warning ("pas_backend_ldap_load_uri failed for '%s' (error %s)\n", + uri, ldap_err2string(ldap_error)); + } +#else + bl->priv->ldap = ldap_init ("ldap.bigfoot.com", 389); + if (NULL != bl->priv->ldap) + bl->priv->connected = TRUE; + else + g_warning ("pas_backend_ldap_load_uri failed for '%s' (error %s)\n", + uri, ldap_err2string(ldap_error)); + + ldap_bind_s(bl->priv->ldap, NULL /*binddn*/, NULL /*passwd*/, LDAP_AUTH_SIMPLE); + +#endif +} + +static void +pas_backend_ldap_add_client (PASBackend *backend, + Evolution_BookListener listener) +{ + PASBackendLDAP *bl; + PASBook *book; + + g_assert (backend != NULL); + g_assert (PAS_IS_BACKEND_LDAP (backend)); + + bl = PAS_BACKEND_LDAP (backend); + + book = pas_book_new ( + backend, listener, + pas_backend_ldap_get_vcard); + + g_assert (book != NULL); + + gtk_signal_connect (GTK_OBJECT (book), "destroy", + pas_backend_ldap_book_destroy_cb, NULL); + + gtk_signal_connect (GTK_OBJECT (book), "requests_queued", + pas_backend_ldap_process_client_requests, NULL); + + bl->priv->clients = g_list_prepend ( + bl->priv->clients, book); + + if (bl->priv->connected) { + pas_book_respond_open ( + book, Evolution_BookListener_Success); + } else { + /* Open the book. */ + pas_book_respond_open ( + book, Evolution_BookListener_Success); + } +} + +static void +pas_backend_ldap_remove_client (PASBackend *backend, + PASBook *book) +{ + g_return_if_fail (backend != NULL); + g_return_if_fail (PAS_IS_BACKEND (backend)); + g_return_if_fail (book != NULL); + g_return_if_fail (PAS_IS_BOOK (book)); + + g_warning ("pas_backend_ldap_remove_client: Unimplemented!\n"); +} + +static gboolean +pas_backend_ldap_construct (PASBackendLDAP *backend) +{ + g_assert (backend != NULL); + g_assert (PAS_IS_BACKEND_LDAP (backend)); + + if (! pas_backend_construct (PAS_BACKEND (backend))) + return FALSE; + + return TRUE; +} + +/** + * pas_backend_ldap_new: + */ +PASBackend * +pas_backend_ldap_new (void) +{ + PASBackendLDAP *backend; + + backend = gtk_type_new (pas_backend_ldap_get_type ()); + + if (! pas_backend_ldap_construct (backend)) { + gtk_object_unref (GTK_OBJECT (backend)); + + return NULL; + } + + return PAS_BACKEND (backend); +} + +static void +pas_backend_ldap_destroy (GtkObject *object) +{ + GTK_OBJECT_CLASS (pas_backend_ldap_parent_class)->destroy (object); +} + +static void +pas_backend_ldap_class_init (PASBackendLDAPClass *klass) +{ + GtkObjectClass *object_class = (GtkObjectClass *) klass; + PASBackendClass *parent_class; + + pas_backend_ldap_parent_class = gtk_type_class (pas_backend_get_type ()); + + parent_class = PAS_BACKEND_CLASS (klass); + + /* Set the virtual methods. */ + parent_class->load_uri = pas_backend_ldap_load_uri; + parent_class->add_client = pas_backend_ldap_add_client; + parent_class->remove_client = pas_backend_ldap_remove_client; + + object_class->destroy = pas_backend_ldap_destroy; +} + +static void +pas_backend_ldap_init (PASBackendLDAP *backend) +{ + PASBackendLDAPPrivate *priv; + + priv = g_new0 (PASBackendLDAPPrivate, 1); + priv->connected = FALSE; + priv->clients = NULL; + + backend->priv = priv; +} + +/** + * pas_backend_ldap_get_type: + */ +GtkType +pas_backend_ldap_get_type (void) +{ + static GtkType type = 0; + + if (! type) { + GtkTypeInfo info = { + "PASBackendLDAP", + sizeof (PASBackendLDAP), + sizeof (PASBackendLDAPClass), + (GtkClassInitFunc) pas_backend_ldap_class_init, + (GtkObjectInitFunc) pas_backend_ldap_init, + NULL, /* reserved 1 */ + NULL, /* reserved 2 */ + (GtkClassInitFunc) NULL + }; + + type = gtk_type_unique (pas_backend_get_type (), &info); + } + + return type; +} diff --git a/addressbook/backend/pas/pas-backend-ldap.h b/addressbook/backend/pas/pas-backend-ldap.h new file mode 100644 index 0000000000..fa6d2295d8 --- /dev/null +++ b/addressbook/backend/pas/pas-backend-ldap.h @@ -0,0 +1,32 @@ +/* + * Copyright 2000, Helix Code, Inc. + */ + +#ifndef __PAS_BACKEND_LDAP_H__ +#define __PAS_BACKEND_LDAP_H__ + +#include <libgnome/gnome-defs.h> +#include <pas-backend.h> + +typedef struct _PASBackendLDAPPrivate PASBackendLDAPPrivate; + +typedef struct { + PASBackend parent_object; + PASBackendLDAPPrivate *priv; +} PASBackendLDAP; + +typedef struct { + PASBackendClass parent_class; +} PASBackendLDAPClass; + +PASBackend *pas_backend_ldap_new (void); +GtkType pas_backend_ldap_get_type (void); + +#define PAS_BACKEND_LDAP_TYPE (pas_backend_ldap_get_type ()) +#define PAS_BACKEND_LDAP(o) (GTK_CHECK_CAST ((o), PAS_BACKEND_LDAP_TYPE, PASBackendLDAP)) +#define PAS_BACKEND_LDAP_CLASS(k) (GTK_CHECK_CLASS_CAST((k), PAS_BACKEND_TYPE, PASBackendLDAPClass)) +#define PAS_IS_BACKEND_LDAP(o) (GTK_CHECK_TYPE ((o), PAS_BACKEND_LDAP_TYPE)) +#define PAS_IS_BACKEND_LDAP_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), PAS_BACKEND_LDAP_TYPE)) + +#endif /* ! __PAS_BACKEND_LDAP_H__ */ + |