<commit_before>/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* 
 * Authors : 
 *  <NAME> <<EMAIL>>
 *  <NAME> <<EMAIL>>
 *
 * Copyright 2003, Novell, Inc.
 *
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of version 2 of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <string.h>
#include <libgnomevfs/gnome-vfs-uri.h>
#include <libgnomevfs/gnome-vfs.h>
#include <bonobo/bonobo-i18n.h>
#include <libedataserver/e-xml-hash-utils.h>
#include <libedataserver/e-url.h>
#include <libedata-cal/e-cal-backend-cache.h>
#include <libedata-cal/e-cal-backend-util.h>
#include <libecal/e-cal-component.h>
#include <libecal/e-cal-time-util.h>
#include "e-cal-backend-groupwise.h"
#include "e-cal-backend-groupwise-utils.h"
#include "e-gw-connection.h"

/* Private part of the CalBackendGroupwise structure */
struct _ECalBackendGroupwisePrivate {
	/* A mutex to control access to the private structure */
	GMutex *mutex;
	EGwConnection *cnc;
	ECalBackendCache *cache;
	gboolean read_only;
	char *uri;
	char *username;
	char *password;
	char *container_id;
	CalMode mode;
	icaltimezone *default_zone;
	GHashTable *categories_by_id;
	GHashTable *categories_by_name;


	/* fields for storing info while offline */
	char *user_email;
};

static void e_cal_backend_groupwise_dispose (GObject *object);
static void e_cal_backend_groupwise_finalize (GObject *object);

#define PARENT_TYPE E_TYPE_CAL_BACKEND_SYNC
static ECalBackendClass *parent_class = NULL;

/* Time interval in milliseconds for obtaining changes from server and refresh the cache. */
#define CACHE_REFRESH_INTERVAL 600000

EGwConnection *
e_cal_backend_groupwise_get_connection (ECalBackendGroupwise *cbgw) {

	g_return_val_if_fail (E_IS_CAL_BACKEND_GROUPWISE (cbgw), NULL);

	return cbgw->priv->cnc;
}

GHashTable *
e_cal_backend_groupwise_get_categories_by_id (ECalBackendGroupwise *cbgw) {
	
	g_return_val_if_fail (E_IS_CAL_BACKEND_GROUPWISE (cbgw), NULL);
	
	return cbgw->priv->categories_by_id;
}

GHashTable *
e_cal_backend_groupwise_get_categories_by_name (ECalBackendGroupwise *cbgw) {

	g_return_val_if_fail (E_IS_CAL_BACKEND_GROUPWISE (cbgw), NULL);

	return cbgw->priv->categories_by_name;
}

icaltimezone *
e_cal_backend_groupwise_get_default_zone (ECalBackendGroupwise *cbgw) {

	g_return_val_if_fail (E_IS_CAL_BACKEND_GROUPWISE (cbgw), NULL);

	return cbgw->priv->default_zone;
}

/* Initialy populate the cache from the server */
static EGwConnectionStatus
populate_cache (ECalBackendGroupwise *cbgw)
{
	ECalBackendGroupwisePrivate *priv;
	EGwConnectionStatus status;
        ECalComponent *comp;
        GList *list = NULL, *l;

	priv = cbgw->priv;

        /* get all the objects from the server */
        status = e_gw_connection_get_items (priv->cnc, priv->container_id, "recipients message recipientStatus", NULL, &list);
        if (status != E_GW_CONNECTION_STATUS_OK) {
                g_list_free (list);
		e_cal_backend_groupwise_notify_error_code (cbgw, status);
                return status;
        }

	/* get the list of category ids and corresponding names from the server */
	status = e_gw_connection_get_categories (priv->cnc, priv->categories_by_id, priv->categories_by_name);
	if (status != E_GW_CONNECTION_STATUS_OK) {
		e_cal_backend_groupwise_notify_error_code (cbgw, status);
                return status;
        }

        for (l = list; l != NULL; l = g_list_next(l)) {
		EGwItem *item;

		item = E_GW_ITEM (l->data);
		comp = e_gw_item_to_cal_component (item, cbgw);
		g_object_unref (item);
		if (E_IS_CAL_COMPONENT (comp)) {
			e_cal_component_commit_sequence (comp);
			e_cal_backend_cache_put_component (priv->cache, comp);
			g_object_unref (comp);
		}
        }
        
        g_list_free (list);

        return E_GW_CONNECTION_STATUS_OK;        
}


static gboolean
get_deltas (gpointer handle)
{
 	ECalBackendGroupwise *cbgw;
	EGwConnection *cnc; 
 	ECalBackendCache *cache; 
        EGwConnectionStatus status; 
	GSList *deletes = NULL, *updates = NULL, *adds = NULL, *l;
        
	cbgw = (ECalBackendGroupwise *) handle;
 	cnc = cbgw->priv->cnc; 
 	cache = cbgw->priv->cache; 

	/* Call e-gw-connection_get_deltas*/
	status = e_gw_connection_get_deltas (cnc, &adds, &deletes, &updates);

	if (status != E_GW_CONNECTION_STATUS_OK) {
		e_cal_backend_groupwise_notify_error_code (cbgw, status);
		return FALSE;
	}
	
	if (deletes) {
		for (l = deletes; l != NULL; l = g_slist_next(l)) {
			if (!e_cal_backend_cache_remove_component (cache, (char *)l->data, NULL)) 
				g_message ("Could not remove %s", (char *)l->data);
		}
	}

	if (adds) {
		for (l = adds; l != NULL; l = g_slist_next (l)) {
			EGwItem *item = (EGwItem *) l->data;
			ECalComponent *comp = e_gw_item_to_cal_component (item, cbgw);
			if (!comp)
				g_message ("Invalid component returned");
			else if (!e_cal_backend_cache_put_component (cache, comp)) 
				g_message ("Could not add the component");
		}
	}	

	if (updates) {
		for (l = updates; l != NULL; l = g_slist_next (l)) {
			EGwItem *item = (EGwItem *) l->data;
			ECalComponent *comp = e_cal_backend_cache_get_component (cache, e_gw_item_get_id (item), NULL);
			if (!comp) /* FIXME  Error in updates. Skipping the element*/
				continue;
			/* FIXME  currently, just overwrite the fields with the
			 * update.*/
			e_cal_backend_cache_remove_component (cache, e_gw_item_get_id (item), NULL);
			e_cal_backend_cache_put_component (cache, e_gw_item_to_cal_component (item, cbgw));
		}
	}

        return TRUE;        
}


static char* 
form_uri (ESource *source)
{
	char *uri;
	const char *port;
	char *formed_uri;
	const char *use_ssl;
	
       	EUri *parsed_uri;

	uri = e_source_get_uri (source);
	if (uri == NULL)
		return NULL;

	parsed_uri = e_uri_new (uri);
	if (parsed_uri == NULL)
		return NULL;

       	port = e_source_get_property (source, "port");
	if (port == NULL)
		port = "7181";
	use_ssl = e_source_get_property (source, "use_ssl");

	if (use_ssl)
		formed_uri = g_strconcat ("https://", parsed_uri->host,":", port, "/soap", NULL );
	else 
		formed_uri = g_strconcat ("http://", parsed_uri->host,":", port, "/soap", NULL );
	
	g_free (uri);
	e_uri_free (parsed_uri);
	return formed_uri;

}

static ECalBackendSyncStatus
connect_to_server (ECalBackendGroupwise *cbgw)
{
	char *real_uri;
	ECalBackendGroupwisePrivate *priv;
	EGwConnectionStatus cnc_status;
	ESource *source;
	const char *use_ssl;
	char *http_uri;
	priv = cbgw->priv;

	source = e_cal_backend_get_source (E_CAL_BACKEND (cbgw));
	real_uri = NULL;
	if (source)
		real_uri = form_uri (source);
	use_ssl = e_source_get_property (source, "use_ssl");
 
	if (!real_uri) {
		e_cal_backend_notify_error (E_CAL_BACKEND (cbgw), _("Invalid server URI"));
		return GNOME_Evolution_Calendar_NoSuchCal;
	} else {
		/* create connection to server */
		priv->cnc = e_gw_connection_new (
			real_uri,
			priv->username,
			priv->password);

		if (!E_IS_GW_CONNECTION(priv->cnc) && use_ssl && g_str_equal (use_ssl, "when-possible")) {
			http_uri = g_strconcat ("http://", real_uri + 8, NULL);
			priv->cnc = e_gw_connection_new (http_uri, priv->username, priv->password);
			g_free (http_uri);
		}
		g_free (real_uri);
			
		/* As of now we are assuming that logged in user has write rights to calender */
		/* we need to read actual rights from server when we implement proxy user access */
		cbgw->priv->read_only = FALSE;
	
		if (E_IS_GW_CONNECTION (priv->cnc)) {
			icalcomponent_kind kind;

			/* get the ID for the container */
			if (priv->container_id)
				g_free (priv->container_id);

			kind = e_cal_backend_get_kind (E_CAL_BACKEND (cbgw));
			if (kind == ICAL_VEVENT_COMPONENT) {
				priv->container_id = g_strdup (e_gw_connection_get_container_id (priv->cnc, "Calendar"));
				e_source_set_name (e_cal_backend_get_source (E_CAL_BACKEND (cbgw)), _("Calendar"));
			} else if (kind == ICAL_VTODO_COMPONENT) {
				priv->container_id = g_strdup (e_gw_connection_get_container_id (priv->cnc, "Calendar"));
				e_source_set_name (e_cal_backend_get_source (E_CAL_BACKEND (cbgw)), _("Calendar"));
			} else
				priv->container_id = NULL;

				priv->cache = e_cal_backend_cache_new (e_cal_backend_get_uri (E_CAL_BACKEND (cbgw)));
				if (!priv->cache) {
					g_mutex_unlock (priv->mutex);
					e_cal_backend_notify_error (E_CAL_BACKEND (cbgw), _("Could not create cache file"));
					return GNOME_Evolution_Calendar_OtherError;
				}

			/* Populate the cache for the first time.*/
			/* start a timed polling thread set to 10 minutes*/
			cnc_status = populate_cache (cbgw);<commit_msg>*** empty log message ***<commit_after>/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* 
 * Authors : 
 *  <NAME> <<EMAIL>>
 *  <NAME> <<EMAIL>>
 *
 * Copyright 2003, Novell, Inc.
 *
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of version 2 of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <string.h>
#include <libgnomevfs/gnome-vfs-uri.h>
#include <libgnomevfs/gnome-vfs.h>
#include <bonobo/bonobo-i18n.h>
#include <libedataserver/e-xml-hash-utils.h>
#include <libedataserver/e-url.h>
#include <libedata-cal/e-cal-backend-cache.h>
#include <libedata-cal/e-cal-backend-util.h>
#include <libecal/e-cal-component.h>
#include <libecal/e-cal-time-util.h>
#include "e-cal-backend-groupwise.h"
#include "e-cal-backend-groupwise-utils.h"
#include "e-gw-connection.h"

/* Private part of the CalBackendGroupwise structure */
struct _ECalBackendGroupwisePrivate {
	/* A mutex to control access to the private structure */
	GMutex *mutex;
	EGwConnection *cnc;
	ECalBackendCache *cache;
	gboolean read_only;
	char *uri;
	char *username;
	char *password;
	char *container_id;
	CalMode mode;
	icaltimezone *default_zone;
	GHashTable *categories_by_id;
	GHashTable *categories_by_name;


	/* fields for storing info while offline */
	char *user_email;
};

static void e_cal_backend_groupwise_dispose (GObject *object);
static void e_cal_backend_groupwise_finalize (GObject *object);

#define PARENT_TYPE E_TYPE_CAL_BACKEND_SYNC
static ECalBackendClass *parent_class = NULL;

/* Time interval in milliseconds for obtaining changes from server and refresh the cache. */
#define CACHE_REFRESH_INTERVAL 600000

EGwConnection *
e_cal_backend_groupwise_get_connection (ECalBackendGroupwise *cbgw) {

	g_return_val_if_fail (E_IS_CAL_BACKEND_GROUPWISE (cbgw), NULL);

	return cbgw->priv->cnc;
}

GHashTable *
e_cal_backend_groupwise_get_categories_by_id (ECalBackendGroupwise *cbgw) {
	
	g_return_val_if_fail (E_IS_CAL_BACKEND_GROUPWISE (cbgw), NULL);
	
	return cbgw->priv->categories_by_id;
}

GHashTable *
e_cal_backend_groupwise_get_categories_by_name (ECalBackendGroupwise *cbgw) {

	g_return_val_if_fail (E_IS_CAL_BACKEND_GROUPWISE (cbgw), NULL);

	return cbgw->priv->categories_by_name;
}

icaltimezone *
e_cal_backend_groupwise_get_default_zone (ECalBackendGroupwise *cbgw) {

	g_return_val_if_fail (E_IS_CAL_BACKEND_GROUPWISE (cbgw), NULL);

	return cbgw->priv->default_zone;
}

/* Initialy populate the cache from the server */
static EGwConnectionStatus
populate_cache (ECalBackendGroupwise *cbgw)
{
	ECalBackendGroupwisePrivate *priv;
	EGwConnectionStatus status;
        ECalComponent *comp;
        GList *list = NULL, *l;

	priv = cbgw->priv;

        /* get all the objects from the server */
        status = e_gw_connection_get_items (priv->cnc, priv->container_id, "recipients message recipientStatus", NULL, &list);
        if (status != E_GW_CONNECTION_STATUS_OK) {
                g_list_free (list);
		e_cal_backend_groupwise_notify_error_code (cbgw, status);
                return status;
        }

	/* get the list of category ids and corresponding names from the server */
	status = e_gw_connection_get_categories (priv->cnc, priv->categories_by_id, priv->categories_by_name);
	if (status != E_GW_CONNECTION_STATUS_OK) {
		e_cal_backend_groupwise_notify_error_code (cbgw, status);
                return status;
        }

        for (l = list; l != NULL; l = g_list_next(l)) {
		EGwItem *item;

		item = E_GW_ITEM (l->data);
		comp = e_gw_item_to_cal_component (item, cbgw);
		g_object_unref (item);
		if (E_IS_CAL_COMPONENT (comp)) {
			e_cal_component_commit_sequence (comp);
			e_cal_backend_cache_put_component (priv->cache, comp);
			g_object_unref (comp);
		}
        }
        
        g_list_free (list);

        return E_GW_CONNECTION_STATUS_OK;        
}


static gboolean
get_deltas (gpointer handle)
{
 	ECalBackendGroupwise *cbgw;
	EGwConnection *cnc; 
 	ECalBackendCache *cache; 
        EGwConnectionStatus status; 
	GSList *deletes = NULL, *updates = NULL, *adds = NULL, *l;
        
	cbgw = (ECalBackendGroupwise *) handle;
 	cnc = cbgw->priv->cnc; 
 	cache = cbgw->priv->cache; 

	/* Call e-gw-connection_get_deltas*/
	status = e_gw_connection_get_deltas (cnc, &adds, &deletes, &updates);

	if (status != E_GW_CONNECTION_STATUS_OK) {
		e_cal_backend_groupwise_notify_error_code (cbgw, status);
		return FALSE;
	}
	
	if (deletes) {
		for (l = deletes; l != NULL; l = g_slist_next(l)) {
			if (!e_cal_backend_cache_remove_component (cache, (char *)l->data, NULL)) 
				g_message ("Could not remove %s", (char *)l->data);
		}
	}

	if (adds) {
		for (l = adds; l != NULL; l = g_slist_next (l)) {
			EGwItem *item = (EGwItem *) l->data;
			ECalComponent *comp = e_gw_item_to_cal_component (item, cbgw);
			if (!comp)
				g_message ("Invalid component returned");
			else if (!e_cal_backend_cache_put_component (cache, comp)) 
				g_message ("Could not add the component");
		}
	}	

	if (updates) {
		for (l = updates; l != NULL; l = g_slist_next (l)) {
			EGwItem *item = (EGwItem *) l->data;
			ECalComponent *comp = e_cal_backend_cache_get_component (cache, e_gw_item_get_id (item), NULL);
			if (!comp) /* FIXME  Error in updates. Skipping the element*/
				continue;
			/* FIXME  currently, just overwrite the fields with the
			 * update.*/
			e_cal_backend_cache_remove_component (cache, e_gw_item_get_id (item), NULL);
			e_cal_backend_cache_put_component (cache, e_gw_item_to_cal_component (item, cbgw));
		}
	}

        return TRUE;        
}


static char* 
form_uri (ESource *source)
{
	char *uri;
	const char *port;
	char *formed_uri;
	const char *use_ssl;
	
       	EUri *parsed_uri;

	uri = e_source_get_uri (source);
	if (uri == NULL)
		return NULL;

	parsed_uri = e_uri_new (uri);
	if (parsed_uri == NULL)
		return NULL;

       	port = e_source_get_property (source, "port");
	if (port == NULL)
		port = "7181";
	use_ssl = e_source_get_property (source, "use_ssl");

	if (use_ssl)
		formed_uri = g_strconcat ("https://", parsed_uri->host,":", port, "/soap", NULL );
	else 
		formed_uri = g_strconcat ("http://", parsed_uri->host,":", port, "/soap", NULL );
	
	g_free (uri);
	e_uri_free (parsed_uri);
	return formed_uri;

}

static ECalBackendSyncStatus
connect_to_server (ECalBackendGroupwise *cbgw)
{
	char *real_uri;
	ECalBackendGroupwisePrivate *priv;
	EGwConnectionStatus cnc_status;
	ESource *source;
	const char *use_ssl;
	char *http_uri;
	priv = cbgw->priv;

	source = e_cal_backend_get_source (E_CAL_BACKEND (cbgw));
	real_uri = NULL;
	if (source)
		real_uri = form_uri (source);
	use_ssl = e_source_get_property (source, "use_ssl");
 
	if (!real_uri) {
		e_cal_backend_notify_error (E_CAL_BACKEND (cbgw), _("Invalid server URI"));
		return GNOME_Evolution_Calendar_NoSuchCal;
	} else {
		/* create connection to server */
		priv->cnc = e_gw_connection_new (
			real_uri,
			priv->username,
			priv->password);

		if (!E_IS_GW_CONNECTION(priv->cnc) && use_ssl && g_str_equal (use_ssl, "when-possible")) {
			http_uri = g_strconcat ("http://", real_uri + 8, NULL);
			priv->cnc = e_gw_connection_new (http_uri, priv->username, priv->password);
			g_free (http_uri);
		}
		g_free (real_uri);
			
		/* As of now we are assuming that logged in user has write rights to calender */
		/* we need to read actual rights from server when we implement proxy user access */
		cbgw->priv->read_only = FALSE;

		if (priv->cnc && priv->cache) {
			priv->mode = CAL_MODE_REMOTE;
			return GNOME_Evolution_Calendar_Success;
		}

	
		if (E_IS_GW_CONNECTION (priv->cnc)) {
			icalcomponent_kind kind;

			/* get the ID for the container */
			if (priv->container_id)
				g_free (priv->container_id);

			kind = e_cal_backend_get_kind (E_CAL_BACKEND (cbgw));
			if (kind == ICAL_VEVENT_COMPONENT) {
				priv->container_id = g_strdup (e_gw_connection_get_container_id (priv->cnc, "Calendar"));
				e_source_set_name (e_cal_backend_get_source (E_CAL_BACKEND (cbgw)), _("Calendar"));
			} else if (kind == ICAL_VTODO_COMPONENT) {
				priv->container_id = g_strdup (e_gw_connection_get_container_id (priv->cnc, "Calendar"));
				e_source_set_name (e_cal_backend_get_source (E_CAL_BACKEND (cbgw)), _("Calendar"));
			} else
				priv->container_id = NULL;

				priv->cache = e_cal_backend_cache_new (e_cal_backend_get_uri (E_CAL_BACKEND (cbgw)));
				if (!priv->cache) {
					g_mutex_unlock (priv->mutex);
					e_cal_backend_notify_error (E_CAL_BACKEND (cbgw), _("Could not create cache file"));
					return GNOME_Evolution_Calendar_OtherError;
				}

			/* Populate the cache for the first time.*/
			/* start a timed polling thread set to 10 minutes*/
			cnc_status = populate_cache (cbgw);
{'fraction_non_alphanumeric': 0.11411002884039832, 'fraction_numerical': 0.003917940904391359, 'mean_word_length': 4.201811491650155, 'pattern_counts': {'":': 4, '<': 37, '<?xml version=': 0, '>': 134, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7145822', 'n_tokens_mistral': 7162, 'n_tokens_neox': 6633, 'n_words': 1606}