evolution-data-server r9151 - in trunk: . addressbook addressbook/backends addressbook/backends/google
- From: abharath svn gnome org
- To: svn-commits-list gnome org
- Subject: evolution-data-server r9151 - in trunk: . addressbook addressbook/backends addressbook/backends/google
- Date: Mon, 21 Jul 2008 03:57:50 +0000 (UTC)
Author: abharath
Date: Mon Jul 21 03:57:49 2008
New Revision: 9151
URL: http://svn.gnome.org/viewvc/evolution-data-server?rev=9151&view=rev
Log:
Committing on behalf of JÃrgen Scheibengruber <mfcn gmx de>
2008-07-21 JÃrgen Scheibengruber <mfcn gmx de>
** Fix for bug #523632
Added Google contacts backend
Added:
trunk/addressbook/backends/google/
trunk/addressbook/backends/google/Makefile.am
trunk/addressbook/backends/google/e-book-backend-google-factory.c
trunk/addressbook/backends/google/e-book-backend-google-factory.h
trunk/addressbook/backends/google/e-book-backend-google.c
trunk/addressbook/backends/google/e-book-backend-google.h
trunk/addressbook/backends/google/util.c
trunk/addressbook/backends/google/util.h
Modified:
trunk/ChangeLog
trunk/addressbook/ChangeLog
trunk/addressbook/backends/Makefile.am
trunk/configure.in
Modified: trunk/addressbook/backends/Makefile.am
==============================================================================
--- trunk/addressbook/backends/Makefile.am (original)
+++ trunk/addressbook/backends/Makefile.am Mon Jul 21 03:57:49 2008
@@ -4,4 +4,4 @@
LDAP_SUBDIR =
endif
-SUBDIRS = file vcf $(LDAP_SUBDIR) groupwise
+SUBDIRS = file vcf $(LDAP_SUBDIR) google groupwise
Added: trunk/addressbook/backends/google/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/addressbook/backends/google/Makefile.am Mon Jul 21 03:57:49 2008
@@ -0,0 +1,32 @@
+INCLUDES = \
+ -DG_LOG_DOMAIN=\"libebookbackendgoogle\" \
+ -I$(top_srcdir)/addressbook \
+ -I$(top_builddir)/addressbook \
+ -I$(top_srcdir)/servers/google/libgdata \
+ -I$(top_builddir)/servers/google/libgdata \
+ -I$(top_srcdir)/servers/google/libgdata-google \
+ -I$(top_builddir)/servers/google/libgdata-google \
+ $(SOUP_CFLAGS) \
+ $(EVOLUTION_ADDRESSBOOK_CFLAGS)
+
+extension_LTLIBRARIES = libebookbackendgoogle.la
+
+libebookbackendgoogle_la_SOURCES = \
+ util.h \
+ util.c \
+ e-book-backend-google-factory.h \
+ e-book-backend-google-factory.c \
+ e-book-backend-google.h \
+ e-book-backend-google.c
+
+libebookbackendgoogle_la_LIBADD = \
+ $(top_builddir)/addressbook/libebook/libebook-1.2.la \
+ $(top_builddir)/addressbook/libedata-book/libedata-book-1.2.la \
+ $(top_builddir)/libedataserver/libedataserver-1.2.la \
+ $(top_builddir)/servers/google/libgdata/libgdata-1.2.la \
+ $(top_builddir)/servers/google/libgdata-google/libgdata-google-1.2.la \
+ $(SOUP_LIBS) \
+ $(EVOLUTION_ADDRESSBOOK_LIBS)
+
+libebookbackendgoogle_la_LDFLAGS = \
+ -module -avoid-version $(NO_UNDEFINED)
Added: trunk/addressbook/backends/google/e-book-backend-google-factory.c
==============================================================================
--- (empty file)
+++ trunk/addressbook/backends/google/e-book-backend-google-factory.c Mon Jul 21 03:57:49 2008
@@ -0,0 +1,95 @@
+/* e-book-backend-google-factory.c - Google contact backend factory.
+ *
+ * Copyright (C) 2008 Joergen Scheibengruber
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Joergen Scheibengruber <joergen.scheibengruber AT googlemail.com>
+ */
+
+#include <config.h>
+
+#include <libedataserver/e-data-server-module.h>
+#include <libedata-book/e-book-backend-factory.h>
+#include "e-book-backend-google-factory.h"
+#include "e-book-backend-google.h"
+
+static GType google_type;
+
+static void
+e_book_backend_google_factory_instance_init (EBookBackendGoogleFactory *factory)
+{
+}
+
+static const char *
+_get_protocol (EBookBackendFactory *factory)
+{
+ return "google";
+}
+
+static EBookBackend*
+_new_backend (EBookBackendFactory *factory)
+{
+ return e_book_backend_google_new ();
+}
+
+static void
+e_book_backend_google_factory_class_init (EBookBackendGoogleFactoryClass *klass)
+{
+ E_BOOK_BACKEND_FACTORY_CLASS (klass)->get_protocol = _get_protocol;
+ E_BOOK_BACKEND_FACTORY_CLASS (klass)->new_backend = _new_backend;
+}
+
+GType
+e_book_backend_google_factory_get_type (GTypeModule *module)
+{
+ static GType type = 0;
+
+ if (!type) {
+ GTypeInfo info = {
+ sizeof (EBookBackendGoogleFactoryClass),
+ NULL, /* base_class_init */
+ NULL, /* base_class_finalize */
+ (GClassInitFunc) e_book_backend_google_factory_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (EBookBackend),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) e_book_backend_google_factory_instance_init
+ };
+
+ type = g_type_module_register_type (module, E_TYPE_BOOK_BACKEND_FACTORY,
+ "EBookBackendGoogleFactory", &info, 0);
+ }
+ return type;
+}
+
+void
+eds_module_initialize (GTypeModule *module)
+{
+ google_type = e_book_backend_google_factory_get_type (module);
+}
+
+void
+eds_module_shutdown (void)
+{
+}
+
+void
+eds_module_list_types (const GType **types, int *num_types)
+{
+ *types = &google_type;
+ *num_types = 1;
+}
Added: trunk/addressbook/backends/google/e-book-backend-google-factory.h
==============================================================================
--- (empty file)
+++ trunk/addressbook/backends/google/e-book-backend-google-factory.h Mon Jul 21 03:57:49 2008
@@ -0,0 +1,53 @@
+/* e-book-backend-google-factory.h - Google contact backend factory.
+ *
+ * Copyright (C) 2008 Joergen Scheibengruber
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Joergen Scheibengruber <joergen.scheibengruber AT googlemail.com>
+ */
+
+#ifndef __E_BOOK_BACKEND_GOOGLE_FACTORY_H__
+#define __E_BOOK_BACKEND_GOOGLE_FACTORY_H__
+
+#include <glib-object.h>
+#include <libedata-book/e-book-backend-factory.h>
+
+G_BEGIN_DECLS
+
+#define E_TYPE_BOOK_BACKEND_GOOGLE_FACTORY (e_book_backend_exchange_factory_get_type ())
+#define E_BOOK_BACKEND_GOOGLE_FACTORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_BOOK_BACKEND_GOOGLE_FACTORY, EBookBackendGoogleFactory))
+#define E_BOOK_BACKEND_GOOGLE_FACTORY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), E_TYPE_BOOK_BACKEND_GOOGLE_FACTORY, EBookBackendGoogleFactoryClass))
+#define E_IS_BOOK_BACKEND_GOOGLE_FACTORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_BOOK_BACKEND_GOOGLE_FACTORY))
+#define E_IS_BOOK_BACKEND_GOOGLE_FACTORY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_BOOK_BACKEND_GOOGLE_FACTORY))
+#define E_BOOK_BACKEND_GOOGLE_FACTORY_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_BOOK_BACKEND_GOOGLE_FACTORY, EBookBackendGoogleFactoryClass))
+
+typedef struct _EBookBackendGoogleFactory EBookBackendGoogleFactory;
+typedef struct _EBookBackendGoogleFactoryClass EBookBackendGoogleFactoryClass;
+
+struct _EBookBackendGoogleFactory {
+ EBookBackendFactory parent_object;
+};
+
+struct _EBookBackendGoogleFactoryClass{
+ EBookBackendFactoryClass parent_class;
+};
+
+GType e_book_backend_google_factory_get_type (GTypeModule *module);
+
+G_END_DECLS
+
+#endif /* __E_BOOK_BACKEND_GOOGLE_FACTORY_H__ */
+
Added: trunk/addressbook/backends/google/e-book-backend-google.c
==============================================================================
--- (empty file)
+++ trunk/addressbook/backends/google/e-book-backend-google.c Mon Jul 21 03:57:49 2008
@@ -0,0 +1,992 @@
+/* e-book-backend-google.c - Google contact backendy.
+ *
+ * Copyright (C) 2008 Joergen Scheibengruber
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Joergen Scheibengruber <joergen.scheibengruber AT googlemail.com>
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include <libebook/e-contact.h>
+#include <libedata-book/e-data-book.h>
+#include <libedata-book/e-data-book-view.h>
+#include <libedata-book/e-book-backend-sexp.h>
+
+#include <gdata-service-iface.h>
+#include <gdata-google-service.h>
+
+#include "e-book-backend-google.h"
+#include "util.h"
+
+G_DEFINE_TYPE (EBookBackendGoogle, e_book_backend_google, E_TYPE_BOOK_BACKEND_SYNC);
+
+struct _EBookBackendGooglePrivate
+{
+ gint mode;
+ char *base_uri;
+
+ GDataGoogleService *service;
+ GHashTable *gdata_entries;
+
+ guint refresh_interval;
+ guint refresh_feed_id;
+ char *feed_last_updated;
+
+ gboolean authorized;
+
+ GList *bookviews;
+ GList *pending_auth_bookviews;
+};
+
+#define GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
+ E_TYPE_BOOK_BACKEND_GOOGLE, \
+ EBookBackendGooglePrivate))
+
+gboolean __e_book_backend_google_debug__;
+
+static EBookBackendSyncStatus
+e_book_backend_google_initial_query (EBookBackendGoogle *backend);
+
+static EBookBackendSyncStatus
+e_book_backend_google_update_query (EBookBackendGoogle *backend,
+ GList **added,
+ GList **modified,
+ GList **deleted);
+
+static EBookBackendSyncStatus
+ebookbackend_status_from_soup_error (int http_error);
+
+static gboolean
+e_book_backend_google_ensure_auth (EBookBackendGoogle *backend)
+{
+ EBookBackendGooglePrivate *priv;
+ gboolean is_authorized;
+
+ priv = GET_PRIVATE (backend);
+
+ is_authorized = (priv->authorized && priv->base_uri && priv->service);
+
+ if (FALSE == is_authorized) {
+ e_book_backend_notify_auth_required (E_BOOK_BACKEND (backend));
+ __debug__ ("auth required");
+ }
+
+ return is_authorized;
+}
+
+static EBookBackendSyncStatus
+e_book_backend_google_create_contact (EBookBackendSync *backend,
+ EDataBook *book,
+ guint32 opid,
+ const char *vcard_str,
+ EContact **contact)
+{
+ EBookBackendGooglePrivate *priv;
+ EBookBackendSyncStatus status = GNOME_Evolution_Addressbook_OtherError;
+ GDataEntry *entry, *new_entry;
+ GError *error = NULL;
+
+ __debug__ (G_STRFUNC);
+ priv = GET_PRIVATE (backend);
+
+ __debug__ ("Creating: %s", vcard_str);
+ *contact = NULL;
+
+ if (priv->mode != GNOME_Evolution_Addressbook_MODE_REMOTE) {
+ return GNOME_Evolution_Addressbook_OfflineUnavailable;
+ }
+
+ if (FALSE == e_book_backend_google_ensure_auth (E_BOOK_BACKEND_GOOGLE (backend))) {
+ return GNOME_Evolution_Addressbook_AuthenticationRequired;
+ }
+
+ entry = gdata_entry_create_from_vcard (vcard_str);
+ __debug__ ("new entry with xml: %s", gdata_entry_generate_xml (entry));
+ new_entry = gdata_service_insert_entry (GDATA_SERVICE (priv->service),
+ priv->base_uri, entry, &error);
+ g_object_unref (entry);
+
+ if (new_entry) {
+ const char *uid;
+
+ uid = gdata_entry_get_id (new_entry);
+ *contact = e_contact_from_gdata_entry (new_entry);
+ g_hash_table_insert (priv->gdata_entries, g_strdup (uid), new_entry);
+ }
+ if (error) {
+ status = ebookbackend_status_from_soup_error (error->code);
+ __debug__ ("Creating contact failed (HTTP %d): %s", error->code, error->message);
+ g_clear_error (&error);
+ }
+
+ if (NULL == *contact) {
+ return status;
+ }
+ return GNOME_Evolution_Addressbook_Success;
+}
+
+static EBookBackendSyncStatus
+e_book_backend_google_remove_contacts (EBookBackendSync *backend,
+ EDataBook *book,
+ guint32 opid,
+ GList *id_list,
+ GList **ids)
+{
+ EBookBackendGooglePrivate *priv;
+ EBookBackendSyncStatus status = GNOME_Evolution_Addressbook_OtherError;
+ GList *id_iter;
+
+ __debug__ (G_STRFUNC);
+ priv = GET_PRIVATE (backend);
+
+ *ids = NULL;
+
+ if (priv->mode != GNOME_Evolution_Addressbook_MODE_REMOTE) {
+ return GNOME_Evolution_Addressbook_OfflineUnavailable;
+ }
+
+ if (FALSE == e_book_backend_google_ensure_auth (E_BOOK_BACKEND_GOOGLE (backend))) {
+ return GNOME_Evolution_Addressbook_AuthenticationRequired;
+ }
+
+ for (id_iter = id_list; id_iter; id_iter = id_iter->next) {
+ GDataEntry *entry;
+ GError *error = NULL;
+ char *uid;
+
+ uid = id_iter->data;
+ entry = g_hash_table_lookup (priv->gdata_entries, uid);
+ if (NULL == entry) {
+ continue;
+ }
+
+ if (gdata_service_delete_entry (GDATA_SERVICE (priv->service), entry, &error)) {
+ g_hash_table_remove (priv->gdata_entries, uid);
+ *ids = g_list_append (*ids, g_strdup (uid));
+ }
+ if (error) {
+ /* Only last error will be reported */
+ status = ebookbackend_status_from_soup_error (error->code);
+ __debug__ ("Deleting contact %s failed (HTTP %d): %s", uid, error->code, error->message);
+ g_clear_error (&error);
+ }
+ }
+
+ if (NULL == *ids) {
+ return status;
+ }
+ return GNOME_Evolution_Addressbook_Success;
+}
+
+static EBookBackendSyncStatus
+e_book_backend_google_modify_contact (EBookBackendSync *backend,
+ EDataBook *book,
+ guint32 opid,
+ const char *vcard_str,
+ EContact **contact)
+{
+ EBookBackendGooglePrivate *priv;
+ EBookBackendSyncStatus status = GNOME_Evolution_Addressbook_OtherError;
+ EVCardAttribute *uid_attr;
+ EVCard *vcard;
+ GDataEntry *entry, *copy, *new_entry;
+ GError *error = NULL;
+ char *uid, *xml;
+
+ __debug__ (G_STRFUNC);
+ priv = GET_PRIVATE (backend);
+
+ __debug__ ("Updating: %s", vcard_str);
+ *contact = NULL;
+
+ if (priv->mode != GNOME_Evolution_Addressbook_MODE_REMOTE) {
+ return GNOME_Evolution_Addressbook_OfflineUnavailable;
+ }
+
+ if (FALSE == e_book_backend_google_ensure_auth (E_BOOK_BACKEND_GOOGLE (backend))) {
+ return GNOME_Evolution_Addressbook_AuthenticationRequired;
+ }
+
+ vcard = e_vcard_new_from_string (vcard_str);
+ if (NULL == vcard)
+ return GNOME_Evolution_Addressbook_OtherError;
+
+ uid_attr = e_vcard_get_attribute (vcard, EVC_UID);
+ if (NULL == uid_attr)
+ return GNOME_Evolution_Addressbook_ContactNotFound;
+
+ uid = e_vcard_attribute_get_value (uid_attr);
+
+ entry = g_hash_table_lookup (priv->gdata_entries, uid ? uid : "");
+
+ if (NULL == entry)
+ return GNOME_Evolution_Addressbook_ContactNotFound;
+
+ xml = gdata_entry_generate_xml (entry);
+ /* We operate on a copy; if we cannot commit our changes we should also
+ * leave the local entry as it was.
+ * There is a warning from libxml2 as result form this, because libgdata
+ * caches the xml from which it was created. However, if it is created
+ * from a feed, this xml will miss all namespace information, thus the warning */
+ copy = gdata_entry_new_from_xml (xml);
+
+ gdata_entry_update_from_e_vcard (copy, vcard);
+ new_entry = gdata_service_update_entry (GDATA_SERVICE (priv->service), copy, &error);
+
+ g_object_unref (copy);
+ g_object_unref (vcard);
+
+ if (new_entry) {
+ *contact = e_contact_from_gdata_entry (new_entry);
+ /* Will unref/free the old entry */
+ g_hash_table_replace (priv->gdata_entries, uid, new_entry);
+ }
+ if (error) {
+ status = ebookbackend_status_from_soup_error (error->code);
+ __debug__ ("Updating contact failed (HTTP %d): %s", error->code, error->message);
+ g_clear_error (&error);
+ }
+
+ if (NULL == *contact) {
+ return status;
+ }
+ return GNOME_Evolution_Addressbook_Success;
+}
+
+static EBookBackendSyncStatus
+e_book_backend_google_get_contact (EBookBackendSync *backend,
+ EDataBook *book,
+ guint32 opid,
+ const char *uid,
+ char **vcard_str)
+{
+ EBookBackendGooglePrivate *priv;
+ GDataEntry *entry;
+
+ __debug__ (G_STRFUNC);
+ priv = GET_PRIVATE (backend);
+
+ if (FALSE == e_book_backend_google_ensure_auth (E_BOOK_BACKEND_GOOGLE (backend))) {
+ return GNOME_Evolution_Addressbook_AuthenticationRequired;
+ }
+
+ entry = g_hash_table_lookup (priv->gdata_entries, uid);
+
+ if (NULL == entry) {
+ *vcard_str = NULL;
+ return GNOME_Evolution_Addressbook_ContactNotFound;
+ }
+
+ *vcard_str = vcard_from_gdata_entry (GDATA_ENTRY (entry));
+
+ return GNOME_Evolution_Addressbook_Success;
+}
+
+static EBookBackendSyncStatus
+e_book_backend_google_get_contact_list (EBookBackendSync *backend,
+ EDataBook *book,
+ guint32 opid,
+ const char *query,
+ GList **contacts)
+{
+ EBookBackendGooglePrivate *priv;
+ EBookBackendSExp *sexp;
+ GHashTableIter iter;
+ GDataEntry *entry;
+ char *uid;
+
+ __debug__ (G_STRFUNC);
+ priv = GET_PRIVATE (backend);
+
+ *contacts = NULL;
+ if (FALSE == e_book_backend_google_ensure_auth (E_BOOK_BACKEND_GOOGLE (backend))) {
+ return GNOME_Evolution_Addressbook_AuthenticationRequired;
+ }
+
+ sexp = e_book_backend_sexp_new (query);
+
+ g_hash_table_iter_init (&iter, priv->gdata_entries);
+ while (g_hash_table_iter_next (&iter, (gpointer)&uid, (gpointer)&entry)) {
+ char *vcard_str;
+
+ vcard_str = vcard_from_gdata_entry (GDATA_ENTRY (entry));
+ if (vcard_str && e_book_backend_sexp_match_vcard (sexp, vcard_str)) {
+ *contacts = g_list_append (*contacts, vcard_str);
+ } else {
+ g_free (vcard_str);
+ }
+ }
+ g_object_unref (sexp);
+
+
+ return GNOME_Evolution_Addressbook_Success;
+}
+
+static gboolean
+refresh_feed (gpointer data)
+{
+ EBookBackendGooglePrivate *priv;
+ GList *added, *modified, *deleted;
+ GList *iter;
+
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_GOOGLE (data), FALSE);
+
+ priv = GET_PRIVATE (data);
+
+ if (NULL == priv->bookviews) {
+ priv->refresh_feed_id = 0;
+
+ return FALSE;
+ }
+ e_book_backend_google_update_query (E_BOOK_BACKEND_GOOGLE (data),
+ &added, &modified, &deleted);
+
+ if (FALSE == (added || modified || deleted))
+ return TRUE;
+
+ modified = g_list_concat (added, modified);
+ while (modified) {
+ char *vcard_str;
+
+ vcard_str = vcard_from_gdata_entry (GDATA_ENTRY (modified->data));
+ __debug__ ("Update or new entry: %s", vcard_str);
+ if (vcard_str) {
+ for (iter = priv->bookviews; iter; iter = iter->next) {
+ e_data_book_view_notify_update_vcard (iter->data, g_strdup (vcard_str));
+ }
+ g_free (vcard_str);
+ }
+
+ g_object_unref (modified->data);
+ modified = g_list_delete_link (modified, modified);
+ }
+
+ while (deleted) {
+ const char *uid;
+
+ uid = gdata_entry_get_id (GDATA_ENTRY (deleted->data));
+ __debug__ ("Deleted entry: %s", uid);
+ if (uid) {
+ for (iter = priv->bookviews; iter; iter = iter->next) {
+ e_data_book_view_notify_remove (iter->data, uid);
+ }
+ }
+
+ g_object_unref (deleted->data);
+ deleted = g_list_delete_link (deleted, deleted);
+ }
+
+ for (iter = priv->bookviews; iter; iter = iter->next) {
+ e_data_book_view_notify_complete (iter->data, GNOME_Evolution_Addressbook_Success);
+ }
+
+ return TRUE;
+}
+
+static void
+do_initial_bookview_population (EBookBackendGoogle *backend,
+ EDataBookView *bookview)
+{
+ EBookBackendGooglePrivate *priv;
+ GHashTableIter iter;
+ GDataEntry *entry;
+ char *uid;
+
+ priv = GET_PRIVATE (backend);
+
+ if (NULL == priv->gdata_entries)
+ return;
+
+ g_hash_table_iter_init (&iter, priv->gdata_entries);
+ while (g_hash_table_iter_next (&iter, (gpointer)&uid, (gpointer)&entry)) {
+ char *vcard_str;
+
+ vcard_str = vcard_from_gdata_entry (GDATA_ENTRY (entry));
+ //__debug__ ("%s", vcard_str);
+ e_data_book_view_notify_update_vcard (bookview, vcard_str);
+
+ }
+
+ e_data_book_view_notify_complete (bookview, GNOME_Evolution_Addressbook_Success);
+
+ if ((0 == priv->refresh_feed_id) && priv->refresh_interval) {
+ priv->refresh_feed_id = g_timeout_add_seconds (priv->refresh_interval,
+ refresh_feed,
+ backend);
+ }
+}
+
+static void
+e_book_backend_google_start_book_view (EBookBackend *backend,
+ EDataBookView *bookview)
+{
+ EBookBackendGooglePrivate *priv;
+ gboolean have_auth;
+
+ g_return_if_fail (E_IS_BOOK_BACKEND_GOOGLE (backend));
+ g_return_if_fail (E_IS_DATA_BOOK_VIEW (bookview));
+
+ __debug__ (G_STRFUNC);
+ priv = GET_PRIVATE (backend);
+
+ priv->bookviews = g_list_append (priv->bookviews, bookview);
+
+ bonobo_object_ref (bookview);
+ e_data_book_view_notify_status_message (bookview, "Loading...");
+
+ have_auth = e_book_backend_google_ensure_auth (E_BOOK_BACKEND_GOOGLE (backend));
+ if (have_auth) {
+ do_initial_bookview_population (E_BOOK_BACKEND_GOOGLE (backend),
+ bookview);
+ } else {
+ priv->pending_auth_bookviews = g_list_append (priv->pending_auth_bookviews,
+ bookview);
+ }
+}
+
+static void
+e_book_backend_google_stop_book_view (EBookBackend *backend,
+ EDataBookView *bookview)
+{
+ EBookBackendGooglePrivate *priv;
+
+ __debug__ (G_STRFUNC);
+ priv = GET_PRIVATE (backend);
+
+ priv->bookviews = g_list_remove (priv->bookviews, bookview);
+ priv->pending_auth_bookviews = g_list_remove (priv->pending_auth_bookviews, bookview);
+ bonobo_object_unref (bookview);
+
+ if ((NULL == priv->bookviews) && priv->refresh_feed_id) {
+ g_source_remove (priv->refresh_feed_id);
+ priv->refresh_feed_id = 0;
+ }
+}
+
+static EBookBackendSyncStatus
+e_book_backend_google_update_query (EBookBackendGoogle *backend,
+ GList **added,
+ GList **modified,
+ GList **deleted)
+{
+ EBookBackendGooglePrivate *priv;
+ GDataFeed *feed;
+ GSList *iter, *entries;
+ GError *error = NULL;
+ char *uri, *updated_min = NULL;
+
+ __debug__ (G_STRFUNC);
+ priv = GET_PRIVATE (backend);
+
+ *added = *modified = *deleted = NULL;
+
+ if (NULL == priv->service ||
+ NULL == priv->base_uri) {
+ return GNOME_Evolution_Addressbook_AuthenticationFailed;
+ }
+
+ if (priv->feed_last_updated) {
+ updated_min = g_strdup_printf ("updated-min=%s", priv->feed_last_updated);
+ }
+
+ uri = build_uri (priv->base_uri, "max-results=100", "showdeleted=true", updated_min, NULL);
+ __debug__ ("URI is '%s'", uri);
+ feed = gdata_service_get_feed (GDATA_SERVICE (priv->service), uri, &error);
+ g_free (uri);
+
+ if (error) {
+ EBookBackendSyncStatus status;
+
+ __debug__ ("Update query failed (HTTP %d): %s", error->code, error->message);
+ status = ebookbackend_status_from_soup_error (error->code);
+ g_clear_error (&error);
+
+ return status;
+ }
+ if (NULL == feed) {
+ return GNOME_Evolution_Addressbook_OtherError;
+ }
+
+ g_free (priv->feed_last_updated);
+ priv->feed_last_updated = g_strdup (gdata_feed_get_updated (GDATA_FEED (feed)));
+
+ entries = gdata_feed_get_entries (feed);
+ __debug__ ("Update-feed has %d entries", entries ? g_slist_length (entries) : -1);
+
+ for (iter = entries; iter; iter = iter->next) {
+ GDataEntry *entry, *old_entry;
+ const char *edit_link, *old_edit_link;
+ gboolean is_deleted;
+ const char *uid;
+
+ entry = GDATA_ENTRY (iter->data);
+ uid = gdata_entry_get_id (entry);
+ is_deleted = gdata_entry_is_deleted (entry);
+
+ old_entry = g_hash_table_lookup (priv->gdata_entries, uid);
+ if (is_deleted) {
+ /* Do we have this item in our list? */
+ if (NULL == old_entry) {
+ continue;
+ } else {
+ *deleted = g_list_append (*deleted, g_object_ref (entry));
+ g_hash_table_remove (priv->gdata_entries, uid);
+ }
+ } else {
+ /* Is this a new entry */
+ if (NULL == old_entry) {
+ *added = g_list_append (*added, g_object_ref (entry));
+ g_hash_table_insert (priv->gdata_entries,
+ g_strdup (uid),
+ g_object_ref (entry));
+ }
+ }
+
+ edit_link = gdata_entry_get_edit_link (entry);
+ old_edit_link = gdata_entry_get_edit_link (old_entry);
+ if (0 == strcmp (edit_link ? edit_link : "", old_edit_link ? old_edit_link : ""))
+ continue;
+
+ g_hash_table_replace (priv->gdata_entries, g_strdup (uid), g_object_ref (entry));
+ *modified = g_list_append (*modified, g_object_ref (entry));
+ }
+ g_object_unref (feed);
+
+ return GNOME_Evolution_Addressbook_Success;
+}
+
+static EBookBackendSyncStatus
+e_book_backend_google_initial_query (EBookBackendGoogle *backend)
+{
+ EBookBackendGooglePrivate *priv;
+ GDataFeed *feed;
+ GSList *iter, *entries;
+ GError *error = NULL;
+ char *uri;
+
+ __debug__ (G_STRFUNC);
+ priv = GET_PRIVATE (backend);
+
+ if (NULL == priv->service ||
+ NULL == priv->base_uri) {
+ return GNOME_Evolution_Addressbook_AuthenticationFailed;
+ }
+
+ uri = build_uri (priv->base_uri, "max-results=100", NULL);
+ __debug__ ("URI is '%s'", uri);
+ feed = gdata_service_get_feed (GDATA_SERVICE (priv->service), uri, &error);
+ g_free (uri);
+
+ if (error) {
+ EBookBackendSyncStatus status;
+
+ __debug__ ("Initial query failed (HTTP %d): %s", error->code, error->message);
+ status = ebookbackend_status_from_soup_error (error->code);
+ g_clear_error (&error);
+
+ return status;
+ }
+ if (NULL == feed) {
+ return GNOME_Evolution_Addressbook_OtherError;
+ }
+
+ g_free (priv->feed_last_updated);
+ priv->feed_last_updated = g_strdup (gdata_feed_get_updated (GDATA_FEED (feed)));
+ if (priv->gdata_entries) {
+ g_hash_table_destroy (priv->gdata_entries);
+ }
+ priv->gdata_entries = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_object_unref);
+
+ entries = gdata_feed_get_entries (feed);
+ __debug__ ("Feed has %d entries", entries ? g_slist_length (entries) : -1);
+ for (iter = entries; iter; iter = iter->next) {
+ GDataEntry *entry;
+ const char* uid;
+
+ entry = GDATA_ENTRY (iter->data);
+ uid = gdata_entry_get_id (entry);
+ g_hash_table_insert (priv->gdata_entries, g_strdup (uid), g_object_ref (entry));
+ }
+ g_object_unref (feed);
+
+ return GNOME_Evolution_Addressbook_Success;
+}
+
+
+static EBookBackendSyncStatus
+e_book_backend_google_authenticate_user (EBookBackendSync *backend,
+ EDataBook *book,
+ guint32 opid,
+ const char *username,
+ const char *password,
+ const char *auth_method)
+{
+ EBookBackendGooglePrivate *priv;
+ EBookBackendSyncStatus status;
+
+ __debug__ (G_STRFUNC);
+ priv = GET_PRIVATE (backend);
+
+ if (priv->mode != GNOME_Evolution_Addressbook_MODE_REMOTE) {
+ g_warning ("Offline mode not mplemented...");
+ return GNOME_Evolution_Addressbook_OfflineUnavailable;
+ }
+ if (NULL == priv->service) {
+ g_warning ("Book not open; could not authenticate");
+ return GNOME_Evolution_Addressbook_RepositoryOffline;
+ }
+
+ g_free (priv->base_uri);
+ priv->base_uri = NULL;
+
+ if (NULL == username || username[0] == 0 ||
+ NULL == password || password[0] == 0) {
+ return GNOME_Evolution_Addressbook_AuthenticationFailed;
+ }
+
+ priv->base_uri = build_base_uri (username);
+ gdata_service_set_credentials (GDATA_SERVICE (priv->service), username, password);
+
+ status = e_book_backend_google_initial_query (E_BOOK_BACKEND_GOOGLE (backend));
+ if (status == GNOME_Evolution_Addressbook_Success) {
+ GList *iter;
+
+ priv->authorized = TRUE;
+ e_book_backend_notify_writable (E_BOOK_BACKEND (backend), TRUE);
+
+ for (iter = priv->pending_auth_bookviews; iter; iter = iter->next) {
+ do_initial_bookview_population (E_BOOK_BACKEND_GOOGLE (backend),
+ iter->data);
+ }
+ } else {
+ g_free (priv->base_uri);
+ priv->base_uri = NULL;
+ priv->authorized = FALSE;
+ }
+
+ return status;
+}
+
+static EBookBackendSyncStatus
+e_book_backend_google_get_supported_auth_methods (EBookBackendSync *backend,
+ EDataBook *book,
+ guint32 opid,
+ GList **methods)
+{
+ char *auth_method;
+
+ __debug__ (G_STRFUNC);
+ auth_method = g_strdup_printf ("plain/password");
+ *methods = g_list_append (NULL, auth_method);
+
+ return GNOME_Evolution_Addressbook_Success;
+}
+
+static EBookBackendSyncStatus
+e_book_backend_google_get_required_fields (EBookBackendSync *backend,
+ EDataBook *book,
+ guint32 opid,
+ GList **fields_out)
+{
+ __debug__ (G_STRFUNC);
+
+ *fields_out = NULL;
+ return GNOME_Evolution_Addressbook_Success;
+}
+
+static EBookBackendSyncStatus
+e_book_backend_google_get_supported_fields (EBookBackendSync *backend,
+ EDataBook *book,
+ guint32 opid,
+ GList **fields_out)
+{
+ const int supported_fields[] =
+ {
+ E_CONTACT_FULL_NAME,
+ E_CONTACT_EMAIL_1,
+ E_CONTACT_EMAIL_2,
+ E_CONTACT_EMAIL_3,
+ E_CONTACT_EMAIL_4,
+ E_CONTACT_ADDRESS_LABEL_HOME,
+ E_CONTACT_ADDRESS_LABEL_WORK,
+ E_CONTACT_ADDRESS_LABEL_OTHER,
+ E_CONTACT_PHONE_HOME,
+ E_CONTACT_PHONE_HOME_FAX,
+ E_CONTACT_PHONE_BUSINESS,
+ E_CONTACT_PHONE_BUSINESS_FAX,
+ E_CONTACT_PHONE_MOBILE,
+ E_CONTACT_PHONE_PAGER,
+ E_CONTACT_IM_AIM,
+ E_CONTACT_IM_JABBER,
+ E_CONTACT_IM_YAHOO,
+ E_CONTACT_IM_MSN,
+ E_CONTACT_IM_ICQ,
+ E_CONTACT_ADDRESS,
+ E_CONTACT_ADDRESS_HOME,
+ E_CONTACT_ADDRESS_WORK,
+ E_CONTACT_ADDRESS_OTHER
+ };
+ GList *fields = NULL;
+ int i;
+
+ __debug__ (G_STRFUNC);
+
+ for (i = 0; i < G_N_ELEMENTS (supported_fields); i++) {
+ const char *field_name;
+
+ field_name = e_contact_field_name (supported_fields[i]);
+ fields = g_list_append (fields, g_strdup (field_name));
+ }
+
+ *fields_out = fields;
+ return GNOME_Evolution_Addressbook_Success;
+}
+
+static EBookBackendSyncStatus
+e_book_backend_google_get_changes (EBookBackendSync *backend,
+ EDataBook *book,
+ guint32 opid,
+ const char *change_id,
+ GList **changes_out)
+{
+ __debug__ (G_STRFUNC);
+ return GNOME_Evolution_Addressbook_OtherError;
+}
+
+static EBookBackendSyncStatus
+e_book_backend_google_remove (EBookBackendSync *backend,
+ EDataBook *book,
+ guint32 opid)
+{
+ __debug__ (G_STRFUNC);
+ return GNOME_Evolution_Addressbook_PermissionDenied;
+}
+
+static GNOME_Evolution_Addressbook_CallStatus
+e_book_backend_google_load_source (EBookBackend *backend,
+ ESource *source,
+ gboolean only_if_exists)
+{
+ EBookBackendGooglePrivate *priv = GET_PRIVATE (backend);
+ const char *refresh_interval;
+
+ if (priv->service) {
+ g_warning ("Source already loaded!");
+ return GNOME_Evolution_Addressbook_OtherError;
+ }
+
+ refresh_interval = e_source_get_property (source, "refresh-interval");
+ if (refresh_interval) {
+ guint val;
+
+ if (1 == sscanf (refresh_interval, "%u", &val)) {
+ priv->refresh_interval = val;
+ }
+ }
+
+ __debug__ (G_STRFUNC);
+ if (priv->mode == GNOME_Evolution_Addressbook_MODE_REMOTE) {
+ gboolean status;
+
+ status = test_repository_availability ();
+ if (FALSE == status) {
+ e_book_backend_notify_connection_status (backend, FALSE);
+
+ return GNOME_Evolution_Addressbook_RepositoryOffline;
+ }
+
+ priv->service = gdata_google_service_new ("cp", "evolution-client-0.0.1");
+
+ e_book_backend_set_is_loaded (backend, TRUE);
+ e_book_backend_notify_connection_status (backend, TRUE);
+
+ return GNOME_Evolution_Addressbook_Success;
+ } else {
+ g_warning ("Offline mode not yet implemented...");
+ return GNOME_Evolution_Addressbook_OfflineUnavailable;
+ }
+}
+
+static char *
+e_book_backend_google_get_static_capabilities (EBookBackend *backend)
+{
+ __debug__ (G_STRFUNC);
+ return g_strdup("net,do-initial-query,contact-lists");
+}
+
+static GNOME_Evolution_Addressbook_CallStatus
+e_book_backend_google_cancel_operation (EBookBackend *backend, EDataBook *book)
+{
+ __debug__ (G_STRFUNC);
+ return GNOME_Evolution_Addressbook_CouldNotCancel;
+}
+
+static void
+e_book_backend_google_set_mode (EBookBackend *backend, GNOME_Evolution_Addressbook_BookMode mode)
+{
+ EBookBackendGooglePrivate *priv = GET_PRIVATE (backend);
+
+ __debug__ (G_STRFUNC);
+
+ if (mode == priv->mode) {
+ return;
+ }
+ priv->mode = mode;
+
+ if (mode == GNOME_Evolution_Addressbook_MODE_REMOTE) {
+ if (e_book_backend_is_loaded (backend)) {
+ gboolean status;
+
+ status = test_repository_availability ();
+
+ if (FALSE == status) {
+ e_book_backend_notify_writable (backend, FALSE);
+ e_book_backend_notify_connection_status (backend, FALSE);
+ } else {
+ status = e_book_backend_google_ensure_auth (E_BOOK_BACKEND_GOOGLE (backend));
+ e_book_backend_notify_writable (backend, status);
+ e_book_backend_notify_connection_status (backend, TRUE);
+ }
+ } else {
+ e_book_backend_set_is_writable (backend, FALSE);
+ }
+ } else {
+ e_book_backend_notify_writable (backend, FALSE);
+ e_book_backend_notify_connection_status (backend, FALSE);
+ g_warning ("Offline mode not implemented yet...");
+ }
+}
+
+static void
+e_book_backend_google_dispose (GObject *object)
+{
+ EBookBackendGooglePrivate *priv = GET_PRIVATE (object);
+
+ __debug__ (G_STRFUNC);
+
+ if (priv->refresh_feed_id) {
+ g_source_remove (priv->refresh_feed_id);
+ priv->refresh_feed_id = 0;
+ }
+
+ while (priv->pending_auth_bookviews) {
+ priv->pending_auth_bookviews =
+ g_list_delete_link (priv->pending_auth_bookviews,
+ priv->pending_auth_bookviews);
+ }
+ while (priv->bookviews) {
+ bonobo_object_unref (priv->bookviews->data);
+ priv->bookviews = g_list_delete_link (priv->bookviews,
+ priv->bookviews);
+ }
+ if (priv->service) {
+ g_object_unref (priv->service);
+ priv->service = NULL;
+ }
+
+ G_OBJECT_CLASS (e_book_backend_google_parent_class)->dispose (object);
+}
+
+static void
+e_book_backend_google_finalize (GObject *object)
+{
+ EBookBackendGooglePrivate *priv = GET_PRIVATE (object);
+
+ __debug__ (G_STRFUNC);
+
+ g_free (priv->base_uri);
+ g_free (priv->feed_last_updated);
+ if (priv->gdata_entries) {
+ g_hash_table_destroy (priv->gdata_entries);
+ }
+ G_OBJECT_CLASS (e_book_backend_google_parent_class)->finalize (object);
+}
+
+static void
+e_book_backend_google_class_init (EBookBackendGoogleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ EBookBackendClass *backend_class;
+ EBookBackendSyncClass *sync_class;
+
+ backend_class = E_BOOK_BACKEND_CLASS (klass);
+ sync_class = E_BOOK_BACKEND_SYNC_CLASS (klass);
+ g_type_class_add_private (klass, sizeof (EBookBackendGooglePrivate));
+
+ /* Set the virtual methods. */
+ backend_class->load_source = e_book_backend_google_load_source;
+ backend_class->get_static_capabilities = e_book_backend_google_get_static_capabilities;
+ backend_class->start_book_view = e_book_backend_google_start_book_view;
+ backend_class->stop_book_view = e_book_backend_google_stop_book_view;
+ backend_class->cancel_operation = e_book_backend_google_cancel_operation;
+ backend_class->set_mode = e_book_backend_google_set_mode;
+ sync_class->remove_sync = e_book_backend_google_remove;
+ sync_class->create_contact_sync = e_book_backend_google_create_contact;
+ sync_class->remove_contacts_sync = e_book_backend_google_remove_contacts;
+ sync_class->modify_contact_sync = e_book_backend_google_modify_contact;
+ sync_class->get_contact_sync = e_book_backend_google_get_contact;
+ sync_class->get_contact_list_sync = e_book_backend_google_get_contact_list;
+ sync_class->get_changes_sync = e_book_backend_google_get_changes;
+ sync_class->authenticate_user_sync = e_book_backend_google_authenticate_user;
+ sync_class->get_supported_fields_sync = e_book_backend_google_get_supported_fields;
+ sync_class->get_required_fields_sync = e_book_backend_google_get_required_fields;
+ sync_class->get_supported_auth_methods_sync = e_book_backend_google_get_supported_auth_methods;
+
+ object_class->dispose = e_book_backend_google_dispose;
+ object_class->finalize = e_book_backend_google_finalize;
+
+ __e_book_backend_google_debug__ = g_getenv ("GOOGLE_BACKEND_DEBUG") ? TRUE : FALSE;
+}
+
+static void
+e_book_backend_google_init (EBookBackendGoogle *backend)
+{
+ __debug__ (G_STRFUNC);
+}
+
+EBookBackend *
+e_book_backend_google_new (void)
+{
+ EBookBackendGoogle *backend;
+
+ __debug__ (G_STRFUNC);
+ backend = g_object_new (E_TYPE_BOOK_BACKEND_GOOGLE, NULL);
+
+ return E_BOOK_BACKEND (backend);
+}
+
+static EBookBackendSyncStatus
+ebookbackend_status_from_soup_error (int http_error)
+{
+ if (http_error < 200) {
+ return GNOME_Evolution_Addressbook_RepositoryOffline;
+ } else
+ if (http_error == 401) {
+ return GNOME_Evolution_Addressbook_AuthenticationRequired;
+ } else
+ if (http_error == 403) {
+ return GNOME_Evolution_Addressbook_AuthenticationFailed;
+ } else {
+ return GNOME_Evolution_Addressbook_OtherError;
+ }
+}
+
Added: trunk/addressbook/backends/google/e-book-backend-google.h
==============================================================================
--- (empty file)
+++ trunk/addressbook/backends/google/e-book-backend-google.h Mon Jul 21 03:57:49 2008
@@ -0,0 +1,52 @@
+/* e-book-backend-google.h - Google contact backendy.
+ *
+ * Copyright (C) 2008 Joergen Scheibengruber
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Joergen Scheibengruber <joergen.scheibengruber AT googlemail.com>
+ */
+
+#ifndef __E_BOOK_BACKEND_GOOGLE_H__
+#define __E_BOOK_BACKEND_GOOGLE_H__
+
+#include <libedata-book/e-book-backend-sync.h>
+
+#define E_TYPE_BOOK_BACKEND_GOOGLE (e_book_backend_google_get_type ())
+#define E_BOOK_BACKEND_GOOGLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), E_TYPE_BOOK_BACKEND_GOOGLE, EBookBackendGoogle))
+#define E_BOOK_BACKEND_GOOGLE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), E_TYPE_BOOK_BACKEND_GOOGLE, EBookBackendGoogleClass))
+#define E_IS_BOOK_BACKEND_GOOGLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), E_TYPE_BOOK_BACKEND_GOOGLE))
+#define E_IS_BOOK_BACKEND_GOOGLE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), E_TYPE_BOOK_BACKEND_GOOGLE))
+#define E_BOOK_BACKEND_GOOGLE_GET_CLASS(k) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_BOOK_BACKEND_GOOGLE, EBookBackendGoogleClass))
+
+typedef struct _EBookBackendGoogle EBookBackendGoogle;
+typedef struct _EBookBackendGoogleClass EBookBackendGoogleClass;
+typedef struct _EBookBackendGooglePrivate EBookBackendGooglePrivate;
+
+struct _EBookBackendGoogle
+{
+ EBookBackendSync parent_object;
+ EBookBackendGooglePrivate *priv;
+};
+
+struct _EBookBackendGoogleClass
+{
+ EBookBackendSyncClass parent_class;
+};
+
+EBookBackend *e_book_backend_google_new (void);
+GType e_book_backend_google_get_type (void);
+
+#endif /* __E_BOOK_BACKEND_GOOGLE_H__ */
Added: trunk/addressbook/backends/google/util.c
==============================================================================
--- (empty file)
+++ trunk/addressbook/backends/google/util.c Mon Jul 21 03:57:49 2008
@@ -0,0 +1,819 @@
+/* util.c - Google contact backend utility functions.
+ *
+ * Copyright (C) 2008 Joergen Scheibengruber
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Joergen Scheibengruber <joergen.scheibengruber AT googlemail.com>
+ */
+
+#include <string.h>
+#include <libsoup/soup.h>
+#include "util.h"
+
+static EVCardAttribute*
+attribute_from_gdata_entry_email_address (GDataEntryEmailAddress *email);
+
+static EVCardAttribute*
+attribute_from_gdata_entry_im_address (GDataEntryIMAddress *im);
+
+static EVCardAttribute*
+attribute_from_gdata_entry_phone_number (GDataEntryPhoneNumber *number);
+
+static EVCardAttribute*
+attribute_from_gdata_entry_postal_address (GDataEntryPostalAddress *address);
+
+static GDataEntryEmailAddress*
+gdata_entry_email_address_from_attribute (EVCardAttribute *attr,
+ gboolean primary);
+
+static GDataEntryIMAddress*
+gdata_entry_im_address_from_attribute (EVCardAttribute *attr,
+ gboolean primary);
+
+static GDataEntryPhoneNumber*
+gdata_entry_phone_number_from_attribute (EVCardAttribute *attr,
+ gboolean primary);
+
+static GDataEntryPostalAddress*
+gdata_entry_postal_address_from_attribute (EVCardAttribute *attr,
+ gboolean primary);
+
+static GList*
+name_values_from_fullname (const char *fullname);
+
+static char*
+fullname_from_name_values (GList *values);
+
+static gboolean
+is_known_google_im_protocol (const char *protocol);
+
+GDataEntry* gdata_entry_create_from_vcard (const char *vcard_str)
+{
+ GDataEntry *entry;
+ EVCard *vcard;
+
+ vcard = e_vcard_new_from_string (vcard_str);
+ if (NULL == vcard)
+ return NULL;
+ entry = gdata_entry_create_from_e_vcard (vcard);
+
+ g_object_unref (vcard);
+
+ return entry;
+}
+
+GDataEntry* gdata_entry_create_from_e_vcard (EVCard *vcard)
+{
+ GDataEntry *entry;
+ GDataEntryCategory *category;
+
+ entry = gdata_entry_new ();
+
+ category = g_new0 (GDataEntryCategory, 1);
+ category->scheme = g_strdup ("http://schemas.google.com/g/2005#kind");
+ category->term = g_strdup ("http://schemas.google.com/contact/2008#contact");
+ gdata_entry_set_categories (entry, g_slist_append (NULL, category));
+
+ if (gdata_entry_update_from_e_vcard (entry, vcard))
+ return entry;
+
+ g_object_unref (entry);
+
+ return NULL;
+}
+
+gboolean gdata_entry_update_from_vcard (GDataEntry *entry,
+ const char *vcard_str)
+{
+ EVCard *vcard;
+
+ vcard = e_vcard_new_from_string (vcard_str);
+ if (NULL == vcard)
+ return FALSE;
+ gdata_entry_update_from_e_vcard (entry, vcard);
+
+ g_object_unref (vcard);
+
+ return TRUE;
+}
+
+gboolean gdata_entry_update_from_e_vcard (GDataEntry *entry,
+ EVCard *vcard)
+{
+ GList *attributes, *iter;
+ char *fullname = NULL;
+ GSList *email_addresses = NULL;
+ GSList *im_addresses = NULL;
+ GSList *phone_numbers = NULL;
+ GSList *postal_addresses = NULL;
+
+ attributes = e_vcard_get_attributes (vcard);
+
+ for (iter = attributes; iter; iter = iter->next) {
+ EVCardAttribute *attr;
+ const char *name;
+
+ attr = iter->data;
+ name = e_vcard_attribute_get_name (attr);
+
+ /* N */
+ if (0 == strcmp (name, EVC_N)) {
+ GList *values;
+
+ if (fullname) {
+ continue;
+ }
+
+ values = e_vcard_attribute_get_values (attr);
+ fullname = fullname_from_name_values (values);
+ } else
+
+ /* FN */
+ if (0 == strcmp (name, EVC_FN)) {
+ GList *values;
+
+ values = e_vcard_attribute_get_values (attr);
+ if (values) {
+ g_free (fullname);
+ fullname = g_strdup (values->data);
+ }
+ } else
+
+ /* EMAIL */
+ if (0 == strcmp (name, EVC_EMAIL)) {
+ GDataEntryEmailAddress *email;
+
+ email = gdata_entry_email_address_from_attribute
+ (attr, email_addresses == NULL);
+ if (email) {
+ email_addresses = g_slist_append (email_addresses,
+ email);
+ }
+ } else
+
+ /* TEL */
+ if (0 == strcmp (name, EVC_TEL)) {
+ GDataEntryPhoneNumber *number;
+
+ number = gdata_entry_phone_number_from_attribute
+ (attr, phone_numbers == NULL);
+ if (number) {
+ phone_numbers = g_slist_append (phone_numbers,
+ number);
+ }
+ } else
+
+ /* LABEL */
+ if (0 == strcmp (name, EVC_LABEL)) {
+ GDataEntryPostalAddress *address;
+
+ address = gdata_entry_postal_address_from_attribute
+ (attr, postal_addresses == NULL);
+ if (address) {
+ postal_addresses = g_slist_append (postal_addresses,
+ address);
+ }
+ } else
+
+ /* X-IM */
+ if (strncmp (name, "X-", MAX (2, strlen (name))) &&
+ is_known_google_im_protocol (name + 2)) {
+ GDataEntryIMAddress *im;
+
+ im = gdata_entry_im_address_from_attribute
+ (attr, im_addresses == NULL);
+ if (im) {
+ im_addresses = g_slist_append (im_addresses,
+ im);
+ }
+ } else {
+ GList *values;
+
+ values = e_vcard_attribute_get_values (attr);
+ if (values && values->data && ((char*)values->data)[0]) {
+ g_warning ("unsupported vcard field: %s: %s", name, (char*)values->data);
+ }
+ }
+ }
+ gdata_entry_set_title (entry, fullname);
+ gdata_entry_set_email_addresses (entry, email_addresses);
+ gdata_entry_set_im_addresses (entry, im_addresses);
+ gdata_entry_set_phone_numbers (entry, phone_numbers);
+ gdata_entry_set_postal_addresses (entry, postal_addresses);
+
+ return TRUE;
+}
+
+EVCard*
+e_vcard_from_gdata_entry (GDataEntry *entry)
+{
+ EVCard *vcard;
+ EVCardAttribute *attr;
+ GSList *email_addresses, *im_addresses, *phone_numbers, *postal_addresses;
+ const char *name;
+ const char *uid;
+ GSList *itr;
+ GDataEntryEmailAddress *email;
+ GDataEntryIMAddress *im;
+ GDataEntryPhoneNumber *phone_number;
+ GDataEntryPostalAddress *postal_address;
+
+ uid = gdata_entry_get_id (entry);
+ if (NULL == uid) {
+ return NULL;
+ }
+
+ vcard = e_vcard_new ();
+
+ /* UID */
+ attr = e_vcard_attribute_new (NULL, EVC_UID);
+ e_vcard_add_attribute_with_value (vcard, attr, uid);
+
+ /* FN - TODO: get title */
+ name = gdata_entry_get_title (entry);
+ if (name) {
+ GList *name_values;
+
+ attr = e_vcard_attribute_new (NULL, EVC_FN);
+ e_vcard_add_attribute_with_value (vcard, attr, name);
+
+ /* N */
+ attr = e_vcard_attribute_new (NULL, EVC_N);
+ name_values = name_values_from_fullname (name);
+ while (name_values) {
+ e_vcard_attribute_add_value (attr, name_values->data);
+ g_free (name_values->data);
+ name_values = g_list_delete_link (name_values, name_values);
+ }
+ e_vcard_add_attribute (vcard, attr);
+ }
+
+ /* EMAIL - primary first */
+ email = gdata_entry_get_primary_email_address (entry);
+ attr = attribute_from_gdata_entry_email_address (email);
+ if (attr) {
+ e_vcard_add_attribute (vcard, attr);
+ }
+
+ email_addresses = gdata_entry_get_email_addresses (entry);
+ for (itr = email_addresses; itr; itr = itr->next) {
+ email = itr->data;
+ if (TRUE == email->primary)
+ continue;
+ attr = attribute_from_gdata_entry_email_address (email);
+ if (attr) {
+ e_vcard_add_attribute (vcard, attr);
+ }
+ }
+
+ /* X-IM - primary first */
+ im = gdata_entry_get_primary_im_address (entry);
+ attr = attribute_from_gdata_entry_im_address (im);
+ if (attr) {
+ e_vcard_add_attribute (vcard, attr);
+ }
+ im_addresses = gdata_entry_get_im_addresses (entry);
+ for (itr = im_addresses; itr; itr = itr->next) {
+ im = itr->data;
+ if (TRUE == im->primary)
+ continue;
+ attr = attribute_from_gdata_entry_im_address (im);
+ if (attr) {
+ e_vcard_add_attribute (vcard, attr);
+ }
+ }
+
+ /* TEL - primary first */
+ phone_number = gdata_entry_get_primary_phone_number (entry);
+ attr = attribute_from_gdata_entry_phone_number (phone_number);
+ if (attr) {
+ e_vcard_add_attribute (vcard, attr);
+ }
+ phone_numbers = gdata_entry_get_phone_numbers (entry);
+ for (itr = phone_numbers; itr; itr = itr->next) {
+ phone_number = itr->data;
+ if (TRUE == phone_number->primary)
+ continue;
+ attr = attribute_from_gdata_entry_phone_number (phone_number);
+ if (attr) {
+ e_vcard_add_attribute (vcard, attr);
+ }
+ }
+
+ /* LABEL - primary first TODO: ADR */
+ postal_address = gdata_entry_get_primary_postal_address (entry);
+ attr = attribute_from_gdata_entry_postal_address (postal_address);
+ if (attr) {
+ e_vcard_add_attribute (vcard, attr);
+ }
+ postal_addresses = gdata_entry_get_postal_addresses (entry);
+ for (itr = postal_addresses; itr; itr = itr->next) {
+ postal_address = itr->data;
+ if (TRUE == postal_address->primary)
+ continue;
+ attr = attribute_from_gdata_entry_postal_address (postal_address);
+ if (attr) {
+ e_vcard_add_attribute (vcard, attr);
+ }
+ }
+
+ return vcard;
+}
+
+EContact*
+e_contact_from_gdata_entry (GDataEntry *entry)
+{
+ EContact *contact;
+ char *vcard_str;
+
+ vcard_str = vcard_from_gdata_entry (entry);
+ contact = e_contact_new_from_vcard (vcard_str);
+ g_free (vcard_str);
+
+ return contact;
+}
+
+char*
+vcard_from_gdata_entry (GDataEntry *entry)
+{
+ EVCard *vcard;
+ char *vcard_str;
+
+ vcard = e_vcard_from_gdata_entry (entry);
+ vcard_str = e_vcard_to_string (vcard, EVC_FORMAT_VCARD_30);
+ g_object_unref (vcard);
+
+ return vcard_str;
+}
+
+static GList*
+name_values_from_fullname (const char *fullname)
+{
+ const char *comma = NULL;
+ char **names;
+ GList *name_values = NULL;
+
+ if (NULL == fullname)
+ return NULL;
+
+ comma = strstr (fullname, ",");
+ names = g_strsplit_set (fullname, ", ", 3);
+ if (NULL == names[0]) {
+ goto out;
+ }
+ /* Homer */
+ if (NULL == names[1]) {
+ name_values = g_list_append (NULL, names[0]);
+ goto out;
+ }
+ if (comma) {
+ /* Simpson, Homer */
+ name_values = g_list_append (NULL, names[0]);
+ name_values = g_list_append (name_values, names[1]);
+ /* Simpson, Homer J.*/
+ if (names[2]) {
+ name_values = g_list_append (name_values, names[2]);
+ }
+ } else {
+ /* Homer J. Simpson */
+ if (names[2]) {
+ name_values = g_list_append (NULL, names[2]);
+ name_values = g_list_append (name_values, names[0]);
+ name_values = g_list_append (name_values, names[1]);
+ }
+ /* Homer Simpson */
+ else {
+ name_values = g_list_append (NULL, names[1]);
+ name_values = g_list_append (name_values, names[0]);
+ }
+ }
+
+out:
+ g_free (names);
+
+ return name_values;
+}
+
+static GString*
+string_prepend_with_space (GString *string, const char *val)
+{
+ if (NULL == val ||
+ 0 == val[0])
+ return string;
+ g_string_prepend (string, " ");
+ g_string_prepend (string, val);
+
+ return string;
+}
+
+#if 0
+static GString*
+string_append_with_space (GString *string, const char *val)
+{
+ if (NULL == val ||
+ 0 == val[0])
+ return string;
+ string = g_string_append (string, " ");
+ string = g_string_append (string, val);
+
+ return string;
+}
+#endif
+
+static char*
+fullname_from_name_values (GList *values)
+{
+ GString *name;
+ const char *givenname;
+
+ if (NULL == values ||
+ NULL == values->data)
+ return NULL;
+
+ /* Family Name */
+ name = g_string_new (values->data);
+
+ values = values->next;
+ if (NULL == values)
+ goto out;
+
+ /* Given Name */
+ givenname = values->data;
+
+ values = values->next;
+ if (NULL == values) {
+ string_prepend_with_space (name, givenname);
+ goto out;
+ }
+
+ /* Additional Names */
+ string_prepend_with_space (name, values->data);
+ string_prepend_with_space (name, givenname);
+
+ values = values->next;
+ if (NULL == values)
+ goto out;
+
+ /* TODO: Honoric stuff should go into ORG? */
+#if 0
+ /* Honorific Prefixes */
+ string_prepend_with_space (name, values->data);
+
+ values = values->next;
+ if (NULL == values)
+ goto out;
+
+ /* Honorific Suffixes */
+ string_append_with_space (name, values->data);
+#endif
+
+out:
+ return g_string_free (name, FALSE);
+}
+
+char* build_uri (const char *base_uri, ...)
+{
+ va_list params;
+ const char *param;
+ GString *query;
+ const char *separator = "?";
+
+ query = g_string_new (base_uri);
+ va_start (params, base_uri);
+ while (TRUE) {
+ param = va_arg (params, const char*);
+ if (NULL == param) {
+ break;
+ }
+ g_string_append (query, separator);
+ g_string_append (query, param);
+ separator = "&";
+ }
+ va_end (params);
+
+ return g_string_free (query, FALSE);
+
+}
+
+char* build_base_uri (const char* username)
+{
+ const char *format = "http://www.google.com/m8/feeds/contacts/%s/base";
+ char *esc_username;
+ char *uri;
+
+ esc_username = g_uri_escape_string (username, NULL, FALSE);
+ uri = g_strdup_printf (format, esc_username);
+ g_free (esc_username);
+
+ return uri;
+}
+
+gboolean test_repository_availability (void)
+{
+ SoupSession *session;
+ SoupMessage *message;
+ int http_status;
+ const char *uri = "http://www.google.com/m8/feeds/contacts";
+
+ session = soup_session_sync_new ();
+ message = soup_message_new (SOUP_METHOD_GET, uri);
+
+ http_status = soup_session_send_message (session, message);
+ __debug__ ("%s: HTTP %d (%s)",
+ G_STRFUNC,
+ http_status,
+ soup_status_get_phrase (http_status));
+ g_object_unref (message);
+ g_object_unref (session);
+
+ /* Everything below 100 means we can't reach www.google.com */
+ return (http_status >= 100);
+}
+
+static char*
+type_from_google_rel_label (const char* rel, const char *label)
+{
+ if (rel) {
+ char *type;
+ type = g_strrstr (rel, "#");
+ if (NULL == type)
+ return NULL;
+ return g_ascii_strup (type + 1, -1);
+ }
+ if (label) {
+ return g_strdup_printf ("X-%s", label);
+ }
+ return NULL;
+}
+
+static void
+google_rel_label_from_type (const char* type, char **rel, char **label)
+{
+ const char *format = "http://schemas.google.com/g/2005#%s";
+
+ *label = NULL;
+ *rel = NULL;
+ if (NULL == type) {
+ *rel = g_strdup_printf (format, "other");
+ return;
+ }
+
+ if (0 == strcmp (type, "WORK")) {
+ *rel = g_strdup_printf (format, "work");
+ return;
+ }
+ if (0 == strcmp (type, "HOME")) {
+ *rel = g_strdup_printf (format, "home");
+ return;
+ }
+
+ if (0 == strncmp (type, "X-", MIN (2, strlen (type)))) {
+ *label = g_strdup (type + 2);
+ return;
+ }
+
+ *rel = g_strdup_printf (format, "other");
+}
+
+static gboolean
+is_known_google_im_protocol (const char *protocol)
+{
+ const char *known_protocols[] =
+ {
+ "AIM", "MSN", "YAHOO", "SKYPE", "QQ",
+ "GOOGLE_TALK", "ICQ", "JABBER"
+ };
+ int i;
+
+ if (NULL == protocol)
+ return FALSE;
+
+ for (i = 0; i < G_N_ELEMENTS (known_protocols); i++) {
+ if (0 == strcmp (known_protocols[i], protocol))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static char*
+field_name_from_google_im_protocol (const char* google_protocol)
+{
+ char *protocol;
+ if (NULL == google_protocol)
+ return NULL;
+
+ protocol = g_strrstr (google_protocol, "#");
+ if (NULL == protocol)
+ return NULL;
+ return g_strdup_printf ("X-%s", protocol + 1);
+}
+
+static char*
+google_im_protocol_from_field_name (const char* field_name)
+{
+ const char *format = "http://schemas.google.com/g/2005#%s";
+
+ if (NULL == field_name ||
+ strlen (field_name) < 3) {
+ return NULL;
+ }
+
+ return g_strdup_printf (format, field_name + 2);
+}
+
+static EVCardAttribute*
+attribute_from_gdata_entry_email_address (GDataEntryEmailAddress *email)
+{
+ EVCardAttribute *attr;
+ EVCardAttributeParam *param;
+ char *type;
+
+ if (NULL == email || NULL == email->address)
+ return NULL;;
+
+ attr = e_vcard_attribute_new (NULL, EVC_EMAIL);
+ type = type_from_google_rel_label (email->rel, email->label);
+ if (type) {
+ param = e_vcard_attribute_param_new ("TYPE");
+ e_vcard_attribute_add_param_with_value (attr, param, type);
+ g_free (type);
+ }
+ e_vcard_attribute_add_value (attr, email->address);
+ return attr;
+}
+
+static EVCardAttribute*
+attribute_from_gdata_entry_im_address (GDataEntryIMAddress *im)
+{
+ EVCardAttribute *attr;
+ EVCardAttributeParam *param;
+ char *type;
+ char *field_name;
+
+ if (NULL == im || NULL == im->address)
+ return NULL;;
+
+ field_name = field_name_from_google_im_protocol (im->protocol);
+ if (NULL == field_name)
+ return NULL;
+
+ attr = e_vcard_attribute_new (NULL, field_name);
+ type = type_from_google_rel_label (im->rel, im->label);
+ if (type) {
+ param = e_vcard_attribute_param_new ("TYPE");
+ e_vcard_attribute_add_param_with_value (attr, param, type);
+ g_free (type);
+ }
+ e_vcard_attribute_add_value (attr, im->address);
+ return attr;
+}
+
+static EVCardAttribute*
+attribute_from_gdata_entry_phone_number (GDataEntryPhoneNumber *number)
+{
+ EVCardAttribute *attr;
+ EVCardAttributeParam *param;
+ char *type;
+
+ if (NULL == number || NULL == number->number)
+ return NULL;;
+
+ attr = e_vcard_attribute_new (NULL, EVC_TEL);
+ /* TODO: This needs more work */
+ type = type_from_google_rel_label (number->rel, number->label);
+ if (type) {
+ param = e_vcard_attribute_param_new ("TYPE");
+ e_vcard_attribute_add_param_with_value (attr, param, type);
+ g_free (type);
+ }
+ e_vcard_attribute_add_value (attr, number->number);
+ return attr;
+}
+
+static EVCardAttribute*
+attribute_from_gdata_entry_postal_address (GDataEntryPostalAddress *address)
+{
+ EVCardAttribute *attr;
+ EVCardAttributeParam *param;
+ char *type;
+
+ if (NULL == address || NULL == address->address)
+ return NULL;;
+
+ attr = e_vcard_attribute_new (NULL, EVC_LABEL);
+ /* TODO: This needs more work */
+ type = type_from_google_rel_label (address->rel, address->label);
+ if (type) {
+ param = e_vcard_attribute_param_new ("TYPE");
+ e_vcard_attribute_add_param_with_value (attr, param, type);
+ g_free (type);
+ }
+ e_vcard_attribute_add_value (attr, address->address);
+ return attr;
+}
+
+static GDataEntryEmailAddress*
+gdata_entry_email_address_from_attribute (EVCardAttribute *attr, gboolean primary)
+{
+ GDataEntryEmailAddress *email = NULL;
+ GList *values;
+
+ values = e_vcard_attribute_get_values (attr);
+ if (values) {
+ GList *param_values;
+ const char *type;
+
+ param_values = e_vcard_attribute_get_param (attr, "TYPE");
+ type = param_values ? param_values->data : NULL;
+ email = g_new0 (GDataEntryEmailAddress, 1);
+ email->address = g_strdup (values->data);
+ google_rel_label_from_type (type, &email->rel, &email->label);
+ email->primary = primary;
+ }
+
+ return email;
+}
+
+static GDataEntryIMAddress*
+gdata_entry_im_address_from_attribute (EVCardAttribute *attr, gboolean primary)
+{
+ GDataEntryIMAddress *im = NULL;
+ GList *values;
+ const char *name;
+
+ name = e_vcard_attribute_get_name (attr);
+
+ values = e_vcard_attribute_get_values (attr);
+ if (values) {
+ GList *param_values;
+ const char *type;
+
+ param_values = e_vcard_attribute_get_param (attr, "TYPE");
+ type = param_values ? param_values->data : NULL;
+ im = g_new0 (GDataEntryIMAddress, 1);
+ im->address = g_strdup (values->data);
+ google_rel_label_from_type (type, &im->rel, &im->label);
+ im->primary = primary;
+ im->protocol = google_im_protocol_from_field_name (name);
+ }
+
+ return im;
+}
+
+static GDataEntryPhoneNumber*
+gdata_entry_phone_number_from_attribute (EVCardAttribute *attr, gboolean primary)
+{
+ GDataEntryPhoneNumber *number = NULL;
+ GList *values;
+
+ values = e_vcard_attribute_get_values (attr);
+ if (values) {
+ GList *param_values;
+ const char *type;
+
+ param_values = e_vcard_attribute_get_param (attr, "TYPE");
+ type = param_values ? param_values->data : NULL;
+ number = g_new0 (GDataEntryPhoneNumber, 1);
+ number->number = g_strdup (values->data);
+ /* TODO: this needs more work */
+ google_rel_label_from_type (type, &number->rel, &number->label);
+ number->primary = primary;
+ }
+
+ return number;
+}
+
+static GDataEntryPostalAddress*
+gdata_entry_postal_address_from_attribute (EVCardAttribute *attr, gboolean primary)
+{
+ GDataEntryPostalAddress *address = NULL;
+ GList *values;
+
+ values = e_vcard_attribute_get_values (attr);
+ if (values) {
+ GList *param_values;
+ const char *type;
+
+ param_values = e_vcard_attribute_get_param (attr, "TYPE");
+ type = param_values ? param_values->data : NULL;
+ address = g_new0 (GDataEntryPostalAddress, 1);
+ address->address = g_strdup (values->data);
+ google_rel_label_from_type (type, &address->rel, &address->label);
+ address->primary = primary;
+ }
+
+ return address;
+}
Added: trunk/addressbook/backends/google/util.h
==============================================================================
--- (empty file)
+++ trunk/addressbook/backends/google/util.h Mon Jul 21 03:57:49 2008
@@ -0,0 +1,52 @@
+/* util.h - Google contact backend utility functions.
+ *
+ * Copyright (C) 2008 Joergen Scheibengruber
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Joergen Scheibengruber <joergen.scheibengruber AT googlemail.com>
+ */
+#ifndef __UTIL_H__
+#define __UTIL_H__
+
+#include <libebook/e-vcard.h>
+#include <libebook/e-contact.h>
+#include <servers/google/libgdata/gdata-entry.h>
+
+char* vcard_from_gdata_entry (GDataEntry *entry);
+EVCard* e_vcard_from_gdata_entry (GDataEntry *entry);
+EContact* e_contact_from_gdata_entry (GDataEntry *entry);
+
+GDataEntry* gdata_entry_create_from_vcard (const char *vcard_str);
+GDataEntry* gdata_entry_create_from_e_vcard (EVCard *vcard);
+gboolean gdata_entry_update_from_vcard (GDataEntry *entry,
+ const char *vcard_str);
+gboolean gdata_entry_update_from_e_vcard (GDataEntry *entry,
+ EVCard *vcard);
+
+
+char* build_uri (const char *base_uri, ...);
+char* build_base_uri (const char *username);
+
+gboolean test_repository_availability (void);
+
+extern gboolean __e_book_backend_google_debug__;
+
+#define __debug__(...) (__e_book_backend_google_debug__ ? \
+ g_log (G_LOG_DOMAIN, \
+ G_LOG_LEVEL_DEBUG, \
+ __VA_ARGS__) : 0 )
+
+#endif
Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in (original)
+++ trunk/configure.in Mon Jul 21 03:57:49 2008
@@ -1667,6 +1667,7 @@
addressbook/backends/file/Makefile
addressbook/backends/vcf/Makefile
addressbook/backends/ldap/Makefile
+addressbook/backends/google/Makefile
addressbook/backends/groupwise/Makefile
addressbook/tests/Makefile
addressbook/tests/ebook/Makefile
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]