aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNat Friedman <nat@src.gnome.org>2000-01-18 11:31:07 +0800
committerNat Friedman <nat@src.gnome.org>2000-01-18 11:31:07 +0800
commit2f1705c6c0d747e708a34b089c4b6ebfc7832022 (patch)
tree1b94d61159ccf0ec4108f98214680850cc5ac350
parente63f053c3e341251c123c72587e930228b781c67 (diff)
downloadgsoc2013-evolution-2f1705c6c0d747e708a34b089c4b6ebfc7832022.tar.gz
gsoc2013-evolution-2f1705c6c0d747e708a34b089c4b6ebfc7832022.tar.zst
gsoc2013-evolution-2f1705c6c0d747e708a34b089c4b6ebfc7832022.zip
A precommit so Federico can see.
svn path=/trunk/; revision=1584
-rw-r--r--addressbook/backend/ebook/Makefile.am52
-rw-r--r--addressbook/backend/ebook/e-book-listener.c271
-rw-r--r--addressbook/backend/ebook/e-book-listener.h65
-rw-r--r--addressbook/backend/ebook/e-book.c316
-rw-r--r--addressbook/backend/ebook/e-book.h106
-rw-r--r--addressbook/backend/ebook/e-card-cursor.h47
-rw-r--r--addressbook/backend/ebook/e-card.h51
-rw-r--r--addressbook/backend/idl/Makefile.am6
-rw-r--r--addressbook/backend/idl/addressbook.idl71
-rw-r--r--addressbook/backend/pas/Makefile.am49
-rw-r--r--addressbook/backend/pas/TODO2
-rw-r--r--addressbook/backend/pas/pas-backend.c148
-rw-r--r--addressbook/backend/pas/pas-backend.h69
-rw-r--r--addressbook/backend/pas/pas-book-factory.c488
-rw-r--r--addressbook/backend/pas/pas-book-factory.h45
-rw-r--r--addressbook/backend/pas/wombat.gnorba5
16 files changed, 1791 insertions, 0 deletions
diff --git a/addressbook/backend/ebook/Makefile.am b/addressbook/backend/ebook/Makefile.am
new file mode 100644
index 0000000000..e9e974b704
--- /dev/null
+++ b/addressbook/backend/ebook/Makefile.am
@@ -0,0 +1,52 @@
+corbadir = $(sysconfdir)/CORBA/servers
+
+CORBA_SOURCE = \
+ addressbook.h \
+ addressbook-common.c \
+ addressbook-stubs.c \
+ addressbook-skels.c
+
+idls = \
+ ../idl/addressbook.idl
+
+idl_flags = `$(GNOME_CONFIG) --cflags idl`
+
+$(CORBA_SOURCE): $(idls)
+ $(ORBIT_IDL) ../idl/addressbook.idl $(idl_flags)
+
+INCLUDES = \
+ -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
+ -DG_LOG_DOMAIN=\"EBook\" \
+ -I$(srcdir) -I$(top_srcdir) \
+ -I. \
+ -I.. \
+ -I$(top_builddir) \
+ -I$(includedir) \
+ $(GNOME_INCLUDEDIR)
+
+gnome_libs = \
+ $(GNOME_LIBDIR) \
+ $(GNOMEUI_LIBS) \
+ $(GNOMEGNORBA_LIBS) \
+ $(INTLLIBS)
+
+ebook_libs = \
+ libebook.la \
+ $(gnome_libs)
+
+lib_LTLIBRARIES = libebook.la
+
+libebook_la_SOURCES = \
+ $(CORBA_SOURCE) \
+ e-book-listener.c \
+ e-book.c
+
+libebookincludedir = $(includedir)/backend
+
+libebookinclude_HEADERS = \
+ e-book.h \
+ e-book-listener.h \
+ e-card.h
+
+BUILT_SOURCES = $(CORBA_SOURCE)
+CLEANFILES += $(BUILT_SOURCES)
diff --git a/addressbook/backend/ebook/e-book-listener.c b/addressbook/backend/ebook/e-book-listener.c
new file mode 100644
index 0000000000..b0e10fc90c
--- /dev/null
+++ b/addressbook/backend/ebook/e-book-listener.c
@@ -0,0 +1,271 @@
+/*
+ * Author:
+ * Nat Friedman (nat@helixcode.com)
+ *
+ * Copyright 2000, Helix Code, Inc.
+ */
+
+#include <e-book-listener.h>
+
+static GnomeObjectClass *e_book_listener_parent_class;
+POA_Evolution_BookListener__vepv e_book_listener_vepv;
+
+static EBookStatus
+e_book_listener_convert_status (const Evolution_BookListener_CallStatus status)
+{
+ switch (status) {
+
+ case Evolution_BookListener_RepositoryOffline:
+ return E_BOOK_STATUS_REPOSITORY_OFFLINE;
+ case Evolution_BookListener_PermissionDenied:
+ return E_BOOK_STATUS_PERMISSION_DENIED;
+ case Evolution_BookListener_CardNotFound:
+ return E_BOOK_STATUS_CARD_NOT_FOUND;
+ default:
+ g_warning ("e_book_listener_convert_status: Unknown status "
+ "from card server: %d\n", (int) status);
+ return E_BOOK_STATUS_UNKNOWN;
+
+ }
+}
+
+static EBookListener *
+e_book_listener_construct (EBookListener *listener, EBook *book)
+{
+ POA_Evolution_BookListener *servant;
+ CORBA_Environment ev;
+ CORBA_Object obj;
+
+ g_assert (listener != NULL);
+ g_assert (E_IS_BOOK_LISTENER (listener));
+ g_assert (book != NULL);
+ g_assert (E_IS_BOOK (book));
+
+ listener->book = book;
+
+ servant = (POA_Evolution_BookListener *) g_new0 (GnomeObjectServant, 1);
+ servant->vepv = &e_book_listener_vepv;
+
+ CORBA_exception_init (&ev);
+
+ POA_Evolution_BookListener__init ((PortableServer_Servant) servant, &ev);
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_free (servant);
+ CORBA_exception_free (&ev);
+
+ return NULL;
+ }
+
+ CORBA_exception_free (&ev);
+
+ obj = gnome_object_activate_servant (GNOME_OBJECT (listener), servant);
+ if (obj == CORBA_OBJECT_NIL) {
+ g_free (servant);
+
+ return NULL;
+ }
+
+ gnome_object_construct (GNOME_OBJECT (listener), obj);
+
+ return listener;
+}
+
+/**
+ * e_book_listener_new:
+ */
+EBookListener *
+e_book_listener_new (EBook *book)
+{
+ EBookListener *listener;
+ EBookListener *retval;
+
+ g_return_val_if_fail (book != NULL, NULL);
+ g_return_val_if_fail (E_IS_BOOK (book), NULL);
+
+ listener = gtk_type_new (E_BOOK_LISTENER_TYPE);
+
+ retval = e_book_listener_construct (listener, book);
+
+ if (retval == NULL) {
+ g_warning ("e_book_listener_new: Error constructing "
+ "EBookListener!\n");
+ gtk_object_unref (GTK_OBJECT (listener));
+ return NULL;
+ }
+
+ return retval;
+}
+
+static void
+impl_BookListener_respond_create_card (PortableServer_Servant servant,
+ const Evolution_BookListener_CallStatus status,
+ CORBA_Environment *ev)
+{
+ EBookListener *listener = E_BOOK_LISTENER (gnome_object_from_servant (servant));
+
+ if (listener->create_response == NULL)
+ return;
+
+ (listener->create_response) (listener->book,
+ e_book_listener_convert_status (status),
+ listener->closure);
+}
+
+static void
+impl_BookListener_respond_remove_card (PortableServer_Servant servant,
+ const Evolution_BookListener_CallStatus status,
+ CORBA_Environment *ev)
+{
+ EBookListener *listener = E_BOOK_LISTENER (gnome_object_from_servant (servant));
+
+ if (listener->remove_response == NULL)
+ return;
+
+ (listener->remove_response) (listener->book,
+ e_book_listener_convert_status (status),
+ listener->closure);
+}
+
+static void
+impl_BookListener_respond_modify_card (PortableServer_Servant servant,
+ const Evolution_BookListener_CallStatus status,
+ CORBA_Environment *ev)
+{
+ EBookListener *listener = E_BOOK_LISTENER (gnome_object_from_servant (servant));
+
+ if (listener->modify_response == NULL)
+ return;
+
+ (listener->modify_response) (listener->book,
+ e_book_listener_convert_status (status),
+ listener->closure);
+}
+
+static void
+impl_BookListener_report_open_book_progress (PortableServer_Servant servant,
+ const CORBA_char *status_message,
+ const CORBA_short percent,
+ CORBA_Environment *ev)
+{
+ EBookListener *listener = E_BOOK_LISTENER (gnome_object_from_servant (servant));
+
+ if (listener->open_progress == NULL)
+ return;
+
+ (listener->open_progress) (listener->book,
+ status_message,
+ percent,
+ listener->closure);
+}
+
+static void
+impl_BookListener_respond_open_book (PortableServer_Servant servant,
+ const Evolution_BookListener_CallStatus status,
+ const Evolution_Book book,
+ CORBA_Environment *ev)
+{
+ EBookListener *listener = E_BOOK_LISTENER (gnome_object_from_servant (servant));
+
+ if (listener->open_response == NULL)
+ return;
+
+ (listener->open_response) (listener->book,
+ e_book_listener_convert_status (status),
+ book,
+ listener->closure);
+}
+
+
+static void
+impl_BookListener_report_connection_status (PortableServer_Servant servant,
+ const CORBA_boolean connected,
+ CORBA_Environment *ev)
+{
+ EBookListener *listener = E_BOOK_LISTENER (gnome_object_from_servant (servant));
+
+ if (listener->connect_status == NULL)
+ return;
+
+ (listener->connect_status) (listener->book, connected, listener->closure);
+}
+
+
+static void
+e_book_listener_init (EBook *listener)
+{
+}
+
+static void
+e_book_listener_destroy (GtkObject *object)
+{
+ EBookListener *listener = E_BOOK_LISTENER (object);
+ CORBA_Environment ev;
+
+ CORBA_exception_init (&ev);
+
+ GTK_OBJECT_CLASS (e_book_listener_parent_class)->destroy (object);
+}
+
+POA_Evolution_BookListener__epv *
+e_book_listener_get_epv (void)
+{
+ POA_Evolution_BookListener__epv *epv;
+
+ epv = g_new0 (POA_Evolution_BookListener__epv, 1);
+
+ epv->report_open_book_progress = impl_BookListener_report_open_book_progress;
+ epv->respond_open_book = impl_BookListener_respond_open_book;
+
+ epv->respond_create_card = impl_BookListener_respond_create_card;
+ epv->respond_remove_card = impl_BookListener_respond_remove_card;
+ epv->respond_modify_card = impl_BookListener_respond_modify_card;
+
+ epv->report_connection_status = impl_BookListener_report_connection_status;
+
+ return epv;
+}
+
+static void
+e_book_listener_corba_class_init (void)
+{
+ e_book_listener_vepv.GNOME_Unknown_epv = gnome_object_get_epv ();
+ e_book_listener_vepv.Evolution_BookListener_epv = e_book_listener_get_epv ();
+}
+
+static void
+e_book_listener_class_init (EBookListenerClass *klass)
+{
+ GtkObjectClass *object_class = (GtkObjectClass *) klass;
+
+ e_book_listener_parent_class = gtk_type_class (gnome_object_get_type ());
+
+ object_class->destroy = e_book_listener_destroy;
+
+ e_book_listener_corba_class_init ();
+}
+
+/**
+ * e_book_listener_get_type:
+ */
+GtkType
+e_book_listener_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (! type) {
+ GtkTypeInfo info = {
+ "EBookListener",
+ sizeof (EBookListener),
+ sizeof (EBookListenerClass),
+ (GtkClassInitFunc) e_book_listener_class_init,
+ (GtkObjectInitFunc) e_book_listener_init,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (gnome_object_get_type (), &info);
+ }
+
+ return type;
+}
diff --git a/addressbook/backend/ebook/e-book-listener.h b/addressbook/backend/ebook/e-book-listener.h
new file mode 100644
index 0000000000..71004a966a
--- /dev/null
+++ b/addressbook/backend/ebook/e-book-listener.h
@@ -0,0 +1,65 @@
+/*
+ * A client-side GtkObject which exposes the
+ * Evolution:BookListener interface.
+ *
+ * Author:
+ * Nat Friedman (nat@helixcode.com)
+ *
+ * Copyright 2000, Helix Code, Inc.
+ */
+
+#ifndef __E_BOOK_LISTENER_H__
+#define __E_BOOK_LISTENER_H__
+
+#include <libgnome/gnome-defs.h>
+
+#include <bonobo/gnome-object.h>
+#include <e-book.h>
+
+#include <addressbook.h>
+
+BEGIN_GNOME_DECLS
+
+typedef struct _EBookListener EBookListener;
+
+typedef void (*EBookListenerRespondOpenBookCallback) (EBook *book,
+ EBookStatus status,
+ Evolution_Book corba_book,
+ gpointer closure);
+
+typedef void (*EBookListenerConnectionStatusCallback) (EBook *book,
+ gboolean connected,
+ gpointer closure);
+
+struct _EBookListener {
+ GnomeObject parent;
+
+ EBook *book;
+
+ gpointer closure;
+
+ EBookCallback create_response;
+ EBookCallback remove_response;
+ EBookCallback modify_response;
+
+ EBookOpenProgressCallback open_progress;
+ EBookListenerRespondOpenBookCallback open_response;
+ EBookListenerConnectionStatusCallback connect_status;
+};
+
+typedef struct {
+ GnomeObjectClass parent;
+} EBookListenerClass;
+
+EBookListener *e_book_listener_new (EBook *book);
+GtkType e_book_listener_get_type (void);
+
+#define E_BOOK_LISTENER_TYPE (e_book_listener_get_type ())
+#define E_BOOK_LISTENER(o) (GTK_CHECK_CAST ((o), E_BOOK_LISTENER_TYPE, EBookListener))
+#define E_BOOK_LISTENER_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_BOOK_LISTENER_TYPE, EBookListenerClass))
+#define E_IS_BOOK_LISTENER(o) (GTK_CHECK_TYPE ((o), E_BOOK_LISTENER_TYPE))
+#define E_IS_BOOK_LISTENER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_BOOK_LISTENER_TYPE))
+
+END_GNOME_DECLS
+
+#endif /* ! __E_BOOK_LISTENER_H__ */
diff --git a/addressbook/backend/ebook/e-book.c b/addressbook/backend/ebook/e-book.c
new file mode 100644
index 0000000000..80d5173231
--- /dev/null
+++ b/addressbook/backend/ebook/e-book.c
@@ -0,0 +1,316 @@
+/*
+ * The Evolution addressbook client object.
+ *
+ * Author:
+ * Nat Friedman (nat@helixcode.com)
+ *
+ * Copyright 1999, 2000, Helix Code, Inc.
+ */
+
+#include <addressbook.h>
+#include <e-card-cursor.h>
+#include <e-book-listener.h>
+#include <e-book.h>
+
+#include <gtk/gtksignal.h>
+#include <gtk/gtkmarshal.h>
+
+GnomeObjectClass *e_book_parent_class;
+
+#define CARDSERVER_GOAD_ID "FIXME"
+
+struct _EBookPrivate {
+ Evolution_BookFactory book_factory;
+ EBookListener *listener;
+
+ gboolean operation_pending;
+
+ EBookCallback open_response;
+ gpointer closure;
+};
+
+enum {
+ CARD_CHANGED,
+ CARD_REMOVED,
+ CARD_ADDED,
+ LINK_STATUS,
+ LAST_SIGNAL
+};
+
+static guint e_book_signals [LAST_SIGNAL];
+
+static EBook *
+e_book_construct (EBook *book,
+ const char *uri,
+ EBookOpenProgressCallback progress_cb,
+ EBookCallback open_response,
+ gpointer closure)
+{
+ CORBA_Environment ev;
+
+ g_return_val_if_fail (book != NULL, NULL);
+ g_assert (uri != NULL);
+
+ /*
+ * Connect to the Personal Addressbook Server.
+ */
+ book->priv->book_factory = (Evolution_BookFactory)
+ goad_server_activate_with_id (NULL, CARDSERVER_GOAD_ID, 0, NULL);
+
+ if (book->priv->book_factory == CORBA_OBJECT_NIL) {
+ g_warning ("e_book_construct: Could not obtain a handle "
+ "to the Personal Addressbook Server!\n");
+ return NULL;
+ }
+
+ /*
+ * Create our local BookListener interface.
+ */
+ book->priv->listener = e_book_listener_new (book);
+ if (book->priv->listener == NULL) {
+ g_warning ("e_book_construct: Could not create EBookListener!\n");
+ return NULL;
+ }
+
+ /*
+ * Setup the callback for getting book-opening progress
+ * notifications.
+ */
+ book->priv->listener->open_progress = progress_cb;
+ book->priv->listener->closure = closure;
+ book->priv->open_response = open_response;
+ book->priv->closure = closure;
+ book->priv->operation_pending = TRUE;
+
+ /*
+ * Load the addressbook into the PAS.
+ */
+ CORBA_exception_init (&ev);
+
+ Evolution_BookFactory_open_book (
+ book->priv->book_factory, uri,
+ gnome_object_corba_objref (GNOME_OBJECT (book->priv->listener)),
+ &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("e_book_construct: CORBA exception while opening addressbook!\n");
+ CORBA_exception_free (&ev);
+ return NULL;
+ }
+
+ CORBA_exception_free (&ev);
+}
+
+/**
+ * e_book_new:
+ */
+EBook *
+e_book_new (const char *uri,
+ EBookOpenProgressCallback progress_cb,
+ EBookCallback open_response,
+ gpointer closure)
+{
+ EBook *book;
+ EBook *retval;
+
+ g_return_val_if_fail (uri != NULL, NULL);
+
+ book = gtk_type_new (E_BOOK_TYPE);
+
+ retval = e_book_construct (book, uri, progress_cb,
+ open_response, closure);
+
+ if (retval == NULL) {
+ g_warning ("e_book_new: Could not construct EBook!\n");
+ gtk_object_unref (GTK_OBJECT (book));
+
+ return NULL;
+ }
+
+ return retval;
+}
+
+static void
+e_book_init (EBook *book)
+{
+ book->priv = g_new0 (EBookPrivate, 1);
+}
+
+static void
+e_book_destroy (GtkObject *object)
+{
+ EBook *book = E_BOOK (object);
+ CORBA_Environment ev;
+
+ gtk_object_unref (GTK_OBJECT (book->priv->listener));
+
+ CORBA_exception_init (&ev);
+
+ CORBA_Object_release (book->priv->book_factory, &ev);
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("EBook: Exception while releasing BookFactory\n");
+
+ CORBA_exception_free (&ev);
+ CORBA_exception_init (&ev);
+ }
+
+ g_free (book->priv);
+
+ GTK_OBJECT_CLASS (e_book_parent_class)->destroy (object);
+}
+
+static void
+e_book_class_init (EBookClass *klass)
+{
+ GtkObjectClass *object_class = (GtkObjectClass *) klass;
+
+ e_book_parent_class = gtk_type_class (gtk_object_get_type ());
+
+ e_book_signals [CARD_CHANGED] =
+ gtk_signal_new ("card_changed",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EBookClass, card_changed),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ e_book_signals [CARD_ADDED] =
+ gtk_signal_new ("card_added",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EBookClass, card_changed),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ e_book_signals [CARD_REMOVED] =
+ gtk_signal_new ("card_removed",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EBookClass, card_changed),
+ gtk_marshal_NONE__POINTER,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_POINTER);
+
+ e_book_signals [LINK_STATUS] =
+ gtk_signal_new ("link_status",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EBookClass, link_status),
+ gtk_marshal_NONE__BOOL,
+ GTK_TYPE_NONE, 1,
+ GTK_TYPE_BOOL);
+
+ gtk_object_class_add_signals (object_class, e_book_signals,
+ LAST_SIGNAL);
+
+ object_class->destroy = e_book_destroy;
+}
+
+/* Fetching cards */
+ECard *
+e_book_get_card (EBook *book,
+ char *id)
+{
+ g_return_val_if_fail (book != NULL, NULL);
+ g_return_val_if_fail (E_IS_BOOK (book), NULL);
+
+ if (book->priv->operation_pending) {
+ g_warning ("EBook: Operation attempted on busy EBook!\n");
+ return;
+ }
+}
+
+char *
+e_book_get_vcard (EBook *book,
+ char *id)
+{
+}
+
+ECardCursor *
+e_book_query (EBook *book,
+ char *query)
+{
+}
+
+/* Deleting cards. */
+void
+e_book_remove_card (EBook *book,
+ ECard *card,
+ EBookCallback cb,
+ gpointer closure)
+{
+}
+
+void
+e_book_remove_card_by_id (EBook *book,
+ char *id,
+ EBookCallback cb,
+ gpointer closure)
+
+{
+}
+
+/* Adding cards. */
+void
+e_book_add_card (EBook *book,
+ ECard *card,
+ EBookCallback cb,
+ gpointer closure)
+{
+}
+
+void
+e_book_add_vcard (EBook *book,
+ char *vcard,
+ char *id,
+ EBookCallback cb,
+ gpointer closure)
+{
+}
+
+
+/* Modifying cards. */
+void
+e_book_commit_card (EBook *book,
+ ECard *card,
+ EBookCallback cb,
+ gpointer closure)
+{
+}
+
+void
+e_book_commit_vcard (EBook *book,
+ char *vcard,
+ EBookCallback cb,
+ gpointer closure)
+{
+}
+
+
+/**
+ * e_book_get_type:
+ */
+GtkType
+e_book_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (! type) {
+ GtkTypeInfo info = {
+ "EBook",
+ sizeof (EBook),
+ sizeof (EBookClass),
+ (GtkClassInitFunc) e_book_class_init,
+ (GtkObjectInitFunc) e_book_init,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (gtk_object_get_type (), &info);
+ }
+
+ return type;
+}
diff --git a/addressbook/backend/ebook/e-book.h b/addressbook/backend/ebook/e-book.h
new file mode 100644
index 0000000000..892f99fb53
--- /dev/null
+++ b/addressbook/backend/ebook/e-book.h
@@ -0,0 +1,106 @@
+/*
+ * The Evolution addressbook client object.
+ *
+ * Author:
+ * Nat Friedman (nat@helixcode.com)
+ *
+ * Copyright 1999, 2000, Helix Code, Inc.
+ */
+
+#ifndef __E_BOOK_H__
+#define __E_BOOK_H__
+
+#include <libgnome/gnome-defs.h>
+
+#include <e-card.h>
+
+BEGIN_GNOME_DECLS
+
+typedef enum {
+ E_BOOK_STATUS_SUCCESS,
+ E_BOOK_STATUS_UNKNOWN,
+ E_BOOK_STATUS_REPOSITORY_OFFLINE,
+ E_BOOK_STATUS_PERMISSION_DENIED,
+ E_BOOK_STATUS_CARD_NOT_FOUND
+} EBookStatus;
+
+typedef struct _EBookPrivate EBookPrivate;
+
+typedef struct {
+ GtkObject parent;
+ EBookPrivate *priv;
+} EBook;
+
+typedef struct {
+ GtkObjectClass parent;
+
+ /*
+ * Signals.
+ */
+ void (* card_changed) (const char *id);
+ void (* card_removed) (const char *id);
+ void (* card_added) (const char *id);
+ void (* link_status) (gboolean connected);
+} EBookClass;
+
+/* Callbacks for asynchronous functions. */
+typedef void (*EBookCallback) (EBook *book, EBookStatus status, gpointer closure);
+typedef void (*EBookOpenProgressCallback) (EBook *book,
+ const char *status_message,
+ short percent,
+ gpointer closure);
+
+
+/* Creating a new addressbook. */
+EBook *e_book_new (const char *uri,
+ EBookOpenProgressCallback progress_cb,
+ EBookCallback open_response,
+ gpointer closure);
+GtkType e_book_get_type (void);
+
+/* Fetching cards. */
+ECard *e_book_get_card (EBook *book,
+ char *id);
+char *e_book_get_vcard (EBook *book,
+ char *id);
+
+/* Deleting cards. */
+void e_book_remove_card (EBook *book,
+ ECard *card,
+ EBookCallback cb,
+ gpointer closure);
+void e_book_remove_card_by_id (EBook *book,
+ char *id,
+ EBookCallback cb,
+ gpointer closure);
+
+/* Adding cards. */
+void e_book_add_card (EBook *book,
+ ECard *card,
+ EBookCallback cb,
+ gpointer closure);
+void e_book_add_vcard (EBook *book,
+ char *vcard,
+ char *id,
+ EBookCallback cb,
+ gpointer closure);
+
+/* Modifying cards. */
+void e_book_commit_card (EBook *book,
+ ECard *card,
+ EBookCallback cb,
+ gpointer closure);
+void e_book_commit_vcard (EBook *book,
+ char *vcard,
+ EBookCallback cb,
+ gpointer closure);
+
+#define E_BOOK_TYPE (e_book_get_type ())
+#define E_BOOK(o) (GTK_CHECK_CAST ((o), E_BOOK_TYPE, EBook))
+#define E_BOOK_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_BOOK_TYPE, EBookClass))
+#define E_IS_BOOK(o) (GTK_CHECK_TYPE ((o), E_BOOK_TYPE))
+#define E_IS_BOOK_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_BOOK_TYPE))
+
+END_GNOME_DECLS
+
+#endif /* ! __E_BOOK_H__ */
diff --git a/addressbook/backend/ebook/e-card-cursor.h b/addressbook/backend/ebook/e-card-cursor.h
new file mode 100644
index 0000000000..5477a4f615
--- /dev/null
+++ b/addressbook/backend/ebook/e-card-cursor.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * Author:
+ * Nat Friedman (nat@helixcode.com)
+ *
+ * Copyright 2000, Helix Code, Inc.
+ */
+
+#include <gtk/gtkobject.h>
+#include <libgnome/gnome-defs.h>
+
+#include <e-book.h>
+
+#ifndef __E_CARD_CURSOR_H__
+#define __E_CARD_CURSOR_H__
+
+BEGIN_GNOME_DECLS
+
+typedef struct _ECardCursorPrivate ECardCursorPrivate;
+
+typedef struct {
+ GtkObject parent;
+ ECardCursorPrivate *priv;
+} ECardCursor;
+
+typedef struct {
+ GtkObjectClass parent;
+} ECardCursorClass;
+
+/* Creating a new addressbook. */
+ECardCursor *e_card_cursor_new (EBook *book,
+ Evolution_CardCursor corba_cursor);
+GtkType e_card_cursor_get_type (void);
+
+/* Fetching cards. */
+int e_card_cursor_get_length (ECardCursor *cursor);
+ECard *e_card_cursor_get_nth (ECardCursor *cursor,
+ int nth);
+#define E_CARD_CURSOR_TYPE (e_card_cursor_get_type ())
+#define E_CARD_CURSOR(o) (GTK_CHECK_CAST ((o), E_CARD_CURSOR_TYPE, ECardCursor))
+#define E_CARD_CURSOR_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_CARD_CURSOR_TYPE, ECardCursorClass))
+#define E_IS_CARD_CURSOR(o) (GTK_CHECK_TYPE ((o), E_CARD_CURSOR_TYPE))
+#define E_IS_CARD_CURSOR_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CARD_CURSOR_TYPE))
+
+END_GNOME_DECLS
+
+#endif /* ! __E_CARD_CURSOR_H__ */
diff --git a/addressbook/backend/ebook/e-card.h b/addressbook/backend/ebook/e-card.h
new file mode 100644
index 0000000000..7959377695
--- /dev/null
+++ b/addressbook/backend/ebook/e-card.h
@@ -0,0 +1,51 @@
+/*
+ * Author:
+ * Nat Friedman (nat@helixcode.com)
+ *
+ * Copyright 1999, Helix Code, Inc.
+ */
+
+#ifndef __E_CARD_H__
+#define __E_CARD_H__
+
+#include <gtk/gtkobject.h>
+#include <libgnome/gnome-defs.h>
+#include <ebook/e-card-fields.h>
+
+BEGIN_GNOME_DECLS
+
+typedef struct _ECardPrivate ECardPrivate;
+
+typedef struct {
+ GtkObject parent;
+ ECardPrivate *priv;
+} ECard;
+
+typedef struct {
+ GtkObjectClass parent;
+} ECardClass;
+
+ECard *e_card_new (void);
+GtkType e_card_get_type (void);
+
+char *e_card_get_string (ECard *card,
+ char *field);
+void e_card_set_string (ECard *card,
+ char *field,
+ char *value);
+
+gboolean e_card_get_boolean (ECard *card,
+ char *field);
+void e_card_set_boolean (ECard *card,
+ char *field,
+ gboolean value);
+
+#define E_CARD_TYPE (e_card_get_type ())
+#define E_CARD(o) (GTK_CHECK_CAST ((o), E_CARD_TYPE, ECard))
+#define E_CARD_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_CARD_TYPE, ECardClass))
+#define E_IS_CARD(o) (GTK_CHECK_TYPE ((o), E_CARD_TYPE))
+#define E_IS_CARD_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CARD_TYPE))
+
+END_GNOME_DECLS
+
+#endif /* ! __E_CARD_H__ */
diff --git a/addressbook/backend/idl/Makefile.am b/addressbook/backend/idl/Makefile.am
new file mode 100644
index 0000000000..db61d2c30c
--- /dev/null
+++ b/addressbook/backend/idl/Makefile.am
@@ -0,0 +1,6 @@
+idldir = $(datadir)/idl
+
+idl_DATA = \
+ addressbook.idl
+
+EXTRA_DIST = $(idl_DATA)
diff --git a/addressbook/backend/idl/addressbook.idl b/addressbook/backend/idl/addressbook.idl
new file mode 100644
index 0000000000..a8f6a89f59
--- /dev/null
+++ b/addressbook/backend/idl/addressbook.idl
@@ -0,0 +1,71 @@
+/*
+ *
+ * Author:
+ * Nat Friedman (nat@helixcode.com)
+ *
+ * Copyright 2000, Helix Code, Inc.
+ */
+
+#include <gnome-unknown.idl>
+
+module Evolution {
+
+ typedef string CardId;
+
+ interface CardCursor {
+ };
+
+ interface Book : GNOME::Unknown {
+
+ /*
+ * Fetching cards in the addresbook.
+ */
+ string get_vcard (in CardId id);
+
+ /*
+ * Adding and deleting cards in the book.
+ */
+ void create_card (in string vcard);
+ void remove_card (in CardId Id);
+
+ /*
+ * Modifying cards in the addressbook.
+ */
+ void modify_card (in CardId id, in string vcard);
+ };
+
+ interface BookListener : GNOME::Unknown {
+
+ enum CallStatus {
+ RepositoryOffline,
+ PermissionDenied,
+ CardNotFound,
+ ProtocolNotSupported
+ };
+
+ void respond_create_card (in CallStatus status);
+
+ void respond_remove_card (in CallStatus status);
+
+ void respond_modify_card (in CallStatus status);
+
+ void report_open_book_progress (in string status_message, in short percent);
+
+ void respond_open_book (in CallStatus status, in Book book);
+
+ /**
+ * report_connection_status:
+ *
+ * Used to report changes in the connection to the
+ * contact repository. This is often a response to a
+ * call to check_connection() on the Book, but wombat
+ * is free to report the connection status without
+ * being asked.
+ */
+ void report_connection_status (in boolean connected);
+ };
+
+ interface BookFactory : GNOME::Unknown {
+ void open_book (in string uri, in BookListener listener);
+ };
+};
diff --git a/addressbook/backend/pas/Makefile.am b/addressbook/backend/pas/Makefile.am
new file mode 100644
index 0000000000..220888f431
--- /dev/null
+++ b/addressbook/backend/pas/Makefile.am
@@ -0,0 +1,49 @@
+corbadir = $(sysconfdir)/CORBA/servers
+
+CORBA_SOURCE = \
+ addressbook.h \
+ addressbook-common.c \
+ addressbook-stubs.c \
+ addressbook-skels.c
+
+idls = \
+ ../idl/addressbook.idl
+
+idl_flags = `$(GNOME_CONFIG) --cflags idl`
+
+$(CORBA_SOURCE): $(idls)
+ $(ORBIT_IDL) ../idl/addressbook.idl $(idl_flags)
+
+INCLUDES = \
+ -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
+ -DG_LOG_DOMAIN=\"Wombat\" \
+ -I$(srcdir) -I$(top_srcdir) \
+ -I. \
+ -I.. \
+ -I$(top_builddir) \
+ -I$(includedir) \
+ $(GNOME_INCLUDEDIR)
+
+gnome_libs = \
+ $(GNOME_LIBDIR) \
+ $(GNOMEUI_LIBS) \
+ $(GNOMEGNORBA_LIBS) \
+ $(INTLLIBS)
+
+pas_libs = \
+ libpas.la \
+ $(gnome_libs)
+
+lib_LTLIBRARIES = libpas.la
+
+libpas_la_SOURCES = \
+ $(CORBA_SOURCE) \
+ pas-book-factory.c
+
+libpasincludedir = $(includedir)/backend
+
+libpasinclude_HEADERS = \
+ pas-book-factory.h
+
+BUILT_SOURCES = $(CORBA_SOURCE)
+CLEANFILES += $(BUILT_SOURCES)
diff --git a/addressbook/backend/pas/TODO b/addressbook/backend/pas/TODO
new file mode 100644
index 0000000000..0c77c1b200
--- /dev/null
+++ b/addressbook/backend/pas/TODO
@@ -0,0 +1,2 @@
+* Implement pas_book_factory_activate
+* Authentication \ No newline at end of file
diff --git a/addressbook/backend/pas/pas-backend.c b/addressbook/backend/pas/pas-backend.c
new file mode 100644
index 0000000000..291b101ce6
--- /dev/null
+++ b/addressbook/backend/pas/pas-backend.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2000, Helix Code, Inc.
+ */
+
+#include <gtk/gtkobject.h>
+#include <pas-backend.h>
+
+typedef struct {
+ Evolution_BookListener listener;
+} PASClient;
+
+struct _PASBackendPrivate {
+ gboolean book_loaded;
+ GList *clients;
+ GList *response_queue;
+};
+
+PASBackend *
+pas_backend_new (void)
+{
+ PASBackend *backend;
+
+ backend = gtk_type_new (pas_backend_get_type ());
+
+ return backend;
+}
+
+void
+pas_backend_load_uri (PASBackend *backend,
+ char *uri)
+{
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (PAS_IS_BACKEND (backend));
+ g_return_if_fail (uri != NULL);
+}
+
+/**
+ * pas_backend_add_client:
+ * @backend:
+ * @listener:
+ */
+void
+pas_backend_add_client (PASBackend *backend,
+ Evolution_BookListener listener)
+{
+ PASClient *client;
+
+ g_return_if_fail (backend != NULL);
+ g_return_if_fail (PAS_IS_BACKEND (backend));
+ g_return_if_fail (listener != CORBA_OBJECT_NIL);
+
+ client = g_new0 (PASClient, 1);
+
+ client->listener = listener;
+
+ if (backend->priv->book_loaded) {
+
+ }
+}
+
+
+void
+pas_backend_remove_client (PASBackend *backend,
+ Evolution_BookListener listener)
+{
+}
+
+/* Synchronous operations. */
+char *
+pas_backend_get_vcard (PASBackend *backend,
+ PASBook *book,
+ char *id)
+{
+}
+
+/* Asynchronous operations. */
+
+/**
+ * pas_backend_queue_remove_card:
+ */
+void
+pas_backend_queue_create_card (PASBackend *backend,
+ PASBook *book,
+ char *vcard)
+{
+}
+
+/**
+ * pas_backend_queue_remove_card:
+ */
+void
+pas_backend_queue_remove_card (PASBackend *backend,
+ PASBook *book,
+ char *id)
+{
+}
+
+/**
+ * pas_backend_queue_modify_card:
+ */
+void
+pas_backend_queue_modify_card (PASBackend *backend,
+ PASBook *book,
+ char *id,
+ char *vcard)
+{
+}
+
+static void
+pas_backend_init (PASBackend *backend)
+{
+ PASBackendPrivate *priv;
+
+ priv = g_new0 (PASBackendPrivate, 1);
+ priv->book_loaded = FALSE;
+ priv->clients = NULL;
+}
+
+static void
+pas_backend_class_init (PASBackendClass *klass)
+{
+}
+
+/**
+ * pas_backend_get_type:
+ */
+GtkType
+pas_backend_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (! type) {
+ GtkTypeInfo info = {
+ "PASBackend",
+ sizeof (PASBackend),
+ sizeof (PASBackendClass),
+ (GtkClassInitFunc) pas_backend_class_init,
+ (GtkObjectInitFunc) pas_backend_init,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (gtk_object_get_type (), &info);
+ }
+
+ return type;
+}
diff --git a/addressbook/backend/pas/pas-backend.h b/addressbook/backend/pas/pas-backend.h
new file mode 100644
index 0000000000..fca4ef7d8d
--- /dev/null
+++ b/addressbook/backend/pas/pas-backend.h
@@ -0,0 +1,69 @@
+/*
+ * An abstract class which defines the API to a given backend.
+ * There will be one PASBackend object for every URI which is loaded.
+ *
+ * Two people will call into the PASBackend API:
+ *
+ * 1. The PASBookFactory, when it has been asked to load a book.
+ * It will create a new PASBackend if one is not already running
+ * for the requested URI. It will call pas_backend_add_client to
+ * add a new client to an existing PASBackend server.
+ *
+ * 2. A PASBook, when a client has requested an operation on the
+ * Evolution_Book interface.
+ *
+ * Author:
+ * Nat Friedman (nat@helixcode.com)
+ *
+ * Copyright 2000, Helix Code, Inc.
+ */
+
+#ifndef __PAS_BACKEND_H__
+#define __PAS_BACKEND_H__
+
+typedef struct _PASBackendPrivate PASBackendPrivate;
+
+typedef struct {
+ GtkObject parent_object;
+ PASBackendPrivate *priv;
+} PASBackend;
+
+typedef struct {
+ GtkObjectClass parent_class;
+} PASBackendClass;
+
+PASBackend *pas_backend_new (void);
+void pas_backend_load_uri (PASBackend *backend,
+ char *uri);
+void pas_backend_add_client (PASBackend *backend,
+ Evolution_BookListener listener);
+void pas_backend_remove_client (PASBackend *backend,
+ Evolution_BookListener listener);
+
+/* Synchronous operations. */
+char *pas_backend_get_vcard (PASBackend *backend,
+ PASBook *book,
+ char *id);
+
+/* Asynchronous operations. */
+void pas_backend_queue_create_card (PASBackend *backend,
+ PASBook *book,
+ char *vcard);
+void pas_backend_queue_remove_card (PASBackend *backend,
+ PASBook *book,
+ char *id);
+void pas_backend_queue_modify_card (PASBackend *backend,
+ PASBook *book,
+ char *id,
+ char *vcard);
+
+GtkType pas_backend_get_type (void);
+
+#define PAS_BACKEND_TYPE (pas_backend_get_type ())
+#define PAS_BACKEND(o) (GTK_CHECK_CAST ((o), PAS_BACKEND_TYPE, PASBackend))
+#define PAS_BACKEND_CLASS(k) (GTK_CHECK_CLASS_CAST((k), PAS_BACKEND_TYPE, PASBackendClass))
+#define PAS_IS_BACKEND(o) (GTK_CHECK_TYPE ((o), PAS_BACKEND_TYPE))
+#define PAS_IS_BACKEND_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), PAS_BACKEND_TYPE))
+
+#endif /* ! __PAS_BACKEND_H__ */
+
diff --git a/addressbook/backend/pas/pas-book-factory.c b/addressbook/backend/pas/pas-book-factory.c
new file mode 100644
index 0000000000..55b67f4e7e
--- /dev/null
+++ b/addressbook/backend/pas/pas-book-factory.c
@@ -0,0 +1,488 @@
+/*
+ *
+ * Author:
+ * Nat Friedman (nat@helixcode.com)
+ *
+ * Copyright 2000, Helix Code, Inc.
+ */
+
+#include <addressbook.h>
+#include <pas-book-factory.h>
+
+static GnomeObjectClass *pas_book_factory_parent_class;
+POA_Evolution_BookFactory__vepv pas_book_factory_vepv;
+
+typedef struct {
+ Evolution_BookListener listener;
+ Evolution_BookListener_CallStatus status;
+} PASBookFactoryQueuedResponse;
+
+typedef struct {
+ char *uri;
+ Evolution_BookListener listener;
+} PASBookFactoryQueuedRequest;
+
+struct _PASBookFactoryPrivate {
+ GHashTable *backends;
+ GHashTable *active_server_map;
+ GList *queued_responses;
+ GList *queued_requests;
+};
+
+static char *
+pas_book_factory_canonicalize_uri (const char *uri)
+{
+ char *canon;
+ char *p;
+
+ /* FIXME: What do I do here? */
+
+ canon = g_strdup (uri);
+
+ for (p = canon; *p != '\0'; p ++)
+ *p = toupper (*p);
+
+ return canon;
+}
+
+static char *
+pas_book_factory_extract_proto_from_uri (const char *uri)
+{
+ char *proto;
+ char *p;
+
+ p = strchr (uri, ':');
+
+ if (p == NULL)
+ return NULL;
+
+ proto = g_malloc0 (p - uri + 1);
+
+ strncpy (proto, uri, p - uri);
+
+ return proto;
+}
+
+/**
+ * pas_book_factory_register_backend:
+ * @factory:
+ * @proto:
+ * @backend:
+ */
+void
+pas_book_factory_register_backend (PASBookFactory *factory,
+ const char *proto,
+ PASBookFactoryBackendFactory backend)
+{
+ g_return_if_fail (factory != NULL);
+ g_return_if_fail (PAS_IS_BOOK_FACTORY (factory));
+ g_return_if_fail (proto != NULL);
+ g_return_if_fail (backend != NULL);
+
+ if (g_hash_table_lookup (factory->priv->backends, proto) != NULL) {
+ g_warning ("pas_book_factory_register_backend: "
+ "Proto \"%s\" already registered!\n", proto);
+ }
+
+ g_hash_table_insert (factory->priv->backends,
+ g_strdup (proto), backend);
+}
+
+static PASBookFactoryBackendFactory
+pas_book_factory_lookup_backend_factory (PASBookFactory *factory,
+ const char *uri)
+{
+ PASBookFactoryBackendFactory backend;
+ char *proto;
+ char *canonical_uri;
+
+ g_assert (factory != NULL);
+ g_assert (PAS_IS_BOOK_FACTORY (factory));
+ g_assert (uri != NULL);
+
+ canonical_uri = pas_book_factory_canonicalize_uri (uri);
+ if (canonical_uri == NULL)
+ return NULL;
+
+ proto = pas_book_factory_extract_proto_from_uri (canonical_uri);
+ if (proto == NULL) {
+ g_free (canonical_uri);
+ return NULL;
+ }
+
+ backend = g_hash_table_lookup (factory->priv->backends, proto);
+
+ g_free (proto);
+ g_free (canonical_uri);
+
+ return backend;
+}
+
+static void
+pas_book_factory_process_request (PASBookFactory *factory,
+ PASBookFactoryQueuedRequest *request)
+{
+ request = factory->priv->queued_requests->data;
+
+ /*
+ * Check to see if there is already a running backend for this
+ * URI.
+ */
+
+
+ backend = pas_book_factory_lookup_backend_factory (
+ factory, request->uri);
+ g_assert (backend != NULL);
+
+ (backend) (factory, request->uri, request->listener);
+}
+
+
+static void
+pas_book_factory_process_response (PASBookFactory *factory,
+ PASBookFactoryQueuedResponse *response)
+{
+ CORBA_Environment ev;
+
+ CORBA_exception_init (&ev);
+
+ Evolution_BookListener_respond_open_book (
+ response->listener, response->status,
+ CORBA_OBJECT_NIL, &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("PASBookFactory: Exception while sending "
+ "response to BookListener!\n");
+
+ CORBA_exception_free (&ev);
+ CORBA_exception_init (&ev);
+ }
+
+ CORBA_Object_release (response->listener, &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("PASBookFactory: Exception releasing "
+ "BookListener!\n");
+ }
+
+ CORBA_exception_free (&ev);
+}
+
+
+static gboolean
+pas_book_factory_process_queues (PASBookFactory *factory)
+{
+ /* Process pending Book-creation requests. */
+ while (factory->priv->queued_requests != NULL) {
+ PASBookFactoryQueuedRequest *request;
+
+ pas_book_factory_process_request (factory, request);
+
+ factory->priv->queued_requests = g_list_remove (
+ factory->priv->queued_requests, request);
+
+ g_free (request);
+ }
+
+ /* Flush the outgoing error queue. */
+ while (factory->priv->queued_responses != NULL) {
+ PASBookFactoryQueuedResponse *response;
+
+ response = factory->priv->queued_responses->data;
+
+ pas_book_factory_process_response (factory, response);
+ factory->priv->queued_responses = g_list_remove (
+ factory->priv->queued_responses, response);
+
+ g_free (response);
+ }
+
+ return TRUE;
+}
+
+static void
+pas_book_factory_queue_response (PASBookFactory *factory,
+ const Evolution_BookListener listener,
+ Evolution_BookListener_CallStatus status)
+{
+ PASBookFactoryQueuedResponse *response;
+ Evolution_BookListener listener_copy;
+ CORBA_Environment ev;
+
+ CORBA_exception_init (&ev);
+
+ listener_copy = CORBA_Object_duplicate (listener, &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("PASBookFactory: Could not duplicate BookListener!\n");
+ CORBA_exception_free (&ev);
+ return;
+ }
+
+ CORBA_exception_free (&ev);
+
+ response = g_new0 (PASBookFactoryQueuedResponse, 1);
+ response->listener = listener_copy;
+ response->status = status;
+
+ factory->priv->queued_responses =
+ g_list_prepend (factory->priv->queued_responses, response);
+}
+
+static void
+pas_book_factory_queue_request (PASBookFactory *factory,
+ const char *uri,
+ const Evolution_BookListener listener)
+{
+ PASBookFactoryQueuedRequest *request;
+ Evolution_BookListener listener_copy;
+ CORBA_Environment ev;
+
+ CORBA_exception_init (&ev);
+
+ listener_copy = CORBA_Object_duplicate (listener, &ev);
+
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("PASBookFactory: Could not duplicate BookListener!\n");
+ CORBA_exception_free (&ev);
+ return;
+ }
+
+ CORBA_exception_free (&ev);
+
+ request = g_new0 (PASBookFactoryQueuedRequest, 1);
+ request->listener = listener_copy;
+ request->uri = g_strdup (uri);
+
+ factory->priv->queued_requests =
+ g_list_prepend (factory->priv->queued_requests, request);
+}
+
+static void
+impl_Evolution_BookFactory_open_book (PortableServer_Servant servant,
+ const CORBA_char *uri,
+ const Evolution_BookListener listener,
+ CORBA_Environment *ev)
+{
+ PASBookFactory *factory =
+ PAS_BOOK_FACTORY (gnome_object_from_servant (servant));
+
+ PASBookFactoryBackendFactory backend;
+
+ backend = pas_book_factory_lookup_backend_factory (factory, uri);
+
+ if (backend == NULL) {
+ g_warning ("PASBookFactory: No backend found for uri: %s\n", uri);
+
+ pas_book_factory_queue_response (
+ factory, listener,
+ Evolution_BookListener_ProtocolNotSupported);
+
+ return;
+ }
+
+ pas_book_factory_queue_request (factory, uri, listener);
+}
+
+static PASBookFactory *
+pas_book_factory_construct (PASBookFactory *factory)
+{
+ POA_Evolution_BookFactory *servant;
+ CORBA_Environment ev;
+ CORBA_Object obj;
+
+ g_assert (factory != NULL);
+ g_assert (PAS_IS_BOOK_FACTORY (factory));
+
+ servant = (POA_Evolution_BookFactory *) g_new0 (GnomeObjectServant, 1);
+ servant->vepv = &pas_book_factory_vepv;
+
+ CORBA_exception_init (&ev);
+
+ POA_Evolution_BookFactory__init ((PortableServer_Servant) servant, &ev);
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_free (servant);
+ CORBA_exception_free (&ev);
+
+ return NULL;
+ }
+
+ CORBA_exception_free (&ev);
+
+ obj = gnome_object_activate_servant (GNOME_OBJECT (factory), servant);
+ if (obj == CORBA_OBJECT_NIL) {
+ g_free (servant);
+
+ return NULL;
+ }
+
+ gnome_object_construct (GNOME_OBJECT (factory), obj);
+
+ return factory;
+}
+
+/**
+ * pas_book_factory_new:
+ */
+PASBookFactory *
+pas_book_factory_new (void)
+{
+ PASBookFactory *factory;
+ PASBookFactory *retval;
+
+ factory = gtk_type_new (PAS_BOOK_FACTORY_TYPE);
+
+ retval = pas_book_factory_construct (factory);
+
+ if (retval == NULL) {
+ g_warning ("pas_book_factoy_new: Could not construct PASBookFactory!\n");
+ gtk_object_unref (GTK_OBJECT (factory));
+
+ return NULL;
+ }
+
+ return retval;
+}
+
+static void
+pas_book_factory_init (PASBookFactory *factory)
+{
+ factory->priv = g_new0 (PASBookFactoryPrivate, 1);
+
+ factory->priv->active_server_map = g_hash_table_new (g_str_hash, g_str_equal);
+ factory->priv->backends = g_hash_table_new (g_str_hash, g_str_equal);
+ factory->priv->queued_requests = NULL;
+ factory->priv->queued_responses = NULL;
+
+ g_idle_add ((GSourceFunc) pas_book_factory_process_queues, factory);
+}
+
+static gboolean
+pas_book_factory_remove_asm_entry (gpointer key, gpointer value,
+ gpointer data)
+{
+ CORBA_Environment ev;
+
+ g_free (key);
+
+ CORBA_exception_init (&ev);
+ CORBA_Object_release ((CORBA_Object) value, &ev);
+ CORBA_exception_free (&ev);
+
+ return TRUE;
+}
+
+static gboolean
+pas_book_factory_remove_backend_entry (gpointer key, gpointer value,
+ gpointer data)
+{
+ g_free (key);
+ return TRUE;
+}
+
+static void
+pas_book_factory_destroy (GtkObject *object)
+{
+ PASBookFactory *factory = PAS_BOOK_FACTORY (object);
+ GList *l;
+
+ for (l = factory->priv->queued_requests; l != NULL; l = l->next) {
+ PASBookFactoryQueuedRequest *request = l->data;
+ CORBA_Environment ev;
+
+ g_free (request->uri);
+
+ CORBA_exception_init (&ev);
+ CORBA_Object_release (request->listener, &ev);
+ CORBA_exception_free (&ev);
+
+ g_free (request);
+ }
+ g_list_free (factory->priv->queued_requests);
+ factory->priv->queued_requests = NULL;
+
+ for (l = factory->priv->queued_responses; l != NULL; l = l->next) {
+ PASBookFactoryQueuedResponse *response = l->data;
+ CORBA_Environment ev;
+
+ CORBA_exception_init (&ev);
+ CORBA_Object_release (response->listener, &ev);
+ CORBA_exception_free (&ev);
+
+ g_free (response);
+ }
+ g_list_free (factory->priv->queued_responses);
+ factory->priv->queued_responses = NULL;
+
+ g_hash_table_foreach_remove (factory->priv->active_server_map,
+ pas_book_factory_remove_asm_entry,
+ NULL);
+ g_hash_table_destroy (factory->priv->active_server_map);
+
+ g_hash_table_foreach_remove (factory->priv->backends,
+ pas_book_factory_remove_backend_entry,
+ NULL);
+ g_hash_table_destroy (factory->priv->backends);
+
+ g_free (factory->priv);
+
+ GTK_OBJECT_CLASS (pas_book_factory_parent_class)->destroy (object);
+}
+
+static POA_Evolution_BookFactory__epv *
+pas_book_factory_get_epv (void)
+{
+ POA_Evolution_BookFactory__epv *epv;
+
+ epv = g_new0 (POA_Evolution_BookFactory__epv, 1);
+
+ epv->open_book = impl_Evolution_BookFactory_open_book;
+
+ return epv;
+
+}
+
+static void
+pas_book_factory_corba_class_init (void)
+{
+ pas_book_factory_vepv.GNOME_Unknown_epv = gnome_object_get_epv ();
+ pas_book_factory_vepv.Evolution_BookFactory_epv = pas_book_factory_get_epv ();
+}
+
+static void
+pas_book_factory_class_init (PASBookFactoryClass *klass)
+{
+ GtkObjectClass *object_class = (GtkObjectClass *) klass;
+
+ pas_book_factory_parent_class = gtk_type_class (gnome_object_get_type ());
+
+ object_class->destroy = pas_book_factory_destroy;
+
+ pas_book_factory_corba_class_init ();
+}
+
+/**
+ * pas_book_factory_get_type:
+ */
+GtkType
+pas_book_factory_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (! type) {
+ GtkTypeInfo info = {
+ "PASBookFactory",
+ sizeof (PASBookFactory),
+ sizeof (PASBookFactoryClass),
+ (GtkClassInitFunc) pas_book_factory_class_init,
+ (GtkObjectInitFunc) pas_book_factory_init,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (gnome_object_get_type (), &info);
+ }
+
+ return type;
+}
diff --git a/addressbook/backend/pas/pas-book-factory.h b/addressbook/backend/pas/pas-book-factory.h
new file mode 100644
index 0000000000..f10444e48c
--- /dev/null
+++ b/addressbook/backend/pas/pas-book-factory.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000, Helix Code, Inc.
+ */
+
+#include <bonobo/gnome-object.h>
+#include <libgnome/gnome-defs.h>
+
+#ifndef __PAS_BOOK_FACTORY_H__
+#define __PAS_BOOK_FACTORY_H__
+
+BEGIN_GNOME_DECLS
+
+typedef struct _PASBookFactoryPrivate PASBookFactoryPrivate;
+
+typedef struct {
+ GnomeObject parent_object;
+ PASBookFactoryPrivate *priv;
+} PASBookFactory;
+
+typedef struct {
+ GnomeObjectClass parent_class;
+} PASBookFactoryClass;
+
+typedef void (*PASBookFactoryBackendFactory) (
+ PASBookFactory *factory, char *uri, Evolution_BookListener listener);
+
+PASBookFactory *pas_book_factory_new (void);
+
+void pas_book_factory_register_backend (PASBookFactory *factory,
+ const char *proto,
+ PASBookFactoryBackendFactory backend);
+
+void pas_book_factory_activate (PASBookFactory *factory);
+
+GtkType pas_book_factory_get_type (void);
+
+#define PAS_BOOK_FACTORY_TYPE (pas_book_factory_get_type ())
+#define PAS_BOOK_FACTORY(o) (GTK_CHECK_CAST ((o), PAS_BOOK_FACTORY_TYPE, PASBookFactory))
+#define PAS_BOOK_FACTORY_CLASS(k) (GTK_CHECK_CLASS_CAST((k), PAS_BOOK_FACTORY_TYPE, PASBookFactoryClass))
+#define PAS_IS_BOOK_FACTORY(o) (GTK_CHECK_TYPE ((o), PAS_BOOK_FACTORY_TYPE))
+#define PAS_IS_BOOK_FACTORY_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), PAS_BOOK_FACTORY_TYPE))
+
+END_GNOME_DECLS
+
+#endif /* ! __PAS_BOOK_FACTORY_H__ */
diff --git a/addressbook/backend/pas/wombat.gnorba b/addressbook/backend/pas/wombat.gnorba
new file mode 100644
index 0000000000..f45ecb3158
--- /dev/null
+++ b/addressbook/backend/pas/wombat.gnorba
@@ -0,0 +1,5 @@
+[evolution:card-server]
+type=exe
+repo_id=IDL:Evolution/CardServer:1.0
+description=The Personal Addressbook Server
+location_info=wombat