From f3d74746d20c04d298e47ab3deaaa70ab158773e Mon Sep 17 00:00:00 2001 From: Chenthill Palanisamy Date: Tue, 23 Oct 2007 10:23:31 +0000 Subject: [PATCH] Initial commit for the Google Calendar Interface. 2007-10-23 Chenthill Palanisamy Initial commit for the Google Calendar Interface. * Makefile.am * libgdata/Makefile.am * libgdata-google/Makefile.am * libgdata/gdata-entry.c * libgdata/gdata-entry.h * libgdata/gdata-feed.c * libgdata/gdata-feed.h * libgdata/gdata-service-iface.c * libgdata/gdata-service-iface.h * libgdata/libgdata.pc.in * libgdata-google/gdata-google-service.c * libgdata-google/gdata-google-service.h * libgdata-google/libgdata-google.pc.in Committing on behalf of Ebby Wiselyn svn path=/trunk/; revision=8141 --- servers/google/Makefile.am | 1 + servers/google/libgdata-google/Makefile.am | 37 + .../google/libgdata-google/gdata-google-service.c | 686 +++++++++ .../google/libgdata-google/gdata-google-service.h | 72 + .../google/libgdata-google/libgdata-google.pc.in | 18 + servers/google/libgdata/Makefile.am | 41 + servers/google/libgdata/gdata-entry.c | 1460 ++++++++++++++++++++ servers/google/libgdata/gdata-entry.h | 175 +++ servers/google/libgdata/gdata-feed.c | 676 +++++++++ servers/google/libgdata/gdata-feed.h | 71 + servers/google/libgdata/gdata-service-iface.c | 110 ++ servers/google/libgdata/gdata-service-iface.h | 79 ++ servers/google/libgdata/libgdata.pc.in | 18 + 13 files changed, 3444 insertions(+) create mode 100644 servers/google/Makefile.am create mode 100644 servers/google/libgdata-google/Makefile.am create mode 100644 servers/google/libgdata-google/gdata-google-service.c create mode 100644 servers/google/libgdata-google/gdata-google-service.h create mode 100644 servers/google/libgdata-google/libgdata-google.pc.in create mode 100644 servers/google/libgdata/Makefile.am create mode 100644 servers/google/libgdata/gdata-entry.c create mode 100644 servers/google/libgdata/gdata-entry.h create mode 100644 servers/google/libgdata/gdata-feed.c create mode 100644 servers/google/libgdata/gdata-feed.h create mode 100644 servers/google/libgdata/gdata-service-iface.c create mode 100644 servers/google/libgdata/gdata-service-iface.h create mode 100644 servers/google/libgdata/libgdata.pc.in diff --git a/servers/google/Makefile.am b/servers/google/Makefile.am new file mode 100644 index 0000000..dd73ff2 --- /dev/null +++ b/servers/google/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = libgdata libgdata-google diff --git a/servers/google/libgdata-google/Makefile.am b/servers/google/libgdata-google/Makefile.am new file mode 100644 index 0000000..e482a85 --- /dev/null +++ b/servers/google/libgdata-google/Makefile.am @@ -0,0 +1,37 @@ +INCLUDES = \ + -DG_LOG_DOMAIN=\"libgdata-google\" \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/servers/google/libgdata \ + $(SOUP_CFLAGS) \ + $(E_DATA_SERVER_CFLAGS) + +lib_LTLIBRARIES = libgdata-google-1.2.la + +libgdata_google_1_2_la_SOURCES = \ + gdata-google-service.c \ + gdata-google-service.h + +libgdata_google_1_2_la_LIBADD = \ + $(top_builddir)/servers/google/libgdata/libgdata-1.2.la \ + $(E_DATA_SERVER_LIBS) \ + $(SOUP_LIBS) + +libgdata_google_1_2_la_LDFLAGS = \ + -version-info $(LIBGDATA_GOOGLE_CURRENT):$(LIBGDATA_GOOGLE_REVISION):$(LIBGDATA_GOOGLE_AGE) $(NO_UNDEFINED) + +libgdata_google_includedir = $(privincludedir)/google/gdata-google + +libgdata_google_include_HEADERS = \ + gdata-google-service.h + +%-$(API_VERSION).pc: %.pc + cp $< $@ + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libgdata-google-$(API_VERSION).pc + +EXTRA_DIST = $(pkgconfig_DATA:-$(API_VERSION).pc=.pc.in) + +DISTCLEANFILES = $(pkgconfig_DATA) + diff --git a/servers/google/libgdata-google/gdata-google-service.c b/servers/google/libgdata-google/gdata-google-service.c new file mode 100644 index 0000000..ffd0e7f --- /dev/null +++ b/servers/google/libgdata-google/gdata-google-service.c @@ -0,0 +1,686 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors : + * Ebby Wiselyn + * Jason Willis + * + * Copyright 2007, Novell, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * 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 library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include + +#include +#include + +#define GDATA_GOOGLE_SERVICE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GDATA_TYPE_GOOGLE_SERVICE, GDataGoogleServicePrivate)) + +void gdata_google_service_update_entry_with_link (GDataService *service, GDataEntry *entry, gchar *edit_link); +GDataEntry * gdata_google_service_insert_entry (GDataService *service, const gchar *feed_url, GDataEntry *entry); +void gdata_google_service_delete_entry (GDataService *service, GDataEntry *entry); +GDataFeed * gdata_google_service_get_feed (GDataService *service, const gchar *feed_url); +void gdata_google_service_update_entry (GDataService *service, GDataEntry *entry); +void gdata_google_service_set_credentials (GDataService *service, const gchar *username, const gchar *password); + +typedef struct _GDataGoogleServiceAuth GDataGoogleServiceAuth; +struct _GDataGoogleServiceAuth { + /* Authentication Information */ + gchar *username; + gchar *password; + + gchar *token; +}; + +struct _GDataGoogleServicePrivate { + /* Session information */ + gchar *name; + gchar *agent; + + SoupSession *soup_session; + GDataGoogleServiceAuth *auth; + + gboolean dispose_has_run; + +}; + +enum { + PROP_0, + PROP_NAME, + PROP_AGENT, +}; + +static const gchar *GOOGLE_CLIENT_LOGIN = "https://www.google.com/accounts/ClientLogin"; +static const gchar *GOOGLE_CLIENT_LOGIN_MSG = "Email=%s&Passwd=%s&service=%s&source=%s"; + +void +gdata_google_service_set_credentials (GDataService *service, const gchar *username, const gchar *password) +{ + GDataGoogleServicePrivate *priv; + GDataGoogleServiceAuth *auth; + + g_return_if_fail (service != NULL); + g_return_if_fail (GDATA_IS_GOOGLE_SERVICE(service)); + + priv = GDATA_GOOGLE_SERVICE_GET_PRIVATE(GDATA_GOOGLE_SERVICE(service)); + auth = (GDataGoogleServiceAuth *)priv->auth; + + auth->username = g_strdup(username); + auth->password = g_strdup(password); +} + +static gboolean +service_is_authenticated (GDataGoogleService *service) +{ + GDataGoogleServicePrivate *priv; + GDataGoogleServiceAuth *auth; + + priv = GDATA_GOOGLE_SERVICE_GET_PRIVATE(service); + auth = (GDataGoogleServiceAuth *)priv->auth; + + if (auth->token == NULL) + return FALSE; + else + return TRUE; +} + +static gchar * +service_authenticate (GDataGoogleService *service) +{ + GDataGoogleServicePrivate *priv; + GDataGoogleServiceAuth *auth; + SoupMessage *msg; + gchar *request_body; + gchar *request_body_encoded; + gchar *token = NULL; + gchar *auth_begin = NULL; + gchar *auth_end = NULL; + + priv = GDATA_GOOGLE_SERVICE_GET_PRIVATE(service); + auth = (GDataGoogleServiceAuth *)priv->auth; + + msg = soup_message_new(SOUP_METHOD_POST, GOOGLE_CLIENT_LOGIN); + request_body = g_strdup_printf(GOOGLE_CLIENT_LOGIN_MSG, auth->username, + auth->password, + priv->name, + priv->agent); + + request_body_encoded = soup_uri_encode(request_body,NULL); + soup_message_set_http_version(msg, SOUP_HTTP_1_0); + + soup_message_set_request (msg, "application/x-www-form-urlencoded", + SOUP_BUFFER_USER_OWNED, + request_body_encoded, + strlen(request_body_encoded)); + + soup_session_send_message(priv->soup_session, msg); + + if (msg->response.length) { + auth_begin = strstr(msg->response.body, "Auth="); + + if (!auth_begin) + return "FAILURE"; + + auth_begin = auth_begin; + auth_end = strstr(auth_begin, "\n") - 5; + + if (auth_begin && strlen(auth_begin) > 5) { + token = g_strndup(auth_begin + strlen("Auth="), auth_end - auth_begin); + } + } + + auth->token = token; + if (!token) + return "FAILURE"; + + g_free(request_body); + g_free(request_body_encoded); + + if(SOUP_IS_MESSAGE(msg)) + g_object_unref(msg); + + return "SUCCESS"; +} + + +/** + * + * gdata_google_service_get_feed: + * @service A GDataService Object + * @feed_url Feed Url , the private url to send request to , needs authentication + * @entry A GDataFeed Object + * returns the newly inserted entry + * + **/ + +GDataFeed * +gdata_google_service_get_feed (GDataService *service, const gchar *feed_url) +{ + GDataFeed *feed = NULL; + GDataGoogleServicePrivate *priv; + GDataGoogleServiceAuth *auth; + SoupSession *soup_session; + SoupMessage *msg; + gchar *status; + + g_return_val_if_fail(service != NULL, NULL); + g_return_val_if_fail(GDATA_IS_GOOGLE_SERVICE(service),NULL); + + if (!service_is_authenticated( GDATA_GOOGLE_SERVICE(service) )) { + status = service_authenticate(GDATA_GOOGLE_SERVICE(service)); + if (g_strcasecmp(status, "SUCCESS")) { + return NULL; + } + } + + priv = GDATA_GOOGLE_SERVICE_GET_PRIVATE( GDATA_GOOGLE_SERVICE(service) ); + auth = (GDataGoogleServiceAuth *)priv->auth; + soup_session = (SoupSession *)priv->soup_session; + msg = NULL; + msg = soup_message_new(SOUP_METHOD_GET, feed_url); + + soup_message_add_header(msg->request_headers, + "Authorization", (gchar *)g_strdup_printf("GoogleLogin auth=%s", auth->token)); + + soup_session_send_message(soup_session, msg); + if (msg->response.length) { + feed = gdata_feed_new_from_xml(msg->response.body, msg->response.length); + } + + if (SOUP_IS_MESSAGE(msg)) + g_object_unref(msg); + + return feed; +} + + +/** + * + * gdata_google_service_insert_entry: + * @service A #GDataService Object + * @feed_url Feed Url , this is the private url of the author which requires authentication + * @entry A #GDataEntry Object + * returns the newly inserted entry + * + **/ +GDataEntry * +gdata_google_service_insert_entry (GDataService *service, const gchar *feed_url, GDataEntry *entry) +{ + GDataGoogleServicePrivate *priv; + GDataGoogleServiceAuth *auth; + GDataEntry *updated_entry; + SoupSession *soup_session; + SoupMessage *msg; + gchar *status; + gchar *entry_xml; + + g_return_val_if_fail(service != NULL, NULL); + g_return_val_if_fail(GDATA_IS_GOOGLE_SERVICE(service), NULL); + + if (!service_is_authenticated(GDATA_GOOGLE_SERVICE(service))) { + status = service_authenticate(GDATA_GOOGLE_SERVICE(service)); + + if (g_strcasecmp(status,"SUCCESS")) + return NULL; + } + + entry_xml = gdata_entry_generate_xml (entry); + priv = GDATA_GOOGLE_SERVICE_GET_PRIVATE(GDATA_GOOGLE_SERVICE(service)); + auth = (GDataGoogleServiceAuth *)priv->auth; + soup_session = (SoupSession *)priv->soup_session; + + msg = soup_message_new(SOUP_METHOD_POST, feed_url); + soup_message_set_http_version (msg, SOUP_HTTP_1_0); + + soup_message_add_header(msg->request_headers, + "Authorization", + (gchar *)g_strdup_printf("GoogleLogin auth=%s", + auth->token)); + + soup_message_set_request (msg, + "application/atom+xml", + SOUP_BUFFER_USER_OWNED, + entry_xml, + strlen(entry_xml)); + + soup_session_send_message(soup_session, msg); + + if (!msg->response.length) { + g_message ("\n %s, %s, Response Length NULL when inserting entry", G_STRLOC, G_STRFUNC); + return NULL; + } + + updated_entry = gdata_entry_new_from_xml (msg->response.body); + if (!GDATA_IS_ENTRY(entry)) { + g_critical ("\n %s, %s, Error During Insert Entry ", G_STRLOC, G_STRFUNC); + return NULL; + } + + if (SOUP_IS_MESSAGE(msg)) + g_object_unref (msg); + + if (entry_xml) + g_free (entry_xml); + + return updated_entry; +} + + +/** + * + * gdata_google_service_delete_entry: + * @service A #GDataService Object + * @feed_url Feed Url , this is the private url of the author which requires authentication + * @entry A #GDataEntry Object + * Removes the entry + * + **/ +void +gdata_google_service_delete_entry (GDataService *service, GDataEntry *entry) +{ + GDataGoogleServiceAuth *auth; + GDataGoogleServicePrivate *priv; + SoupSession *soup_session; + SoupMessage *msg; + const gchar *entry_edit_url; + xmlChar *status; + + g_return_if_fail (service !=NULL); + g_return_if_fail (GDATA_IS_GOOGLE_SERVICE(service)); + + if (!service_is_authenticated (GDATA_GOOGLE_SERVICE(service))) { + status = (xmlChar *)service_authenticate (GDATA_GOOGLE_SERVICE(service)); + if (g_strcasecmp((gchar *)status, "SUCCESS")) + return ; + } + + entry_edit_url = gdata_entry_get_edit_link (entry); + priv = GDATA_GOOGLE_SERVICE_GET_PRIVATE (GDATA_GOOGLE_SERVICE (service)); + auth = (GDataGoogleServiceAuth *) priv->auth; + soup_session = (SoupSession *)priv->soup_session; + + msg = soup_message_new (SOUP_METHOD_DELETE, entry_edit_url); + soup_message_add_header (msg->request_headers, + "Authorization", + (gchar *)g_strdup_printf ("GoogleLogin auth=%s", + auth->token)); + soup_session_send_message (soup_session, msg); + + if (SOUP_IS_MESSAGE(msg)) + g_object_unref (msg); +} + +/** + * + * gdata_google_service_update_entry: + * @service A GDataService Object + * @feed_url Feed Url , this is the private url of the author which requires authentication + * @entry A GDataEntry Object + * updates the entry + * + **/ +void +gdata_google_service_update_entry (GDataService *service, GDataEntry *entry) +{ + GDataGoogleServiceAuth *auth; + GDataGoogleServicePrivate *priv; + SoupSession *soup_session; + SoupMessage *msg; + gchar *status; + gchar *entry_xml; + const gchar *entry_edit_url; + + g_return_if_fail (service !=NULL); + g_return_if_fail (GDATA_IS_GOOGLE_SERVICE (service)); + + if (!service_is_authenticated (GDATA_GOOGLE_SERVICE (service))) { + status = service_authenticate (GDATA_GOOGLE_SERVICE (service)); + if (g_strcasecmp (status, "SUCCESS")) + return; + } + + entry_xml = gdata_entry_generate_xml (entry); + priv = GDATA_GOOGLE_SERVICE_GET_PRIVATE (GDATA_GOOGLE_SERVICE (service)); + auth = (GDataGoogleServiceAuth *)priv->auth; + soup_session = (SoupSession *)priv->soup_session; + + entry_edit_url = g_strdup (gdata_entry_get_edit_link (entry)); + msg = soup_message_new (SOUP_METHOD_PUT, entry_edit_url); + + if (!msg) { + g_message ("\n MSG Fails %s", G_STRLOC); + return; + } + + soup_message_add_header (msg->request_headers, + "Authorization", + (gchar *)g_strdup_printf ("GoogleLogin auth=%s", + auth->token)); + soup_message_set_request (msg, + "application/atom+xml", + SOUP_BUFFER_USER_OWNED, + entry_xml, + strlen(entry_xml)); + + soup_session_send_message (soup_session, msg); + + if (SOUP_IS_MESSAGE(msg)) + g_object_unref (msg); + if (entry_xml) + g_free (entry_xml); +} + + +/** + * + * gdata_google_update_entry_with_link: + * @service A #GDataService Object + * @edit_link url of the edit link of the entry + * @entry A #GDataEntry Object + * Updates the entry + * + **/ +void +gdata_google_service_update_entry_with_link (GDataService *service, GDataEntry *entry, gchar *edit_link) +{ + GDataGoogleServiceAuth *auth; + GDataGoogleServicePrivate *priv; + SoupSession *soup_session; + SoupMessage *msg; + gchar *status; + gchar *entry_xml; + + g_return_if_fail (service !=NULL); + g_return_if_fail (GDATA_IS_GOOGLE_SERVICE (service)); + + if (!service_is_authenticated (GDATA_GOOGLE_SERVICE(service))) { + status = service_authenticate (GDATA_GOOGLE_SERVICE(service)); + if (g_strcasecmp (status, "SUCCESS")) + return; + } + + entry_xml = gdata_entry_generate_xml (entry); + priv = GDATA_GOOGLE_SERVICE_GET_PRIVATE (GDATA_GOOGLE_SERVICE(service)); + auth = (GDataGoogleServiceAuth *)priv->auth; + soup_session = (SoupSession *)priv->soup_session; + + msg = soup_message_new (SOUP_METHOD_PUT, edit_link); + + if (!msg) { + g_message ("\n Message Corrupt %s", G_STRLOC); + return; + } + + soup_message_add_header (msg->request_headers, + "Authorization", + (gchar *)g_strdup_printf ("GoogleLogin auth=%s", + auth->token)); + + soup_message_set_request (msg, + "application/atom+xml", + SOUP_BUFFER_USER_OWNED, + entry_xml, + strlen(entry_xml)); + + soup_session_send_message (soup_session, msg); + + if (SOUP_IS_MESSAGE(msg)) + g_object_unref (msg); + if (entry_xml) + g_free (entry_xml); +} + +static void gdata_google_service_iface_init(gpointer g_iface, gpointer iface_data) +{ + GDataServiceIface *iface = (GDataServiceIface *)g_iface; + + iface->set_credentials = gdata_google_service_set_credentials; + iface->get_feed = gdata_google_service_get_feed; + iface->insert_entry = gdata_google_service_insert_entry; + iface->delete_entry = gdata_google_service_delete_entry; + iface->update_entry = gdata_google_service_update_entry; + iface->update_entry_with_link = gdata_google_service_update_entry_with_link; + return; +} + +static void gdata_google_service_instance_init(GTypeInstance *instance, + gpointer g_class) +{ + GDataGoogleServicePrivate *priv; + GDataGoogleService *self = (GDataGoogleService *)instance; + + /* Private data set by g_type_class_add_private */ + priv = GDATA_GOOGLE_SERVICE_GET_PRIVATE(self); + priv->dispose_has_run = FALSE; + + priv->name = NULL; + priv->agent = NULL; + + + priv->auth = g_new0(GDataGoogleServiceAuth,1); + priv->auth->username = NULL; + priv->auth->password = NULL; + priv->auth->token = NULL; + + priv->soup_session = soup_session_sync_new(); +} + +static void gdata_google_service_dispose(GObject *obj) +{ + GObjectClass *parent_class; + GDataGoogleServiceClass *klass; + + GDataGoogleService *self = (GDataGoogleService *)obj; + GDataGoogleServicePrivate *priv = GDATA_GOOGLE_SERVICE_GET_PRIVATE(self); + + if (priv->dispose_has_run) { + /* Don't run dispose twice */ + return; + } + + priv->dispose_has_run = TRUE; + + /* Chain up to the parent class */ + klass = GDATA_GOOGLE_SERVICE_CLASS(g_type_class_peek(GDATA_TYPE_GOOGLE_SERVICE)); + parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); + + parent_class->dispose(obj); +} + +static void gdata_google_service_finalize(GObject *obj) +{ + GDataGoogleServicePrivate *priv; + GDataGoogleServiceAuth *auth; + GDataGoogleService *self = GDATA_GOOGLE_SERVICE(obj); + GObjectClass *parent_class; + GDataGoogleServiceClass *klass; + + priv = GDATA_GOOGLE_SERVICE_GET_PRIVATE(self); + auth = (GDataGoogleServiceAuth *)priv->auth; + + if (priv->name != NULL) + g_free(priv->name); + + if (priv->agent != NULL) + g_free(priv->agent); + + if (auth->username != NULL) + g_free(auth->username); + + if (auth->password) + g_free(auth->password); + + if (auth->token != NULL) { + g_free(auth->token); + } + g_free(auth); + + /* Chain up to the parent class */ + klass = GDATA_GOOGLE_SERVICE_CLASS(g_type_class_peek(GDATA_TYPE_GOOGLE_SERVICE)); + parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); + parent_class->finalize(obj); +} + +static void gdata_google_service_get_property (GObject *obj, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GDataGoogleServicePrivate *priv; + + priv = GDATA_GOOGLE_SERVICE_GET_PRIVATE(obj); + + switch (property_id) { + case PROP_NAME: + g_value_set_string(value, priv->name); + break; + case PROP_AGENT: + g_value_set_string(value, priv->name); + break; + default: + /* Invalid Property */ + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec); + break; + } +} + +static void gdata_google_service_set_property (GObject *obj, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GDataGoogleServicePrivate *priv; + GDataGoogleService *self = (GDataGoogleService *) obj; + + priv = GDATA_GOOGLE_SERVICE_GET_PRIVATE(self); + + switch (property_id) { + case PROP_NAME: + if (priv->name != NULL) + g_free(priv->name); + priv->name = g_value_dup_string(value); + break; + case PROP_AGENT: + if (priv->agent != NULL) + g_free(priv->agent); + priv->agent = g_value_dup_string(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec); + break; + } +} + + +static void gdata_google_service_class_init(gpointer g_class, + gpointer g_class_data) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(g_class); + GDataGoogleServiceClass *klass = GDATA_GOOGLE_SERVICE_CLASS(g_class); + + g_type_class_add_private(klass, sizeof (GDataGoogleServicePrivate)); + + gobject_class->set_property = gdata_google_service_set_property; + gobject_class->get_property = gdata_google_service_get_property; + gobject_class->dispose = gdata_google_service_dispose; + gobject_class->finalize = gdata_google_service_finalize; + + + g_object_class_install_property(gobject_class, PROP_NAME, + g_param_spec_string("name", "Name", + "The name (e.g. 'cl') of the service", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + + g_object_class_install_property(gobject_class, PROP_AGENT, + g_param_spec_string("agent", "Agent", + "The agent (e.g 'evolution', 'tinymail') of the calling program", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + return; +} + + +GType gdata_google_service_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY(type == 0)) + { + static const GTypeInfo info = + { + sizeof (GDataGoogleServiceClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gdata_google_service_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GDataGoogleService), + 0, /* n_preallocs */ + gdata_google_service_instance_init /* instance_init */ + }; + + static const GInterfaceInfo gdata_google_service_iface_info = + { + (GInterfaceInitFunc) gdata_google_service_iface_init, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + + type = g_type_register_static (G_TYPE_OBJECT, + "GDataGoogleServiceType", + &info, 0); + + g_type_add_interface_static (type, GDATA_TYPE_SERVICE, + &gdata_google_service_iface_info); + + } + + return type; +} + + +/*********API******* */ + +/** + * + * gdata_google_service_new: + * @service_name + * @agent + * Returns a new #GDataGoogleService Object + * + **/ +GDataGoogleService * +gdata_google_service_new(const gchar *service_name, const gchar *agent) +{ + return g_object_new(GDATA_TYPE_GOOGLE_SERVICE, + "name", service_name, + "agent",agent, + NULL); +} + diff --git a/servers/google/libgdata-google/gdata-google-service.h b/servers/google/libgdata-google/gdata-google-service.h new file mode 100644 index 0000000..9894358 --- /dev/null +++ b/servers/google/libgdata-google/gdata-google-service.h @@ -0,0 +1,72 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors : + * Ebby Wiselyn + * Jason Willis + * + * Copyright 2007, Novell, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * 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 library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef _GDATA_GOOGLE_SERVICE_H_ +#define _GDATA_GOOGLE_SERVICE_H_ + +#include +#include + +#include "gdata-feed.h" +#include "gdata-entry.h" + +G_BEGIN_DECLS + +#define GDATA_TYPE_GOOGLE_SERVICE (gdata_google_service_get_type()) +#define GDATA_GOOGLE_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GDATA_TYPE_GOOGLE_SERVICE, GDataGoogleService)) +#define GDATA_GOOGLE_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GDATA_TYPE_GOOGLE_SERVICE, GDataGoogleServiceClass)) +#define GDATA_IS_GOOGLE_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GDATA_TYPE_GOOGLE_SERVICE)) +#define GDATA_IS_GOOGLE_SERVICE_CLASS(klass)(G_TYPE_CHECK_CLASS_TYPE((klass), GDATA_TYPE_GOOGLE_SERVICE)) +#define GDATA_GOOGLE_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE((obj), GDATA_TYPE_GOOGLE_SERVICE, GDataGoogleServiceClass)) + +typedef struct _GDataGoogleService GDataGoogleService; +typedef struct _GDataGoogleServiceClass GDataGoogleServiceClass; +typedef struct _GDataGoogleServicePrivate GDataGoogleServicePrivate; + +struct _GDataGoogleService { + GObject parent; + + /* private */ + +}; + +struct _GDataGoogleServiceClass { + GObjectClass parent_class; + + /* Public Methods - Inherited from GDATA_SERVICE_IFACE */ +}; + +GType gdata_google_service_get_type(void); + +/**API******/ + +GDataGoogleService * gdata_google_service_new(const gchar *serviceName, const gchar *agent); +G_END_DECLS + +#endif + + + + + diff --git a/servers/google/libgdata-google/libgdata-google.pc.in b/servers/google/libgdata-google/libgdata-google.pc.in new file mode 100644 index 0000000..e3a8084 --- /dev/null +++ b/servers/google/libgdata-google/libgdata-google.pc.in @@ -0,0 +1,18 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +datarootdir=@datarootdir@ +datadir=@datadir@ + +idldir=@idldir@ +IDL_INCLUDES=-I${idldir} @IDL_INCLUDES@ + +privincludedir=@privincludedir@ + +Name: libgdata-google +Description: Client library for accessing google POA through SOAP interface +Version: @VERSION@ +Requires: @LIBSOUP@ >= @LIBSOUP_REQUIRED@ +Libs: -L${libdir} -lgdata-google-1.2 +Cflags: -I${privincludedir}/gdata-google diff --git a/servers/google/libgdata/Makefile.am b/servers/google/libgdata/Makefile.am new file mode 100644 index 0000000..2e1464a --- /dev/null +++ b/servers/google/libgdata/Makefile.am @@ -0,0 +1,41 @@ +INCLUDES = \ + -DG_LOG_DOMAIN=\"libgdata\" \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(SOUP_CFLAGS) \ + $(E_DATA_SERVER_CFLAGS) + +lib_LTLIBRARIES = libgdata-1.2.la + +libgdata_1_2_la_SOURCES = \ + gdata-feed.c \ + gdata-feed.h \ + gdata-entry.c \ + gdata-entry.h \ + gdata-service-iface.c \ + gdata-service-iface.h + +libgdata_1_2_la_LIBADD = \ + $(E_DATA_SERVER_LIBS) \ + $(SOUP_LIBS) + +libgdata_1_2_la_LDFLAGS = \ + -version-info $(LIBGDATA_CURRENT):$(LIBGDATA_REVISION):$(LIBGDATA_AGE) $(NO_UNDEFINED) + +libgdataincludedir = $(privincludedir)/google/gdata + +libgdatainclude_HEADERS = \ + gdata-feed.h \ + gdata-entry.h \ + gdata-service-iface.h + +%-$(API_VERSION).pc: %.pc + cp $< $@ + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libgdata-$(API_VERSION).pc + +EXTRA_DIST = $(pkgconfig_DATA:-$(API_VERSION).pc=.pc.in) + +DISTCLEANFILES = $(pkgconfig_DATA) + diff --git a/servers/google/libgdata/gdata-entry.c b/servers/google/libgdata/gdata-entry.c new file mode 100644 index 0000000..69f1d49 --- /dev/null +++ b/servers/google/libgdata/gdata-entry.c @@ -0,0 +1,1460 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors : + * Ebby Wiselyn + * Jason Willis + * + * Copyright 2007, Novell, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * 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 library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + +#include + +/* LibXML2 includes */ +#include +#include +#include +#include + +#include + +#define GDATA_ENTRY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GDATA_TYPE_ENTRY, GDataEntryPrivate)) + +struct _GDataEntryAuthor { + gchar *email; + gchar *name; + gchar *uri; +}; +typedef struct _GDataEntryAuthor GDataEntryAuthor; + +struct _GDataEntryCategory { + gchar *label; + gchar *scheme; + gchar *scheme_prefix; + gchar *scheme_suffix; + gchar *term; +}; +typedef struct _GDataEntryCategory GDataEntryCategory; + +struct _GDataEntryLink { + gchar *href; + gint length; + gchar *rel; + gchar *title; + gchar *type; +}; +typedef struct _GDataEntryLink GDataEntryLink; + +struct _GDataEntryPrivate { + GSList *authors; + GSList *categories; + GSList *links; + GHashTable *field_table; + GSList *attendees; + gchar *location; + gchar *content; + gchar *title; + gchar *reminder; + gchar *status; + gchar *visibility; + gchar *start_time; + gchar *end_time; + gchar *send_notification; + gchar *transparency; + gchar *id; + + gboolean entry_needs_update; + gboolean has_attendees; + gchar *entry_xml; + + gboolean dispose_has_run; + gboolean is_recurrent; +}; + +static void gdata_entry_set_xml (GDataEntry *entry, const gchar *xml); + +static void destroy_authors (gpointer data, gpointer user_data) +{ + GDataEntryAuthor *author = (GDataEntryAuthor *)data; + if (author->email != NULL) + g_free(author->email); + + if (author->name != NULL) + g_free(author->name); + + if (author->uri != NULL) + g_free(author->uri); + + g_free(author); +} + +static void destroy_categories (gpointer data, gpointer user_data) +{ + GDataEntryCategory *category = (GDataEntryCategory *)data; + if (category->label != NULL) + g_free(category->label); + + if (category->scheme != NULL) + g_free(category->scheme); + + if (category->scheme_prefix != NULL) + g_free(category->scheme_prefix); + + if (category->scheme_suffix != NULL) + g_free(category->scheme_suffix); + + if (category->term != NULL) + g_free(category->term); + + g_free(category); +} + +static void destroy_links (gpointer data, gpointer user_data) +{ + GDataEntryLink *link = (GDataEntryLink *)data; + if (link->href != NULL) + g_free(link->href); + + if (link->rel != NULL) + g_free(link->rel); + + if (link->title != NULL) + g_free(link->title); + + if (link->type != NULL) + g_free(link->type); + + g_free(link); +} + +enum { + PROP_0, +}; + +static void gdata_entry_init (GTypeInstance *instance, + gpointer g_class) +{ + GDataEntryPrivate *priv; + GDataEntry *self = (GDataEntry *)instance; + + /* Private data set by g_type_class_add_private */ + priv = GDATA_ENTRY_GET_PRIVATE(self); + priv->dispose_has_run = FALSE; + priv->authors = NULL; + priv->links = NULL; + priv->categories = NULL; + priv->content = NULL; + priv->title = NULL; + priv->field_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + priv->entry_needs_update = FALSE; + priv->entry_xml = NULL; + priv->is_recurrent = FALSE; +} + +static void gdata_entry_dispose (GObject *obj) +{ + GObjectClass *parent_class; + GDataEntryClass *klass; + GDataEntry *self = GDATA_ENTRY(obj); + GDataEntryPrivate *priv = GDATA_ENTRY_GET_PRIVATE(self); + + if (priv->dispose_has_run) { + /* Don't run dispose twice */ + return; + } + priv->dispose_has_run = TRUE; + /* Chain up to the parent class */ + klass = GDATA_ENTRY_CLASS(g_type_class_peek(GDATA_TYPE_ENTRY)); + parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); + parent_class->dispose(obj); +} + +static void gdata_entry_finalize (GObject *obj) +{ + GDataEntryPrivate *priv; + GDataEntry *self = GDATA_ENTRY(obj); + GObjectClass *parent_class; + GDataEntryClass *klass; + + priv = GDATA_ENTRY_GET_PRIVATE(self); + if (priv->authors != NULL) { + g_slist_foreach(priv->authors, (GFunc) destroy_authors, NULL); + g_slist_free(priv->authors); + } + + if (priv->links != NULL) { + g_slist_foreach(priv->links, (GFunc) destroy_links, NULL); + g_slist_free(priv->links); + } + + if (priv->categories != NULL) { + g_slist_foreach(priv->categories, (GFunc) destroy_categories, NULL); + g_slist_free(priv->categories); + } + + if (priv->field_table != NULL) + g_hash_table_destroy(priv->field_table); + + if (priv->entry_xml != NULL) + g_free(priv->entry_xml); + + /* Chain up to the parent class */ + klass = GDATA_ENTRY_CLASS(g_type_class_peek(GDATA_TYPE_ENTRY)); + parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); + parent_class->finalize(obj); +} + +static void gdata_entry_get_property (GObject *obj, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GDataEntryPrivate *priv; + + priv = GDATA_ENTRY_GET_PRIVATE(obj); +} + +static void gdata_entry_set_property (GObject *obj, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GDataEntryPrivate *priv; + GDataEntry *self = (GDataEntry *) obj; + + priv = GDATA_ENTRY_GET_PRIVATE(self); +} + +static void gdata_entry_class_init (gpointer g_class, + gpointer g_class_data) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(g_class); + GDataEntryClass *klass = GDATA_ENTRY_CLASS(g_class); + + g_type_class_add_private(klass, sizeof (GDataEntryPrivate)); + gobject_class->set_property = gdata_entry_set_property; + gobject_class->get_property = gdata_entry_get_property; + gobject_class->dispose = gdata_entry_dispose; + gobject_class->finalize = gdata_entry_finalize; +} + +GType gdata_entry_get_type (void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (GDataEntryClass), + NULL, /* base init */ + NULL, /* base finalize */ + gdata_entry_class_init, /* class init */ + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (GDataEntry), + 0, /* n_preallocs */ + gdata_entry_init /* instance init */ + }; + type = g_type_register_static(G_TYPE_OBJECT,"GDataEntryType", &info,0); + } + + return type; +} + + +/*** API ***/ +static GDataEntryAuthor * +xmlnode_to_author (xmlDocPtr doc, xmlNodePtr cur) +{ + GDataEntryAuthor *author; + xmlChar *value; + + author = g_new0(GDataEntryAuthor, 1); + author->email = NULL; + author->name = NULL; + author->uri = NULL; + + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if (!xmlStrcmp(cur->name, (xmlChar *)"email")) { + value = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + author->email = g_strdup((gchar *)value); + xmlFree(value); + } + + if (!xmlStrcmp(cur->name, (xmlChar *)"name")) { + value = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + author->name = g_strdup((gchar *)value); + xmlFree(value); + } + + if (!xmlStrcmp(cur->name, (xmlChar *)"uri")) { + value = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + author->uri = g_strdup((gchar *)value); + xmlFree(value); + } + cur = cur->next; + } + + return author; +} + +static GDataEntryLink * +xmlnode_to_link (xmlDocPtr doc, xmlNodePtr cur) +{ + GDataEntryLink *link; + xmlChar *value; + + link = g_new0(GDataEntryLink, 1); + link->href = NULL; + link->rel = NULL; + link->title = NULL; + link->type = NULL; + + value = xmlGetProp(cur, (xmlChar *)"href"); + if (value) { + link->href = g_strdup((gchar *)value); + xmlFree(value); + } + + value = xmlGetProp(cur, (xmlChar *)"rel"); + if (value) { + link->rel = g_strdup((gchar *)value); + xmlFree(value); + } + + value = xmlGetProp(cur, (xmlChar *)"title"); + if (value) { + link->title = g_strdup((gchar *)value); + xmlFree(value); + } + + value = xmlGetProp(cur, (xmlChar *)"type"); + if (value) { + link->type = g_strdup((gchar *)value); + xmlFree(value); + } + + return link; +} + +static GDataEntryCategory * +xmlnode_to_category (xmlDocPtr doc, xmlNodePtr cur) +{ + GDataEntryCategory *category; + xmlChar *value; + + category = g_new0(GDataEntryCategory, 1); + category->label = NULL; + category->scheme = NULL; + category->scheme_prefix = NULL; + category->scheme_suffix = NULL; + category->term = NULL; + + value = xmlGetProp(cur, (xmlChar *)"label"); + if (value) { + category->label = g_strdup((gchar *)value); + xmlFree(value); + } + + value = xmlGetProp(cur, (xmlChar *)"scheme"); + if (value) { + category->scheme = g_strdup((gchar *)value); + xmlFree(value); + } + + value = xmlGetProp(cur, (xmlChar *)"term"); + if (value) { + category->term = g_strdup((gchar *)value); + xmlFree(value); + } + + return category; +} + +Attendee * +xmlnode_to_attendee (xmlDocPtr doc, xmlNodePtr cur) +{ + Attendee *attendee; + xmlChar *value; + + attendee = g_new0 (Attendee, 1); + + while (cur != NULL) { + value = xmlGetProp(cur, (xmlChar *)"email"); + if (value) { + attendee->attendee_email = g_strdup((gchar *)value); + xmlFree(value); + } + + value = xmlGetProp(cur, (xmlChar *)"rel"); + + if (value) { + attendee->attendee_rel = g_strdup((gchar *)value); + xmlFree (value); + } + + value= xmlGetProp(cur, (xmlChar *)"valueString"); + if (value) { + attendee->attendee_value = g_strdup((gchar *)value); + xmlFree (value); + } + + cur = cur->next; + } + return attendee; +} + +static xmlNodePtr +entry_to_xmlnode (GDataEntry *entry) +{ + xmlDocPtr doc; + xmlNodePtr cur; + gchar *xmlEntry; + + xmlEntry = gdata_entry_generate_xml (entry); + + /* FIXME 3rd argument could carry a better name */ + doc = xmlReadMemory (xmlEntry, strlen(xmlEntry), "feeds.xml", NULL, 0); + cur = xmlDocGetRootElement (doc); + + return cur; +} + +static xmlNodePtr +author_to_xmlnode (GDataEntryAuthor *author) +{ + + xmlNodePtr author_node; + + author_node = xmlNewNode(NULL, (xmlChar *)"author"); + if (author->email) + xmlNewChild (author_node, NULL, (xmlChar *)"email", (xmlChar *)author->email); + + if (author->name) + xmlNewChild (author_node, NULL, (xmlChar *)"name", (xmlChar *)author->name); + + return author_node; +} + +static xmlNodePtr +link_to_xmlnode (GDataEntryLink *link) +{ + xmlNodePtr link_node; + link_node = xmlNewNode(NULL, (xmlChar *)"link"); + + if (link->href) { + xmlSetProp (link_node, (xmlChar *)"href", (xmlChar *)link->href); + } + + if (link->rel) { + xmlSetProp (link_node, (xmlChar *)"rel", (xmlChar *)link->rel); + } + + if (link->title) { + xmlSetProp (link_node, (xmlChar *)"title", (xmlChar *)link->title); + } + + if (link->type) { + xmlSetProp (link_node, (xmlChar *)"type", (xmlChar *)link->type); + } + + return link_node; +} + +static xmlNodePtr +category_to_xmlnode (GDataEntryCategory *category) +{ + xmlNodePtr category_node; + category_node = xmlNewNode(NULL, (xmlChar *)"category"); + + if (category->label) { + xmlSetProp (category_node, (xmlChar *)"label", (xmlChar *)category->label); + } + + if (category->scheme) { + xmlSetProp (category_node, (xmlChar *)"scheme", (xmlChar *)category->scheme); + } + + if (category->term) { + xmlSetProp (category_node, (xmlChar *)"term", (xmlChar *)category->term); + } + + return category_node; +} + +/** + * gdata_entry_new: + * Creates a new #GDataEntry. + **/ +GDataEntry * +gdata_entry_new (void) +{ + return g_object_new(GDATA_TYPE_ENTRY, NULL); +} + +/** + * gdata_entry_get_private: + * @entry: A #GDataEntry object + * Returns a #GDataEntryPrivate object + **/ +GDataEntryPrivate * +gdata_entry_get_private (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + priv = GDATA_ENTRY_GET_PRIVATE (entry); + + return priv; +} +/** + * gdata_entry_new_from_xmlptr: + * @doc: A xml document pointer + * @ptr: A xml Node pointer + **/ +GDataEntry * +gdata_entry_new_from_xmlptr (xmlDocPtr doc, xmlNodePtr cur) +{ + GDataEntry *entry; + GDataEntryPrivate *priv; + xmlChar *value = NULL; + xmlOutputBufferPtr buf; + gchar *xmlString; + + g_return_val_if_fail(doc != NULL, NULL); + g_return_val_if_fail(cur != NULL, NULL); + + if (xmlStrcmp(cur->name, (xmlChar *)"entry")) { + return NULL; + } + + entry = gdata_entry_new (); + priv = GDATA_ENTRY_GET_PRIVATE(entry); + buf = xmlAllocOutputBuffer (NULL); + + if (buf == NULL) { + xmlString = NULL; + } + else { + xmlNodeDumpOutput (buf, NULL, cur, 0, 1, NULL); + xmlOutputBufferFlush (buf); + + if (buf->conv == NULL) + xmlString = g_strdup ((gchar *)buf->buffer->content); + else + xmlString = g_strdup ((gchar *)buf->conv->content); + xmlOutputBufferClose (buf); + } + + priv->entry_xml = g_strdup (xmlString); + cur = cur->xmlChildrenNode; + while (cur != NULL) { + + if (!xmlStrcmp(cur->name, (xmlChar *)"author")) { + priv->authors = g_slist_prepend(priv->authors, xmlnode_to_author(doc, cur)); + } + else if (!xmlStrcmp(cur->name, (xmlChar *)"link")) { + priv->links = g_slist_prepend(priv->links, xmlnode_to_link(doc, cur)); + } + else if (!xmlStrcmp(cur->name, (xmlChar *)"category")) { + priv->categories = g_slist_prepend(priv->categories, xmlnode_to_category(doc, cur)); + } + else if (!xmlStrcmp (cur->name, (xmlChar *)"where")) { + priv->location = (gchar *)xmlGetProp (cur, (xmlChar *)"valueString"); + } + else if (!xmlStrcmp (cur->name, (xmlChar *)"eventStatus")) { + priv->status = (gchar *)xmlGetProp (cur, (xmlChar *)"value"); + } + else if (!xmlStrcmp (cur->name, (xmlChar *)"visibility")) { + priv->visibility = (gchar *)xmlNodeListGetString (doc, cur->xmlChildrenNode, 1); + } + else if (!xmlStrcmp (cur->name, (xmlChar *)"when")) { + priv->start_time = (gchar *)xmlGetProp (cur, (xmlChar *)"startTime"); + priv->end_time = (gchar *)xmlGetProp (cur, (xmlChar *)"endTime"); + } + else if (!xmlStrcmp (cur->name, (xmlChar *)"recurrence")) { + priv->is_recurrent = TRUE; + } + + else if (!xmlStrcmp (cur->name, (xmlChar *)"who")) { + priv->attendees = g_slist_prepend (priv->attendees, xmlnode_to_attendee (doc, cur)); + priv->has_attendees = TRUE; + } + else if (!xmlStrcmp (cur->name, (xmlChar *)"sendEventNotifications")) { + priv->send_notification =(gchar *)xmlGetProp (cur, (xmlChar *)"value"); + } + else if (!xmlStrcmp (cur->name, (xmlChar *)"comments")) { + /*FIXME Call _comment_to_xml_node */ + } + + else { + value = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + g_hash_table_insert(priv->field_table, g_strdup((gchar *)cur->name), + g_strdup((gchar *)value)); + xmlFree(value); + } + cur = cur->next; + } + + xmlFree(value); + return entry; +} + +/** + * gdata_entries_new_from_xml: + * @feed_xml: A xml tree. + * @length: length of feed_xml + * Returns the list of all the entries in a feed. + **/ +/*Returns all the entries from the feed */ +GSList * +gdata_entries_new_from_xml (const gchar *feed_xml, const gint length) +{ + GSList *list; + xmlNodePtr cur; + xmlDocPtr doc; + + list = NULL; + + g_return_val_if_fail(feed_xml != NULL && *feed_xml != '\0', NULL); + + doc = xmlReadMemory (feed_xml, strlen(feed_xml), "feed.xml", NULL, 0); + if (doc == NULL) + return NULL; + + cur = xmlDocGetRootElement (doc); + if (cur == NULL) { + xmlFree (doc); + } + + cur = cur->xmlChildrenNode; + while (cur != NULL) + { + if (!xmlStrcmp (cur->name, (xmlChar *)"entry")) { + list = g_slist_prepend (list, gdata_entry_new_from_xmlptr (doc, cur)); + } + cur = cur->next; + } + + /* Free them */ + xmlFreeDoc (doc); + xmlFreeNode (cur); + + if (list == NULL) + g_slist_free (list); + + return list; +} + +/** + * gdata_entry_new_from_xml: + * @entry_xml: the xml tree + * Returns a GDataEntry object: + **/ +GDataEntry * +gdata_entry_new_from_xml (const gchar *entry_xml) +{ + GDataEntry *entry = NULL; + xmlDocPtr doc; + xmlNodePtr cur; + + g_return_val_if_fail (entry_xml != NULL && *entry_xml != '\0', NULL); + doc = xmlReadMemory (entry_xml, strlen(entry_xml), "feed.xml", NULL, 0); + + if (doc == NULL) + return NULL; + + cur = xmlDocGetRootElement (doc); + if (cur == NULL) + xmlFree (doc); + + while (cur != NULL) { + if (!xmlStrcmp (cur->name,(xmlChar *)"entry")) + entry = gdata_entry_new_from_xmlptr (doc, cur); + cur = cur->next; + } + /*Free them */ + xmlFreeDoc (doc); + xmlFreeNode (cur); + + if (!GDATA_IS_ENTRY(entry)) + return NULL; + + return entry; +} + +/** + *gdata_entry_generate_xml: + *@entry: A GDataEntry Object + *Returns the xml content: + **/ +gchar * +gdata_entry_generate_xml (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + GSList *list; + xmlChar *xmlString; + xmlNsPtr ns; + xmlNodePtr cur, cur_child, root; + xmlDocPtr doc; + gint xml_buffer_size; + + g_return_val_if_fail(entry !=NULL, NULL); + g_return_val_if_fail(GDATA_IS_ENTRY (entry), NULL); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + + if (!(priv->entry_xml == NULL || priv->entry_needs_update == TRUE)) + return priv->entry_xml; + + /* Construct DOM tree */ + doc = xmlNewDoc ((xmlChar *)"1.0"); + root = xmlNewDocNode (doc, NULL, (xmlChar *)"entry", NULL); + + xmlSetProp (root, (xmlChar *)"xmlns", (xmlChar *)"http://www.w3.org/2005/Atom"); + ns = xmlNewNs (root, (xmlChar *)"http://schemas.google.com/g/2005", (xmlChar *)"gd"); + xmlDocSetRootElement (doc, root); + cur = root; + + list = priv->categories; + while (list) { + cur_child = category_to_xmlnode(list->data); + xmlAddChild(root, cur_child); + list = g_slist_next(list); + } + + list = priv->authors; + while (list) { + cur_child = author_to_xmlnode(list->data); + xmlAddChild(root, cur_child); + list = g_slist_next(list); + } + + list = priv->links; + while (list) { + cur_child = link_to_xmlnode(list->data); + xmlAddChild(root, cur_child); + list = g_slist_next(list); + } + + if (priv->status) { + cur_child = xmlNewChild(root, NULL, (xmlChar *)"eventStatus", NULL); + xmlSetNs (cur_child, xmlNewNs (cur_child, NULL, (xmlChar *)"gd")); + xmlSetProp (cur_child, (xmlChar *)"value", (xmlChar *)priv->status); + } + + if (priv->start_time || priv->end_time || priv->reminder) { + cur_child = xmlNewChild(root, NULL, (xmlChar *)"when", NULL); + xmlSetNs (cur_child, xmlNewNs (cur_child, NULL, (xmlChar *)"gd")); + xmlSetProp (cur_child, (xmlChar *)"startTime", (xmlChar *)priv->start_time); + xmlSetProp (cur_child, (xmlChar *)"endTime", (xmlChar *)priv->end_time); + + if (priv->reminder) { + cur = cur_child; + cur_child = xmlNewChild(cur, NULL, (xmlChar *)"reminder", (xmlChar *)""); + xmlSetNs (cur_child, xmlNewNs (cur_child, NULL, (xmlChar *)"gd")); + xmlSetProp (cur_child->xmlChildrenNode, (xmlChar *)"minutes", (xmlChar *)priv->reminder); + } + } + + if (priv->location ) { + cur_child = xmlNewChild(root, NULL, (xmlChar *)"where", NULL); + xmlSetNs (cur_child, xmlNewNs (cur_child, NULL, (xmlChar *)"gd")); + xmlSetProp (cur_child, (xmlChar *)"valueString", (xmlChar *)priv->location); + } + + if (priv->content) { + cur_child = xmlNewChild(root, NULL, (xmlChar *)"content", (xmlChar *)priv->content); + xmlSetProp (cur_child, (xmlChar *)"type", (xmlChar *)"text"); + } + + if (priv->title) { + cur_child = xmlNewChild(root, NULL, (xmlChar *)"title", (xmlChar *)priv->title); + xmlSetProp (cur_child, (xmlChar *)"type", (xmlChar *)"text"); + } + + /* + if (priv->field_table) { + g_hash_table_foreach (priv->field_table,(GHFunc) _build_hash_table_entries, &root); + } + */ + + xmlDocDumpMemory(doc, &xmlString, &xml_buffer_size); + priv->entry_xml = g_strdup((gchar *)xmlString); + + xmlFree(xmlString); + xmlFreeDoc(doc); + + return priv->entry_xml; +} + +/* Builds the DOM tree for the entries stored in hash table */ +static void +build_hash_table_entries (gchar *key, gchar *value, xmlNode **cur) +{ + xmlNode *ptr; + ptr = *cur; + + /* Iterates from a node pointer , till it reaches NULL , to append other nodes */ + while (TRUE) { + + if (ptr->next == NULL) { + /* FIXME: Will we be needing , these nodes of entries when building them ? */ + if (!g_strcasecmp (key, "published") || !g_strcasecmp (key, "id") || !g_strcasecmp (key, "updated")) + break; + + ptr->next = xmlNewNode (NULL, (xmlChar *)key); + (value) ? xmlNodeSetContent (ptr->next, (xmlChar *)value) : xmlNodeSetContent (ptr->next, (xmlChar *)""); + break; + } + else + ptr = ptr->next; + } +} + +/** + * gdata_entry_get_id: + * @entry: A GDataEntry object + * Returns the id of the Entry: + **/ +gchar * +gdata_entry_get_id (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + + g_return_val_if_fail(entry != NULL, NULL); + g_return_val_if_fail (GDATA_IS_ENTRY (entry), NULL); + + priv = GDATA_ENTRY_GET_PRIVATE (entry); + return g_hash_table_lookup (priv->field_table, "id"); +} + +/** + * gdata_entry_get_visibility: + * @entry: A GDataEntry object + * Returns the visibility of the Entry: + **/ +gchar * +gdata_entry_get_visibility (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + + g_return_val_if_fail(entry != NULL, NULL); + g_return_val_if_fail (GDATA_IS_ENTRY (entry), NULL); + + priv = GDATA_ENTRY_GET_PRIVATE (entry); + return priv->visibility; +} + +/** + * gdata_entry_get_content: + * @entry: A #GDataEntry object + * Returns the content of the Entry/Event. + **/ +gchar * +gdata_entry_get_content (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + + g_return_val_if_fail (entry !=NULL, NULL); + g_return_val_if_fail (GDATA_IS_ENTRY (entry), NULL); + + priv = GDATA_ENTRY_GET_PRIVATE (entry); + return g_hash_table_lookup (priv->field_table, "content"); +} + +/** + * gdata_entry_get_description: + * @entry: A #GDataEntry object + * Returns the description of the Entry. + **/ +/* Returns the description of the entry */ +gchar * +gdata_entry_get_description (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + + g_return_val_if_fail (entry !=NULL, NULL); + g_return_val_if_fail (GDATA_IS_ENTRY (entry), NULL); + + priv = GDATA_ENTRY_GET_PRIVATE (entry); + return NULL; +} + +/** + * gdata_entry_get_copyright: + * @entry: A #GDataEntry object + * Returns the copyright of the Entry + **/ +gchar * +gdata_entry_get_copyright (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + + g_return_val_if_fail (entry !=NULL, NULL); + g_return_val_if_fail (GDATA_IS_ENTRY (entry), NULL); + + priv = GDATA_ENTRY_GET_PRIVATE (entry); + return g_hash_table_lookup (priv->field_table, "copyright"); +} + +/** + * gdata_entry_get_title: + * @entry: A #GDataEntry object. + * Returns the title of the Entry. + **/ +gchar * +gdata_entry_get_title (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + + g_return_val_if_fail (entry !=NULL, NULL); + g_return_val_if_fail (GDATA_IS_ENTRY (entry), NULL); + + priv = GDATA_ENTRY_GET_PRIVATE (entry); + return g_hash_table_lookup (priv->field_table, "title"); +} + +/** + * gdata_entry_get_authors: + * @entry: A #GDataEntry object. + * Returns the list of authors of entry. + **/ +GSList * +gdata_entry_get_authors (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + + g_return_val_if_fail (entry != NULL, NULL); + g_return_val_if_fail (GDATA_IS_ENTRY (entry), NULL); + + priv = GDATA_ENTRY_GET_PRIVATE (entry); + return priv->authors; +} + +/** + * gdata_entry_get_links: + * @entry: A #GDataEntry object. + * Returns the list of links + **/ +GSList * +gdata_entry_get_links (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + + g_return_val_if_fail (entry !=NULL, NULL); + g_return_val_if_fail (GDATA_IS_ENTRY (entry), NULL); + + priv = GDATA_ENTRY_GET_PRIVATE (entry); + return priv->links; +} + +/** + * gdata_entry_get_start_time: + * @entry: A #GDataEntry object. + * Returns the starting time of the Event. + **/ +gchar * +gdata_entry_get_start_time (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + + g_return_val_if_fail (entry!=NULL, NULL); + g_return_val_if_fail (GDATA_IS_ENTRY(entry), NULL); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + return priv->start_time; +} + + +/** + * gdata_entry_get_transparency: + * @entry: A #GDataEntry object. + * Returns the transparency of the Event. + **/ +gchar * +gdata_entry_get_transparency (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + + g_return_val_if_fail (entry!=NULL, NULL); + g_return_val_if_fail (GDATA_IS_ENTRY(entry), NULL); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + return priv->transparency; +} + +/** + * gdata_entry_get_end_time: + * @entry: A #GDataEntry object. + * Returns the ending time of the Event. + **/ +gchar * +gdata_entry_get_end_time (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + + g_return_val_if_fail (entry != NULL, NULL); + g_return_val_if_fail (GDATA_IS_ENTRY(entry), NULL); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + return priv->end_time; +} + +/** + * gdata_entry_get_location: + * @entry: A #GDataEntry object. + * Returns the location of the Event. + **/ +gchar * +gdata_entry_get_location (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + + g_return_val_if_fail (entry != NULL, NULL); + g_return_val_if_fail (GDATA_IS_ENTRY (entry), NULL); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + return priv->location; +} + +/** + * gdata_entry_get_status: + * @entry: A #GDataEntry object. + * Returns the status of the Event. + **/ +gchar * +gdata_entry_get_status (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + + g_return_val_if_fail(entry !=NULL, NULL); + g_return_val_if_fail(GDATA_IS_ENTRY (entry), NULL); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + return priv->status; +} + +/** + * gdata_entry_get_categories: + * @entry: A #GDataEntry object. + * Returns the status of the Event. + **/ +GSList * +gdata_entry_get_categories (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + + g_return_val_if_fail(entry !=NULL, NULL); + g_return_val_if_fail(GDATA_IS_ENTRY (entry), NULL); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + return priv->categories; +} + +/** + * gdata_entry_get_edit_link: + * @entry: A #GDataEntry object. + * Returns the edit link of the entry + **/ +gchar * +gdata_entry_get_edit_link (GDataEntry *entry) +{ + GSList *list; + GDataEntryLink *link; + gchar *edit_link = NULL; + + g_return_val_if_fail(GDATA_IS_ENTRY(entry), NULL); + list = gdata_entry_get_links (entry); + + while (list) { + link = list->data; + if (!g_strcasecmp (link->rel, "edit")) { + edit_link = g_strdup(link->href); + } + list = g_slist_next (list); + } + + return edit_link; +} + +/** + * gdata_entry_set_author: + * @entry: A #GDataEntry object. + * @author: A list of authors. + * Sets the list of authors. + **/ +void +gdata_entry_set_author (GDataEntry *entry, GSList *author) +{ + GDataEntryPrivate *priv; + + g_return_if_fail (author !=NULL); + g_return_if_fail (GDATA_IS_ENTRY(entry)); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + priv->authors = author; + priv->entry_needs_update = TRUE; +} + +/** + * gdata_entry_set_id: + * @entry: A #GDataEntry object. + * @id: Id of the entry. + * Sets the list of authors. + **/ +void +gdata_entry_set_id (GDataEntry *entry, gchar *id) +{ + GDataEntryPrivate *priv; + + g_return_if_fail (id !=NULL); + g_return_if_fail (GDATA_IS_ENTRY(entry)); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + priv->id = g_strdup(id); + priv->entry_needs_update = TRUE; +} + + + + +/** + * gdata_entry_set_categories: + * @entry: A GDataEntry object. + * @categories: A list of categories. + * Sets the list of categories of the Entry. + **/ +void +gdata_entry_set_categories (GDataEntry *entry, GSList *categories) +{ + GDataEntryPrivate *priv; + + g_return_if_fail(categories !=NULL); + g_return_if_fail(GDATA_IS_ENTRY(entry)); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + priv->categories = categories; + priv->entry_needs_update = TRUE; +} + +/** + * gdata_entry_set_title: + * @entry: A GDataEntry object. + * @title: title of the event. + * Sets the title of the Entry. + **/ +void +gdata_entry_set_title (GDataEntry *entry, const gchar *title) +{ + GDataEntryPrivate *priv; + + g_return_if_fail(title !=NULL); + g_return_if_fail(GDATA_IS_ENTRY (entry)); + + priv = GDATA_ENTRY_GET_PRIVATE (entry); + priv->title = g_strdup(title); + g_hash_table_insert (priv->field_table, g_strdup("title"), g_strdup(title)); + priv->entry_needs_update = TRUE; +} + +/** + * gdata_entry_set_content: + * @entry: A GDataEntry object. + * @content: The content of the event. + * Sets the content of the Entry. + **/ +void +gdata_entry_set_content (GDataEntry *entry, const gchar *content) +{ + GDataEntryPrivate *priv; + + g_return_if_fail(content !=NULL); + g_return_if_fail(GDATA_IS_ENTRY(entry)); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + priv->content = g_strdup (content); + priv->entry_needs_update = TRUE; + g_hash_table_insert (priv->field_table, g_strdup("content"), g_strdup (content)); +} + +/** + * gdata_entry_set_links: + * @entry: A GDataEntry object. + * @links: A list of links associated. + * Sets the links of the Event. + **/ +void +gdata_entry_set_links (GDataEntry *entry, GSList *links) +{ + GDataEntryPrivate *priv; + + g_return_if_fail( links !=NULL); + g_return_if_fail(GDATA_IS_ENTRY(entry)); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + priv->links = links; + priv->entry_needs_update = TRUE; +} + +/** + * gdata_entry_set_status: + * @entry: A GDataEntry object. + * @status: The status of the event. + * Sets the status of the Event. + **/ +void +gdata_entry_set_status (GDataEntry *entry, const gchar *status) +{ + GDataEntryPrivate *priv; + + g_return_if_fail(status!=NULL); + g_return_if_fail(GDATA_IS_ENTRY(entry)); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + priv->status = g_strdup (status); + priv->entry_needs_update = TRUE; +} + +/** + * gdata_entry_set_sendNotification: + * @entry: A GDataEntry object. + * @sendNotification: Whether notification is required. + * Sets whether notification should be sent by the Event. + **/ +void +gdata_entry_set_send_notification (GDataEntry *entry, const gchar *send_notification) +{ + GDataEntryPrivate *priv; + + g_return_if_fail (send_notification!=NULL); + g_return_if_fail (GDATA_IS_ENTRY (entry)); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + priv->send_notification = g_strdup(send_notification); + priv->entry_needs_update = TRUE; +} + +/** + * gdata_entry_set_reminder: + * @entry: A GDataEntry object. + * @reminder: The reminder set. + * Sets the reminder of the Event. + **/ +void +gdata_entry_set_reminder (GDataEntry *entry, const gchar *reminder) +{ + GDataEntryPrivate *priv; + + g_return_if_fail(reminder !=NULL); + g_return_if_fail(GDATA_IS_ENTRY (entry)); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + priv->reminder = g_strdup (reminder); + priv->entry_needs_update = TRUE; +} + +/** + * gdata_entry_set_start_time: + * @entry: A GDataEntry object. + * @start_time: The starting time of the event. + * Sets the starting time of the Event. + **/ +void +gdata_entry_set_start_time (GDataEntry *entry, const gchar *start_time) +{ + GDataEntryPrivate *priv; + + g_return_if_fail(start_time !=NULL); + g_return_if_fail(GDATA_IS_ENTRY(entry)); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + priv->start_time = g_strdup(start_time); + priv->entry_needs_update = TRUE; +} + +/** + * gdata_entry_set_end_time: + * @entry: A GDataEntry object. + * @end_time: The end time of the event. + * Sets the end time of the event. + **/ +void +gdata_entry_set_end_time (GDataEntry *entry, const gchar *end_time) +{ + GDataEntryPrivate *priv; + + g_return_if_fail(end_time !=NULL); + g_return_if_fail(GDATA_IS_ENTRY (entry)); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + priv->end_time = g_strdup(end_time); + priv->entry_needs_update = TRUE; +} + +/** + * gdata_entry_set_transparency: + * @entry: A GDataEntry object. + * @transparency: Transparency of the Entry. + * Sets the transparency of the entry. + **/ +void +gdata_entry_set_transparency (GDataEntry *entry, const gchar *transparency) +{ + GDataEntryPrivate *priv; + + g_return_if_fail (transparency !=NULL); + g_return_if_fail (GDATA_IS_ENTRY(entry)); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + priv->transparency = g_strdup (transparency); + priv->entry_needs_update = TRUE; +} + +/** + * gdata_entry_set_location: + * @entry: A GDataEntry object. + * @location: Location of the event. + * Sets the location of the event. + **/ +void +gdata_entry_set_location (GDataEntry *entry, const gchar *location) +{ + GDataEntryPrivate *priv; + + g_return_if_fail (location !=NULL); + g_return_if_fail (GDATA_IS_ENTRY(entry)); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + priv->location = g_strdup (location); + priv->entry_needs_update = TRUE; +} + +/** + * gdata_entry_set_xml: + * @entry: A GDataEntry object. + * @location: xml tree of the entry. + * Sets the xml tree of the entry. + **/ +static void +gdata_entry_set_xml (GDataEntry *entry, const gchar *xml) +{ + GDataEntryPrivate *priv; + + g_return_if_fail(GDATA_IS_ENTRY(entry)); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + priv->entry_xml = g_strdup (xml); + priv->entry_needs_update = TRUE; + +} + +/** + * gdata_entry_create_authors: + * @entry: A GDataEntry object. + * @name: The name of the author. + * @email: The email of the author. + * Sets the list of authors to the Entry. + **/ +void +gdata_entry_create_authors (GDataEntry *entry, + const gchar *name, + const gchar *email) +{ + GDataEntryPrivate *priv; + GDataEntryAuthor *author; + + g_return_if_fail(name !=NULL || email !=NULL); + g_return_if_fail(GDATA_IS_ENTRY(entry)); + + author = g_new0 (GDataEntryAuthor, 1); + priv = GDATA_ENTRY_GET_PRIVATE(entry); + + author->name = g_strdup(name); + author->email = g_strdup(email); + + priv->authors = g_slist_prepend(priv->authors, author); + priv->entry_needs_update = TRUE; + +} + +/** + * gdata_entry_create_categories: + * @entry: A GDataEntry object. + * @scheme:Scheme. + * @label:Label. + * @term: Term. + * Sets the categories of the Event. + **/ +void +gdata_entry_create_categories (GDataEntry *entry, + const gchar *scheme, + const gchar *label , + const gchar *term) +{ + GDataEntryPrivate *priv; + GDataEntryCategory *category; + + g_return_if_fail(scheme !=NULL || label !=NULL || term !=NULL); + g_return_if_fail(GDATA_IS_ENTRY (entry)); + + category = g_new0(GDataEntryCategory, 1); + priv = GDATA_ENTRY_GET_PRIVATE(entry); + + category->scheme = g_strdup(scheme); + category->label = g_strdup(label); + category->term = g_strdup(term); + + priv->categories = g_slist_prepend(priv->categories, category); + priv->entry_needs_update = TRUE; +} + +gboolean +gdata_entry_is_recurrent (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + + g_return_val_if_fail (entry != NULL, 0); + g_return_val_if_fail (GDATA_IS_ENTRY (entry), 0); + + priv = GDATA_ENTRY_GET_PRIVATE (entry); + return priv->is_recurrent; +} + +GSList * +gdata_entry_get_attendee_list (GDataEntry *entry) +{ + GDataEntryPrivate *priv; + + g_return_val_if_fail (entry != NULL, NULL); + g_return_val_if_fail (GDATA_IS_ENTRY(entry), NULL); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + return priv->attendees; +} + +void +gdata_entry_set_attendee_list (GDataEntry *entry, GSList *attendees) +{ + GDataEntryPrivate *priv; + + g_return_if_fail (entry != NULL); + g_return_if_fail (GDATA_IS_ENTRY(entry)); + g_return_if_fail (attendees != NULL); + + priv = GDATA_ENTRY_GET_PRIVATE(entry); + priv->attendees = attendees; + priv->has_attendees = TRUE; +} diff --git a/servers/google/libgdata/gdata-entry.h b/servers/google/libgdata/gdata-entry.h new file mode 100644 index 0000000..7a7f542 --- /dev/null +++ b/servers/google/libgdata/gdata-entry.h @@ -0,0 +1,175 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors : + * Ebby Wiselyn + * Jason Willis + * + * Copyright 2007, Novell, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * 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 library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef _GDATA_ENTRY_H_ +#define _GDATA_ENTRY_H_ + +#include +#include + + +/* LibXML2 includes */ +#include +#include +#include +#include + + +G_BEGIN_DECLS + + +#define GDATA_TYPE_ENTRY (gdata_entry_get_type()) +#define GDATA_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GDATA_TYPE_ENTRY, GDataEntry)) +#define GDATA_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GDATA_TYPE_ENTRY, GDataEntryClass)) +#define GDATA_IS_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GDATA_TYPE_ENTRY)) +#define GDATA_IS_ENTRY_CLASS(klass)(G_TYPE_CHECK_CLASS_TYPE((klass), GDATA_TYPE_ENTRY)) +#define GDATA_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GDATA_TYPE_ENTRY, GDataEntryClass)) + +typedef struct _GDataEntry GDataEntry; +typedef struct _GDataEntryClass GDataEntryClass; +typedef struct _GDataEntryPrivate GDataEntryPrivate; + + +struct _GDataEntry { + + GObject parent; + + /* private */ + GDataEntryPrivate *priv; +}; + +struct _GDataEntryClass { + + GObjectClass parent_class; + /* class members */ + +}; + +/* Should be moved under extensions */ +typedef struct _Attendee Attendee; +struct _Attendee { + gchar *attendee_email; + gchar *attendee_rel; + gchar *attendee_value; + gchar *attendee_status; + gchar *attendee_type; +}; + +GType gdata_entry_get_type(void); + + +/***** API *****/ + +GDataEntry * gdata_entry_new(void); + +GDataEntryPrivate * gdata_entry_get_private (GDataEntry *entry); + +GDataEntry * gdata_entry_new_from_xml(const gchar *entryXML); + +GDataEntry * gdata_entry_new_from_xmlptr (xmlDocPtr doc, xmlNodePtr cur); + +gchar * gdata_entry_generate_xml (GDataEntry *entry); + +gchar * gdata_entry_get_id(GDataEntry *entry); + +gchar * gdata_entry_get_content(GDataEntry *entry); + +gchar * gdata_entry_get_description (GDataEntry *entry); + +gchar * gdata_entry_get_copyright (GDataEntry *entry); + +gchar * gdata_entry_get_title (GDataEntry *entry); + +GSList * gdata_entry_get_authors (GDataEntry *entry); + +GSList * gdata_entry_get_links (GDataEntry *links); + +gchar * gdata_entry_get_start_time (GDataEntry *entry); + +gchar * gdata_entry_get_end_time (GDataEntry *entry); + +gchar * gdata_entry_get_location (GDataEntry *entry); + +gchar * gdata_entry_get_status (GDataEntry *entry); + +gchar * gdata_entry_get_edit_link (GDataEntry *entry); + +GSList * gdata_entry_get_categories (GDataEntry *entry); + +gchar * gdata_entry_get_start_date (GDataEntry *entry); + +gchar * gdata_entry_get_end_date (GDataEntry *entry); + +gchar * +gdata_entry_get_visibility (GDataEntry *entry); + +gchar * +gdata_entry_get_transparency (GDataEntry *entry); + +GSList * +gdata_entry_get_attendee_list (GDataEntry *entry); + +void gdata_entry_set_author (GDataEntry *entry, GSList *author); + +void gdata_entry_set_categories (GDataEntry *entry, GSList *categories); + +void gdata_entry_set_title (GDataEntry *entry, const gchar *title); + +void gdata_entry_set_content (GDataEntry *entry, const gchar *content); + +void gdata_entry_set_links (GDataEntry *entry, GSList *links); + +void gdata_entry_set_status (GDataEntry *entry, const gchar *status); + +void gdata_entry_set_send_notification (GDataEntry *entry, const gchar *sendNotification); + +void gdata_entry_set_reminder (GDataEntry *entry, const gchar *reminder); + +void gdata_entry_set_start_time (GDataEntry *entry, const gchar *start_time); + +void gdata_entry_set_end_time (GDataEntry *entry, const gchar *end_time); + +void gdata_entry_set_transparency (GDataEntry *entry, const gchar *transparency); + +void gdata_entry_set_location (GDataEntry *entry, const gchar *location); + +void gdata_entry_create_authors (GDataEntry *entry,const gchar *name, const gchar *email); + +void gdata_entry_create_categories (GDataEntry *entry, const gchar *scheme, const gchar *label , const gchar *term); + +GSList * gdata_entries_new_from_xml (const gchar *feedXML, const gint length); + +void +gdata_entry_set_id (GDataEntry *entry, gchar *id); + +gboolean gdata_entry_is_recurrent (GDataEntry *entry); + +void +gdata_entry_set_attendee_list (GDataEntry *entry, GSList *attendee); +#endif + + + + + diff --git a/servers/google/libgdata/gdata-feed.c b/servers/google/libgdata/gdata-feed.c new file mode 100644 index 0000000..8a73a32 --- /dev/null +++ b/servers/google/libgdata/gdata-feed.c @@ -0,0 +1,676 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors : + * Ebby Wiselyn + * Jason Willis + * Copyright 2007, Novell, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * 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 library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include + +#include +#include + +/* LibXML2 includes */ +#include +#include +#include +#include + +#include + +#define GDATA_FEED_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GDATA_TYPE_FEED, GDataFeedPrivate)) + + +struct _GDataFeedAuthor { + gchar *email; + gchar *name; + gchar *uri; +}; +typedef struct _GDataFeedAuthor GDataFeedAuthor; + +struct _GDataFeedCategory { + gchar *label; + gchar *scheme; + gchar *scheme_prefix; + gchar *scheme_suffix; + gchar *term; +}; +typedef struct _GDataFeedCategory GDataFeedCategory; + +struct _GDataFeedLink { + gchar *href; + gint length; + gchar *rel; + gchar *title; + gchar *type; +}; +typedef struct _GDataFeedLink GDataFeedLink; + + + +struct _GDataFeedPrivate { + + /* feed information */ + GSList *authors; + GSList *categories; + GSList *links; + GSList *entries; + + gchar *content; + gchar *contributor; + gchar *id; + gchar *link; + gchar *published; + gchar *rights; + gchar *source; + gchar *summary; + gchar *title; + gchar *updated; + + GHashTable *field_table; + gchar *feedXML; + + gboolean dispose_has_run; +}; + +static void destroy_authors(gpointer data, gpointer user_data) +{ + GDataFeedAuthor *author = (GDataFeedAuthor *)data; + if (author->email != NULL) + g_free(author->email); + + if (author->name != NULL) + g_free(author->name); + + if (author->uri != NULL) + g_free(author->uri); + + g_free(author); +} + +static void destroy_categories(gpointer data, gpointer user_data) +{ + GDataFeedCategory *category = (GDataFeedCategory *)data; + if (category->label != NULL) + g_free(category->label); + + if (category->scheme != NULL) + g_free(category->scheme); + + if (category->scheme_prefix != NULL) + g_free(category->scheme_prefix); + + if (category->scheme_suffix != NULL) + g_free(category->scheme_suffix); + + if (category->term != NULL) + g_free(category->term); + + g_free(category); +} + +static void destroy_links(gpointer data, gpointer user_data) +{ + GDataFeedLink *link = (GDataFeedLink *)data; + + if (link->href != NULL) + g_free(link->href); + + if (link->rel != NULL) + g_free(link->rel); + + if (link->title != NULL) + g_free(link->title); + + if (link->type != NULL) + g_free(link->type); + + g_free(link); +} + +static void destroy_entries(gpointer data, gpointer user_data) +{ + GDataEntry *entry = GDATA_ENTRY(data); + g_object_unref(G_OBJECT(entry)); +} + +enum { + PROP_0, + +}; + +static void +gdata_feed_init(GTypeInstance *instance, + gpointer g_class) +{ + GDataFeedPrivate *priv; + + GDataFeed *self = (GDataFeed *)instance; + + /* Private data set by g_type_class_add_private */ + priv = GDATA_FEED_GET_PRIVATE(self); + priv->dispose_has_run = FALSE; + + priv->content = NULL; + priv->contributor = NULL; + priv->id = NULL; + priv->link = NULL; + priv->published = NULL; + priv->rights = NULL; + priv->source = NULL; + priv->summary = NULL; + priv->title = NULL; + priv->updated = NULL; + + priv->authors = NULL; + priv->links = NULL; + priv->categories = NULL; + priv->entries = NULL; + + priv->field_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + priv->feedXML = NULL; +} + +static void +gdata_feed_dispose(GObject *obj) +{ + GObjectClass *parent_class; + GDataFeedClass *klass; + + GDataFeed *self = GDATA_FEED(obj); + GDataFeedPrivate *priv = GDATA_FEED_GET_PRIVATE(self); + + if (priv->dispose_has_run) { + /* Don't run dispose twice */ + return; + } + + priv->dispose_has_run = TRUE; + + /* Chain up to the parent class */ + klass = GDATA_FEED_CLASS(g_type_class_peek(GDATA_TYPE_FEED)); + parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); + + parent_class->dispose(obj); +} + +static void +gdata_feed_finalize(GObject *obj) +{ + GDataFeedPrivate *priv; + GDataFeed *self = GDATA_FEED(obj); + + GObjectClass *parent_class; + GDataFeedClass *klass; + + priv = GDATA_FEED_GET_PRIVATE(self); + if (priv->entries != NULL) { + g_slist_foreach(priv->entries, (GFunc)destroy_entries, NULL); + g_slist_free(priv->entries); + } + + if (priv->authors != NULL) { + g_slist_foreach(priv->authors, (GFunc)destroy_authors, NULL); + g_slist_free(priv->authors); + } + + if (priv->links != NULL) { + g_slist_foreach(priv->links, (GFunc)destroy_links, NULL); + g_slist_free(priv->links); + } + + if (priv->categories != NULL) { + g_slist_foreach(priv->categories, (GFunc)destroy_categories, NULL); + g_slist_free(priv->categories); + } + + if (priv->field_table != NULL) + g_hash_table_destroy(priv->field_table); + + if (priv->feedXML != NULL) + g_free(priv->feedXML); + + + /* Chain up to the parent class */ + klass = GDATA_FEED_CLASS(g_type_class_peek(GDATA_TYPE_FEED)); + parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); + parent_class->finalize(obj); +} + +static void +gdata_feed_get_property (GObject *obj, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GDataFeedPrivate *priv; + + priv = GDATA_FEED_GET_PRIVATE(obj); + +} + +static void +gdata_feed_set_property (GObject *obj, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GDataFeedPrivate *priv; + GDataFeed *self = (GDataFeed *) obj; + + priv = GDATA_FEED_GET_PRIVATE(self); + +} + +static GObject * gdata_feed_constructor(GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + GObject *obj; + + GObjectClass *parent_class; + GDataFeedClass *klass; + + /* Chain up to the parent class */ + klass = GDATA_FEED_CLASS(g_type_class_peek(GDATA_TYPE_FEED)); + parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); + + obj = parent_class->constructor(type, n_construct_properties, construct_properties); + + return obj; + +} + +static void +gdata_feed_class_init(gpointer g_class, + gpointer g_class_data) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(g_class); + GDataFeedClass *klass = GDATA_FEED_CLASS(g_class); + + + g_type_class_add_private(klass, sizeof (GDataFeedPrivate)); + + gobject_class->set_property = gdata_feed_set_property; + gobject_class->get_property = gdata_feed_get_property; + + + gobject_class->dispose = gdata_feed_dispose; + gobject_class->finalize = gdata_feed_finalize; + gobject_class->constructor = gdata_feed_constructor; + +} + +GType gdata_feed_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (GDataFeedClass), + NULL, /* base init */ + NULL, /* base finalize */ + gdata_feed_class_init, /* class init */ + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (GDataFeed), + 0, /* n_preallocs */ + gdata_feed_init /* instance init */ + }; + type = g_type_register_static(G_TYPE_OBJECT,"GDataFeedType", &info,0); + } + return type; +} + + +/*** API ***/ + static GDataFeedAuthor * +xmlnode_to_author(xmlDocPtr doc, xmlNodePtr cur) +{ + GDataFeedAuthor *author; + xmlChar *value; + + author = g_new0(GDataFeedAuthor, 1); + author->email = NULL; + author->name = NULL; + author->uri = NULL; + + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if (!xmlStrcmp(cur->name, (xmlChar *)"email")) { + value = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + author->email = g_strdup((gchar *)value); + xmlFree(value); + } + + if (!xmlStrcmp(cur->name, (xmlChar *)"name")) { + value = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + author->name = g_strdup((gchar *)value); + xmlFree(value); + } + + if (!xmlStrcmp(cur->name, (xmlChar *)"uri")) { + value = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + author->uri = g_strdup((gchar *)value); + xmlFree(value); + } + cur = cur->next; + } + + return author; +} + +static GDataFeedLink * +xmlnode_to_link(xmlDocPtr doc, xmlNodePtr cur) +{ + GDataFeedLink *link; + xmlChar *value; + + link = g_new0(GDataFeedLink, 1); + link->href = NULL; + link->rel = NULL; + link->title = NULL; + link->type = NULL; + + + value = xmlGetProp(cur, (xmlChar *)"href"); + if (value) { + link->href = g_strdup((gchar *)value); + xmlFree(value); + } + + value = xmlGetProp(cur, (xmlChar *)"rel"); + if (value) { + link->rel = g_strdup((gchar *)value); + xmlFree(value); + } + + value = xmlGetProp(cur, (xmlChar *)"title"); + if (value) { + link->title = g_strdup((gchar *)value); + xmlFree(value); + } + + value = xmlGetProp(cur, (xmlChar *)"type"); + if (value) { + link->type = g_strdup((gchar *)value); + xmlFree(value); + } + + return link; +} + + +static GDataFeedCategory * +xmlnode_to_category(xmlDocPtr doc, xmlNodePtr cur) +{ + GDataFeedCategory *category; + xmlChar *value; + + category = g_new0(GDataFeedCategory, 1); + category->label = NULL; + category->scheme = NULL; + category->scheme_prefix = NULL; + category->scheme_suffix = NULL; + category->term = NULL; + + value = xmlGetProp(cur, (xmlChar *)"label"); + if (value) { + category->label = g_strdup((gchar *)value); + xmlFree(value); + } + + value = xmlGetProp(cur, (xmlChar *)"scheme"); + if (value) { + category->scheme = g_strdup((gchar *)value); + xmlFree(value); + } + + value = xmlGetProp(cur, (xmlChar *)"term"); + if (value) { + category->term = g_strdup((gchar *)value); + xmlFree(value); + } + return category; +} + +static xmlNodePtr +link_to_xmlnode (GDataFeedLink *link) +{ + xmlNodePtr cur; + cur = xmlNewNode (NULL, (xmlChar *)"link"); + + if (link->href) { + xmlSetProp (cur, (xmlChar *)"href", (xmlChar *)link->href); + } + if (link->rel) { + xmlSetProp (cur, (xmlChar *)"rel", (xmlChar *)link->rel); + } + if (link->title) { + xmlSetProp (cur, (xmlChar *)"title", (xmlChar *)link->title); + } + if (link->type) { + xmlSetProp (cur, (xmlChar *)"type", (xmlChar *)link->type); + } + + return cur; +} + +static xmlNodePtr +author_to_xmlnode (GDataFeedAuthor *author) +{ + xmlNodePtr cur; + cur = xmlNewNode (NULL, (xmlChar *)"author"); + + if (author->name) + xmlNewChild (cur, NULL, (xmlChar *)"name", (xmlChar *)author->name); + + if (author->email) + xmlNewChild (cur, NULL, (xmlChar *)"email", (xmlChar *)author->email); + + if (author->uri) + xmlNewChild (cur, NULL, (xmlChar *)"uri", (xmlChar *)author->uri); + + return cur; +} + +static xmlNodePtr +category_to_xmlnode (GDataFeedCategory *category) +{ + xmlNodePtr cur; + cur = xmlNewNode (NULL, (xmlChar *)"category"); + + if (category->label) + xmlSetProp (cur, (xmlChar *)"label", (xmlChar *)category->label); + if (category->scheme) + xmlSetProp (cur, (xmlChar *)"scheme", (xmlChar *)category->scheme); + + return cur; +} + +static xmlNodePtr +entry_to_xmlnode (GDataEntry *entry) +{ + xmlDocPtr doc; + xmlNodePtr cur; + gchar *xmlEntry; + + xmlEntry = gdata_entry_generate_xml (entry); + doc = xmlReadMemory (xmlEntry, strlen (xmlEntry), "feed.xml", NULL, 0); + cur = xmlDocGetRootElement (doc); + + return cur; +} + +GDataFeed * +gdata_feed_new(void) +{ + return g_object_new(GDATA_TYPE_FEED, NULL); +} + + +GDataFeed * +gdata_feed_new_from_xml(const gchar* feedXML, const gint length) +{ + GDataFeed *feed; + GDataFeedPrivate *priv; + + xmlDocPtr doc; + xmlNodePtr cur; + + xmlChar *value; + gint value_size; + + g_return_val_if_fail(feedXML != NULL && *feedXML != '\0', NULL); + doc = xmlReadMemory(feedXML, length, + "feed.xml", + NULL, + 0); + + if (doc == NULL) + return NULL; + + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + /* Empty */ + xmlFreeDoc(doc); + return NULL; + } + + if (xmlStrcmp(cur->name, (xmlChar *)"feed")) { + xmlFreeDoc(doc); + return NULL; + } + + feed = g_object_new(GDATA_TYPE_FEED, NULL); + priv = GDATA_FEED_GET_PRIVATE(feed); + + cur = cur->xmlChildrenNode; + while (cur != NULL) { + + if (!xmlStrcmp(cur->name, (xmlChar *)"author")) { + priv->authors = g_slist_prepend(priv->authors, xmlnode_to_author(doc, cur)); + } + else if (!xmlStrcmp(cur->name, (xmlChar *)"link")) { + priv->links = g_slist_prepend(priv->links, xmlnode_to_link(doc, cur)); + } + else if (!xmlStrcmp(cur->name, (xmlChar *)"category")) { + priv->categories = g_slist_prepend(priv->categories, xmlnode_to_category(doc, cur)); + } + else if (!xmlStrcmp(cur->name, (xmlChar *)"entry")) { + priv->entries = g_slist_prepend(priv->entries, gdata_entry_new_from_xmlptr(doc,cur)); + } + else { + value = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + g_hash_table_insert(priv->field_table, g_strdup((gchar *)cur->name), + g_strdup((gchar *)value)); + xmlFree(value); + } + cur = cur->next; + } + + xmlDocDumpFormatMemory(doc, &value, &value_size, 1); + priv->feedXML = g_strdup(feedXML); + + xmlFree(value); + xmlFreeDoc(doc); + + return feed; +} + + +gchar * +gdata_feed_generate_xml(GDataFeed *feed) +{ + GDataFeedPrivate *priv; + xmlDocPtr doc; + xmlNodePtr cur; + xmlNodePtr root; + xmlNsPtr ns_os, ns_gd, ns_gcal; + xmlChar *xmlString; + gint xml_buffer_size; + GSList *list; + + g_return_val_if_fail(feed != NULL, NULL); + g_return_val_if_fail(GDATA_IS_FEED(feed), NULL); + + priv = GDATA_FEED_GET_PRIVATE(feed); + + if (!priv->feedXML) { + doc = xmlNewDoc ((xmlChar *)"1.0"); + root = xmlNewDocNode (doc, NULL, (xmlChar *)"feed", NULL); + + xmlSetProp (root, (xmlChar *)"xmlns", (xmlChar *)"http://www.w3.org/2005/Atom"); + ns_os = xmlNewNs (root, (xmlChar *)"http://a9.com/-/spec/opensearchrss/1.0/", (xmlChar *)"openSearch"); + ns_gd = xmlNewNs (root, (xmlChar *)"http://schemas.google.com/g/2005", (xmlChar *)"gd"); + ns_gcal = xmlNewNs (root, (xmlChar *)"http://schemas.google.com/gcal/2005", (xmlChar *)"gCal"); + + if (priv->id) { + cur = xmlNewChild (root, NULL, (xmlChar *)"id", NULL); + xmlNodeSetContent (cur, (xmlChar *)priv->id); + } + + list = priv->categories; + while (list) { + cur = category_to_xmlnode (list->data); + xmlAddChild (root, cur); + list = g_slist_next (list); + } + + list = priv->links; + while (list) { + cur = link_to_xmlnode (list->data); + xmlAddChild (root, cur); + list = g_slist_next (list); + } + + list = priv->authors; + while (list) { + cur = author_to_xmlnode (list->data); + xmlAddChild (root, cur); + list = g_slist_next (list); + } + + list = priv->entries; + while (list) { + cur = entry_to_xmlnode (list->data); + xmlAddChild (root, cur); + list = g_slist_next (list); + } + xmlDocDumpMemory (doc, &xmlString, &xml_buffer_size); + priv->feedXML = g_strdup ((gchar *)xmlString); + xmlFree (xmlString); + xmlFreeDoc (doc); + return priv->feedXML; + } + else { + return priv->feedXML; + } +} + +GSList * +gdata_feed_get_entries (GDataFeed *feed) +{ + GDataFeedPrivate *priv; + priv = GDATA_FEED_GET_PRIVATE (feed); + + g_return_val_if_fail (feed !=NULL, NULL); + g_return_val_if_fail (GDATA_IS_FEED(feed), NULL); + + return priv->entries; +} diff --git a/servers/google/libgdata/gdata-feed.h b/servers/google/libgdata/gdata-feed.h new file mode 100644 index 0000000..ffb6571 --- /dev/null +++ b/servers/google/libgdata/gdata-feed.h @@ -0,0 +1,71 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors : + * Ebby Wiselyn + * Jason Willis + * Copyright 2007, Novell, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * 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 library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef _GDATA_FEED_H_ +#define _GDATA_FEED_H_ + +#include +#include + +G_BEGIN_DECLS + + +#define GDATA_TYPE_FEED (gdata_feed_get_type()) +#define GDATA_FEED(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GDATA_TYPE_FEED, GDataFeed)) +#define GDATA_FEED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GDATA_TYPE_FEED, GDataFeedClass)) +#define GDATA_IS_FEED(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GDATA_TYPE_FEED)) +#define GDATA_IS_FEED_CLASS(klass)(G_TYPE_CHECK_CLASS_TYPE((klass), GDATA_TYPE_FEED)) +#define GDATA_FEED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GDATA_TYPE_FEED, GDataFeedClass)) + +typedef struct _GDataFeed GDataFeed; +typedef struct _GDataFeedClass GDataFeedClass; +typedef struct _GDataFeedPrivate GDataFeedPrivate; + + +struct _GDataFeed { + + GObject parent; + + /* private */ + GDataFeedPrivate *priv; +}; + +struct _GDataFeedClass { + + GObjectClass parent_class; + /* class members */ + +}; + +GType gdata_feed_get_type(void); +#endif + +/*** API ***/ + +GDataFeed * gdata_feed_new(void); + +GDataFeed * gdata_feed_new_from_xml(const gchar *feedXML, const gint length); + +gchar * gdata_feed_generate_xml(GDataFeed *feed); + +GSList * gdata_feed_get_entries (GDataFeed *feed); diff --git a/servers/google/libgdata/gdata-service-iface.c b/servers/google/libgdata/gdata-service-iface.c new file mode 100644 index 0000000..898dc9c --- /dev/null +++ b/servers/google/libgdata/gdata-service-iface.c @@ -0,0 +1,110 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors : + * Ebby Wiselyn + * Jason Willis + * + * Copyright 2007, Novell, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * 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 library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include +#include + +void +gdata_service_set_credentials (GDataService *self, const char *username, const gchar *password) +{ + GDATA_SERVICE_GET_IFACE(self)->set_credentials(self, username, password); + return; +} + +GDataFeed* +gdata_service_get_feed (GDataService *self, const char* feedURL) +{ + return GDATA_SERVICE_GET_IFACE(self)->get_feed(self, feedURL); +} + +GDataEntry* +gdata_service_insert_entry (GDataService *self, const gchar *feed_postURL, GDataEntry *entry) +{ + return GDATA_SERVICE_GET_IFACE(self)->insert_entry(self, g_strdup(feed_postURL), entry); +} + +GDataEntry* +gdata_service_get_entry (GDataService *self, const gchar *entry_getURL) +{ + return GDATA_SERVICE_GET_IFACE(self)->get_entry(self, entry_getURL); +} + +GDataEntry* +gdata_service_update_entry (GDataService *self, GDataEntry *entry) +{ + GDATA_SERVICE_GET_IFACE(self)->update_entry(self, entry); + return NULL; +} + +GDataEntry* +gdata_service_update_entry_with_link (GDataService *self, GDataEntry *entry, gchar *link) +{ + GDATA_SERVICE_GET_IFACE(self)->update_entry_with_link(self, entry, link); + return NULL; +} + +void +gdata_service_delete_entry (GDataService *self, GDataEntry *entry) +{ + GDATA_SERVICE_GET_IFACE(self)->delete_entry (self, entry); + return; +} + +static void +gdata_service_base_init (gpointer g_class) +{ + static gboolean initialized = FALSE; + + if (!initialized) { + /* create interface signals here. */ + initialized = TRUE; + } +} + +GType +gdata_service_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY(type == 0)) + { + static const GTypeInfo info = + { + sizeof (GDataServiceIface), + gdata_service_base_init, /* base_init */ + NULL, /* base_finalize */ + NULL, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL /* instance_init */ + }; + type = g_type_register_static (G_TYPE_INTERFACE, + "GDataService", &info, 0); + g_type_interface_add_prerequisite (type, G_TYPE_OBJECT ); + } + + return type; +} diff --git a/servers/google/libgdata/gdata-service-iface.h b/servers/google/libgdata/gdata-service-iface.h new file mode 100644 index 0000000..0a0a9d8 --- /dev/null +++ b/servers/google/libgdata/gdata-service-iface.h @@ -0,0 +1,79 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors : + * Ebby Wiselyn + * Jason Willis + * + * Copyright 2007, Novell, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * 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 library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef _GDATA_SERVICE_H_ +#define _GDATA_SERVICE_H_ + +#include +#include + +#include "gdata-feed.h" +#include "gdata-entry.h" + +G_BEGIN_DECLS + +#define GDATA_TYPE_SERVICE (gdata_service_get_type()) +#define GDATA_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GDATA_TYPE_SERVICE, GDataService)) +#define GDATA_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GDATA_TYPE_SERVICE, GDataServiceClass)) +#define GDATA_IS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GDATA_TYPE_SERVICE)) +#define GDATA_IS_SERVICE_CLASS(klass)(G_TYPE_CHECK_CLASS_TYPE((klass), GDATA_TYPE_SERVICE)) +#define GDATA_SERVICE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE((obj), GDATA_TYPE_SERVICE, GDataServiceIface)) + +typedef struct _GDataService GDataService; +typedef struct _GDataServiceIface GDataServiceIface; + +struct _GDataServiceIface { + + GTypeInterface parent; + + /* Public Methods */ + void (*set_credentials)(GDataService *self, const gchar *username, const gchar *password); + GDataFeed * (*get_feed) (GDataService *self, const gchar *feed_getURL); + GDataEntry* (*insert_entry)(GDataService *self, const gchar *feed_postURL, GDataEntry *entry); + GDataEntry* (*get_entry) (GDataService *self, const gchar *entry_getURL); + GDataEntry* (*update_entry)(GDataService *self, GDataEntry *entry); + GDataEntry* (*update_entry_with_link)(GDataService *self, GDataEntry *entry, gchar *link); + void (*delete_entry)(GDataService *self, GDataEntry *entry); +}; + +GType gdata_service_get_type(void); + +/* Function Prototypes */ +void gdata_service_set_credentials(GDataService *self, const gchar *username, const gchar *password); + +GDataFeed* gdata_service_get_feed(GDataService *self, const gchar *feed_getURL); + +GDataEntry* gdata_service_insert_entry(GDataService *self, const gchar *feed_postURL, GDataEntry *entry); + +GDataEntry* gdata_service_get_entry(GDataService *self, const gchar *entry_getURL); + +GDataEntry* gdata_service_update_entry(GDataService *self, GDataEntry *entry); + +GDataEntry* gdata_service_update_entry_with_link(GDataService *self, GDataEntry *entry, gchar *link); + +void gdata_service_delete_entry(GDataService *self, GDataEntry *entry); + +G_END_DECLS + +#endif diff --git a/servers/google/libgdata/libgdata.pc.in b/servers/google/libgdata/libgdata.pc.in new file mode 100644 index 0000000..0af25a1 --- /dev/null +++ b/servers/google/libgdata/libgdata.pc.in @@ -0,0 +1,18 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +datarootdir=@datarootdir@ +datadir=@datadir@ + +idldir=@idldir@ +IDL_INCLUDES=-I${idldir} @IDL_INCLUDES@ + +privincludedir=@privincludedir@ + +Name: libgdata +Description: Client library for accessing google POA through SOAP interface +Version: @VERSION@ +Requires: @LIBSOUP@ >= @LIBSOUP_REQUIRED@ +Libs: -L${libdir} -lgdata-1.2 +Cflags: -I${privincludedir}/gdata -- 2.7.4