From c8429cddf96238a5849cc61e95347853424b5182 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Thu, 5 Apr 2012 00:22:02 -0400 Subject: [PATCH] Add 'google-backend' module. --- configure.ac | 1 + modules/Makefile.am | 1 + modules/google-backend/Makefile.am | 29 ++ modules/google-backend/module-google-backend.c | 448 +++++++++++++++++++++++++ 4 files changed, 479 insertions(+) create mode 100644 modules/google-backend/Makefile.am create mode 100644 modules/google-backend/module-google-backend.c diff --git a/configure.ac b/configure.ac index 1582361..2489184 100644 --- a/configure.ac +++ b/configure.ac @@ -1663,6 +1663,7 @@ libedataserver/libedataserver.pc libedataserverui/Makefile libedataserverui/libedataserverui.pc modules/Makefile +modules/google-backend/Makefile modules/online-accounts/Makefile private/Makefile services/Makefile diff --git a/modules/Makefile.am b/modules/Makefile.am index 6f7cf42..5c84f5b 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -5,6 +5,7 @@ ONLINE_ACCOUNTS_DIR = online-accounts endif SUBDIRS = \ + google-backend \ $(ONLINE_ACCOUNTS_DIR) \ $(NULL) diff --git a/modules/google-backend/Makefile.am b/modules/google-backend/Makefile.am new file mode 100644 index 0000000..9a046dc --- /dev/null +++ b/modules/google-backend/Makefile.am @@ -0,0 +1,29 @@ +NULL = + +module_LTLIBRARIES = module-google-backend.la + +module_google_backend_la_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -I$(top_srcdir) \ + -DG_LOG_DOMAIN=\"module-google-backend\" \ + $(E_BACKEND_CFLAGS) \ + $(E_DATA_SERVER_CFLAGS) \ + $(NULL) + +module_google_backend_la_SOURCES = \ + module-google-backend.c \ + $(NULL) + +module_google_backend_la_LIBADD = \ + $(top_builddir)/libebackend/libebackend-1.2.la \ + $(top_builddir)/libedataserver/libedataserver-1.2.la \ + $(top_builddir)/camel/libcamel-1.2.la \ + $(E_BACKEND_LIBS) \ + $(E_DATA_SERVER_LIBS) \ + $(NULL) + +module_google_backend_la_LDFLAGS = \ + -module -avoid-version $(NO_UNDEFINED) \ + $(NULL) + +-include $(top_srcdir)/git.mk diff --git a/modules/google-backend/module-google-backend.c b/modules/google-backend/module-google-backend.c new file mode 100644 index 0000000..3da1678 --- /dev/null +++ b/modules/google-backend/module-google-backend.c @@ -0,0 +1,448 @@ +/* + * module-google-backend.c + * + * 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 of the License, or (at your option) version 3. + * + * 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 the program; if not, see + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* Standard GObject macros */ +#define E_TYPE_GOOGLE_BACKEND \ + (e_google_backend_get_type ()) +#define E_GOOGLE_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_GOOGLE_BACKEND, EGoogleBackend)) + +/* Just for readability... */ +#define METHOD(x) (CAMEL_NETWORK_SECURITY_METHOD_##x) + +/* IMAP Configuration Details */ +#define GOOGLE_IMAP_BACKEND_NAME "imapx" +#define GOOGLE_IMAP_HOST "imap.gmail.com" +#define GOOGLE_IMAP_PORT 993 +#define GOOGLE_IMAP_SECURITY_METHOD METHOD (SSL_ON_ALTERNATE_PORT) + +/* SMTP Configuration Details */ +#define GOOGLE_SMTP_BACKEND_NAME "smtp" +#define GOOGLE_SMTP_HOST "smtp.gmail.com" +#define GOOGLE_SMTP_PORT 587 +#define GOOGLE_SMTP_SECURITY_METHOD METHOD (STARTTLS_ON_STANDARD_PORT) + +/* Calendar Configuration Details */ +#define GOOGLE_CALENDAR_BACKEND_NAME "caldav" +#define GOOGLE_CALENDAR_HOST "www.google.com" +#define GOOGLE_CALENDAR_CALDAV_PATH "/calendar/dav/%s/events" + +/* Contacts Configuration Details */ +#define GOOGLE_CONTACTS_BACKEND_NAME "google" + +typedef struct _EGoogleBackend EGoogleBackend; +typedef struct _EGoogleBackendClass EGoogleBackendClass; + +typedef struct _EGoogleBackendFactory EGoogleBackendFactory; +typedef struct _EGoogleBackendFactoryClass EGoogleBackendFactoryClass; + +struct _EGoogleBackend { + ECollectionBackend parent; +}; + +struct _EGoogleBackendClass { + ECollectionBackendClass parent_class; +}; + +struct _EGoogleBackendFactory { + ECollectionBackendFactory parent; +}; + +struct _EGoogleBackendFactoryClass { + ECollectionBackendFactoryClass parent_class; +}; + +/* Module Entry Points */ +void e_module_load (GTypeModule *type_module); +void e_module_unload (GTypeModule *type_module); + +/* Forward Declarations */ +GType e_google_backend_get_type (void); +GType e_google_backend_factory_get_type (void); + +G_DEFINE_DYNAMIC_TYPE ( + EGoogleBackend, + e_google_backend, + E_TYPE_COLLECTION_BACKEND) + +G_DEFINE_DYNAMIC_TYPE ( + EGoogleBackendFactory, + e_google_backend_factory, + E_TYPE_COLLECTION_BACKEND_FACTORY) + +static void +google_backend_add_calendar (ECollectionBackend *backend) +{ + ESource *source; + ESource *collection_source; + ESourceRegistryServer *server; + ESourceExtension *extension; + ESourceCollection *collection_extension; + const gchar *backend_name; + const gchar *extension_name; + const gchar *identity; + gchar *path; + + /* FIXME As a future enhancement, we should query Google + * for a list of user calendars and add them to the + * collection with matching display names and colors. */ + + collection_source = e_backend_get_source (E_BACKEND (backend)); + + source = e_collection_backend_new_child (backend, "Calendar"); + e_source_set_display_name (source, _("Calendar")); + + collection_extension = e_source_get_extension ( + collection_source, E_SOURCE_EXTENSION_COLLECTION); + + /* Configure the calendar source. */ + + backend_name = GOOGLE_CALENDAR_BACKEND_NAME; + + extension_name = E_SOURCE_EXTENSION_CALENDAR; + extension = e_source_get_extension (source, extension_name); + + e_source_backend_set_backend_name ( + E_SOURCE_BACKEND (extension), backend_name); + + extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; + extension = e_source_get_extension (source, extension_name); + + e_source_authentication_set_host ( + E_SOURCE_AUTHENTICATION (extension), + GOOGLE_CALENDAR_HOST); + + g_object_bind_property ( + collection_extension, "identity", + extension, "user", + G_BINDING_SYNC_CREATE); + + extension_name = E_SOURCE_EXTENSION_SECURITY; + extension = e_source_get_extension (source, extension_name); + + e_source_security_set_secure ( + E_SOURCE_SECURITY (extension), TRUE); + + extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND; + extension = e_source_get_extension (source, extension_name); + + identity = e_source_collection_get_identity (collection_extension); + path = g_strdup_printf (GOOGLE_CALENDAR_CALDAV_PATH, identity); + e_source_webdav_set_resource_path ( + E_SOURCE_WEBDAV (extension), path); + g_free (path); + + server = e_collection_backend_ref_server (backend); + e_source_registry_server_add_source (server, source); + g_object_unref (server); + + g_object_unref (source); +} + +static void +google_backend_add_contacts (ECollectionBackend *backend) +{ + ESource *source; + ESource *collection_source; + ESourceRegistryServer *server; + ESourceExtension *extension; + ESourceCollection *collection_extension; + const gchar *backend_name; + const gchar *extension_name; + + collection_source = e_backend_get_source (E_BACKEND (backend)); + + source = e_collection_backend_new_child (backend, "Contacts"); + e_source_set_display_name (source, _("Contacts")); + + /* Add the address book source to the collection. */ + collection_extension = e_source_get_extension ( + collection_source, E_SOURCE_EXTENSION_COLLECTION); + + /* Configure the address book source. */ + + backend_name = GOOGLE_CONTACTS_BACKEND_NAME; + + extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK; + extension = e_source_get_extension (source, extension_name); + + e_source_backend_set_backend_name ( + E_SOURCE_BACKEND (extension), backend_name); + + extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; + extension = e_source_get_extension (source, extension_name); + + g_object_bind_property ( + collection_extension, "identity", + extension, "user", + G_BINDING_SYNC_CREATE); + + extension_name = E_SOURCE_EXTENSION_SECURITY; + extension = e_source_get_extension (source, extension_name); + + e_source_security_set_secure ( + E_SOURCE_SECURITY (extension), TRUE); + + server = e_collection_backend_ref_server (backend); + e_source_registry_server_add_source (server, source); + g_object_unref (server); + + g_object_unref (source); +} + +static void +google_backend_populate (ECollectionBackend *backend) +{ + GList *list; + + list = e_collection_backend_list_calendar_sources (backend); + if (list == NULL) + google_backend_add_calendar (backend); + g_list_free_full (list, (GDestroyNotify) g_object_unref); + + list = e_collection_backend_list_contacts_sources (backend); + if (list == NULL) + google_backend_add_contacts (backend); + g_list_free_full (list, (GDestroyNotify) g_object_unref); + + /* Chain up to parent's populate() method. */ + E_COLLECTION_BACKEND_CLASS (e_google_backend_parent_class)-> + populate (backend); +} + +static void +google_backend_child_added (ECollectionBackend *backend, + ESource *child_source) +{ + ESource *collection_source; + const gchar *extension_name; + gboolean is_mail = FALSE; + + collection_source = e_backend_get_source (E_BACKEND (backend)); + + extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; + is_mail |= e_source_has_extension (child_source, extension_name); + + extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY; + is_mail |= e_source_has_extension (child_source, extension_name); + + extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT; + is_mail |= e_source_has_extension (child_source, extension_name); + + /* Synchronize mail-related display names with the collection. */ + if (is_mail) + g_object_bind_property ( + collection_source, "display-name", + child_source, "display-name", + G_BINDING_SYNC_CREATE); + + /* Synchronize mail-related user with the collection identity. */ + extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; + if (is_mail && e_source_has_extension (child_source, extension_name)) { + ESourceAuthentication *auth_child_extension; + ESourceCollection *collection_extension; + + extension_name = E_SOURCE_EXTENSION_COLLECTION; + collection_extension = e_source_get_extension ( + collection_source, extension_name); + + extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; + auth_child_extension = e_source_get_extension ( + child_source, extension_name); + + g_object_bind_property ( + collection_extension, "identity", + auth_child_extension, "user", + G_BINDING_SYNC_CREATE); + } + + /* Chain up to parent's child_added() method. */ + E_COLLECTION_BACKEND_CLASS (e_google_backend_parent_class)-> + child_added (backend, child_source); +} + +static void +e_google_backend_class_init (EGoogleBackendClass *class) +{ + ECollectionBackendClass *backend_class; + + backend_class = E_COLLECTION_BACKEND_CLASS (class); + backend_class->populate = google_backend_populate; + backend_class->child_added = google_backend_child_added; +} + +static void +e_google_backend_class_finalize (EGoogleBackendClass *class) +{ +} + +static void +e_google_backend_init (EGoogleBackend *backend) +{ +} + +static void +google_backend_prepare_mail_account_source (ESource *source) +{ + ESourceCamel *camel_extension; + ESourceExtension *extension; + CamelSettings *settings; + const gchar *backend_name; + const gchar *extension_name; + + backend_name = GOOGLE_IMAP_BACKEND_NAME; + + extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; + extension = e_source_get_extension (source, extension_name); + + e_source_backend_set_backend_name ( + E_SOURCE_BACKEND (extension), backend_name); + + extension_name = e_source_camel_get_extension_name (backend_name); + camel_extension = e_source_get_extension (source, extension_name); + settings = e_source_camel_get_settings (camel_extension); + + /* The "auth-mechanism" should be determined elsewhere. */ + + camel_network_settings_set_host ( + CAMEL_NETWORK_SETTINGS (settings), + GOOGLE_IMAP_HOST); + + camel_network_settings_set_port ( + CAMEL_NETWORK_SETTINGS (settings), + GOOGLE_IMAP_PORT); + + camel_network_settings_set_security_method ( + CAMEL_NETWORK_SETTINGS (settings), + GOOGLE_IMAP_SECURITY_METHOD); +} + +static void +google_backend_prepare_mail_transport_source (ESource *source) +{ + ESourceCamel *camel_extension; + ESourceExtension *extension; + CamelSettings *settings; + const gchar *backend_name; + const gchar *extension_name; + + /* Configure the mail transport source. */ + + backend_name = GOOGLE_SMTP_BACKEND_NAME; + + extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT; + extension = e_source_get_extension (source, extension_name); + + e_source_backend_set_backend_name ( + E_SOURCE_BACKEND (extension), backend_name); + + extension_name = e_source_camel_get_extension_name (backend_name); + camel_extension = e_source_get_extension (source, extension_name); + settings = e_source_camel_get_settings (camel_extension); + + /* The "auth-mechanism" should be determined elsewhere. */ + + camel_network_settings_set_host ( + CAMEL_NETWORK_SETTINGS (settings), + GOOGLE_SMTP_HOST); + + camel_network_settings_set_port ( + CAMEL_NETWORK_SETTINGS (settings), + GOOGLE_SMTP_PORT); + + camel_network_settings_set_security_method ( + CAMEL_NETWORK_SETTINGS (settings), + GOOGLE_SMTP_SECURITY_METHOD); +} + +static void +google_backend_factory_prepare_mail (ECollectionBackendFactory *factory, + ESource *mail_account_source, + ESource *mail_identity_source, + ESource *mail_transport_source) +{ + ECollectionBackendFactoryClass *parent_class; + + /* Chain up to parent's prepare_mail() method. */ + parent_class = + E_COLLECTION_BACKEND_FACTORY_CLASS ( + e_google_backend_factory_parent_class); + parent_class->prepare_mail ( + factory, + mail_account_source, + mail_identity_source, + mail_transport_source); + + google_backend_prepare_mail_account_source (mail_account_source); + google_backend_prepare_mail_transport_source (mail_transport_source); +} + +static void +e_google_backend_factory_class_init (EGoogleBackendFactoryClass *class) +{ + ECollectionBackendFactoryClass *factory_class; + + factory_class = E_COLLECTION_BACKEND_FACTORY_CLASS (class); + factory_class->factory_name = "google"; + factory_class->backend_type = E_TYPE_GOOGLE_BACKEND; + factory_class->prepare_mail = google_backend_factory_prepare_mail; +} + +static void +e_google_backend_factory_class_finalize (EGoogleBackendFactoryClass *class) +{ +} + +static void +e_google_backend_factory_init (EGoogleBackendFactory *factory) +{ +} + +G_MODULE_EXPORT void +e_module_load (GTypeModule *type_module) +{ + e_google_backend_register_type (type_module); + e_google_backend_factory_register_type (type_module); +} + +G_MODULE_EXPORT void +e_module_unload (GTypeModule *type_module) +{ +} + -- 2.7.4