aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/exchange-operations/exchange-config-listener.c
diff options
context:
space:
mode:
authorSarfraaz Ahmed <asarfraaz@novell.com>2005-06-13 20:39:20 +0800
committerAhmed Sarfraaz <sarfraaz@src.gnome.org>2005-06-13 20:39:20 +0800
commitd12d5fd082bd480bd9b635dbdae72d439730273a (patch)
tree83aab9a5eb38958a1828d20a1a09cfb8c980d4a1 /plugins/exchange-operations/exchange-config-listener.c
parent571d426db5c37683f03e2c95d3feea7e3d2905ec (diff)
downloadgsoc2013-evolution-d12d5fd082bd480bd9b635dbdae72d439730273a.tar
gsoc2013-evolution-d12d5fd082bd480bd9b635dbdae72d439730273a.tar.gz
gsoc2013-evolution-d12d5fd082bd480bd9b635dbdae72d439730273a.tar.bz2
gsoc2013-evolution-d12d5fd082bd480bd9b635dbdae72d439730273a.tar.lz
gsoc2013-evolution-d12d5fd082bd480bd9b635dbdae72d439730273a.tar.xz
gsoc2013-evolution-d12d5fd082bd480bd9b635dbdae72d439730273a.tar.zst
gsoc2013-evolution-d12d5fd082bd480bd9b635dbdae72d439730273a.zip
Added a new plugin directory for renaming exchange-account-setup as
2005-06-12 Sarfraaz Ahmed <asarfraaz@novell.com> * plugins/exchange-operations : Added a new plugin directory for renaming exchange-account-setup as exchange-operations. svn path=/trunk/; revision=29498
Diffstat (limited to 'plugins/exchange-operations/exchange-config-listener.c')
-rw-r--r--plugins/exchange-operations/exchange-config-listener.c1095
1 files changed, 1095 insertions, 0 deletions
diff --git a/plugins/exchange-operations/exchange-config-listener.c b/plugins/exchange-operations/exchange-config-listener.c
new file mode 100644
index 0000000000..d41384d79d
--- /dev/null
+++ b/plugins/exchange-operations/exchange-config-listener.c
@@ -0,0 +1,1095 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/* Copyright (C) 2001-2004 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.
+ */
+
+/* ExchangeConfigListener: a class that listens to the config database
+ * and handles creating the ExchangeAccount object and making sure that
+ * default folders are updated as needed.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "exchange-config-listener.h"
+
+#include <exchange-account.h>
+#include <exchange-constants.h>
+#include <e-folder-exchange.h>
+#include <e2k-marshal.h>
+#include <e2k-uri.h>
+// SURF : #include "mail-stub-listener.h"
+
+// SURF : #include <libedataserver/e-dialog-utils.h>
+
+#include <libedataserver/e-source.h>
+#include <libedataserver/e-source-list.h>
+#include <libedataserver/e-source-group.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+struct _ExchangeConfigListenerPrivate {
+ GConfClient *gconf;
+ guint idle_id;
+
+ char *configured_uri, *configured_name;
+ EAccount *configured_account;
+
+ ExchangeAccount *exchange_account;
+};
+
+typedef struct {
+ const char *name;
+ const char *uri;
+ int type;
+}FolderInfo;
+
+enum {
+ EXCHANGE_ACCOUNT_CREATED,
+ EXCHANGE_ACCOUNT_REMOVED,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+#define PARENT_TYPE E_TYPE_ACCOUNT_LIST
+
+#define CONF_KEY_SELECTED_CAL_SOURCES "/apps/evolution/calendar/display/selected_calendars"
+#define CONF_KEY_SELECTED_TASKS_SOURCES "/apps/evolution/calendar/tasks/selected_tasks"
+
+static EAccountListClass *parent_class = NULL;
+
+static void dispose (GObject *object);
+static void finalize (GObject *object);
+
+static void account_added (EAccountList *account_listener,
+ EAccount *account);
+static void account_changed (EAccountList *account_listener,
+ EAccount *account);
+static void account_removed (EAccountList *account_listener,
+ EAccount *account);
+
+static void
+class_init (GObjectClass *object_class)
+{
+ EAccountListClass *e_account_list_class =
+ E_ACCOUNT_LIST_CLASS (object_class);
+
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ /* virtual method override */
+ object_class->dispose = dispose;
+ object_class->finalize = finalize;
+
+ e_account_list_class->account_added = account_added;
+ e_account_list_class->account_changed = account_changed;
+ e_account_list_class->account_removed = account_removed;
+
+ /* signals */
+ signals[EXCHANGE_ACCOUNT_CREATED] =
+ g_signal_new ("exchange_account_created",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ExchangeConfigListenerClass, exchange_account_created),
+ NULL, NULL,
+ e2k_marshal_NONE__POINTER,
+ G_TYPE_NONE, 1,
+ G_TYPE_POINTER);
+ signals[EXCHANGE_ACCOUNT_REMOVED] =
+ g_signal_new ("exchange_account_removed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ExchangeConfigListenerClass, exchange_account_removed),
+ NULL, NULL,
+ e2k_marshal_NONE__POINTER,
+ G_TYPE_NONE, 1,
+ G_TYPE_POINTER);
+}
+
+static void
+init (GObject *object)
+{
+ ExchangeConfigListener *config_listener =
+ EXCHANGE_CONFIG_LISTENER (object);
+
+ config_listener->priv = g_new0 (ExchangeConfigListenerPrivate, 1);
+}
+
+static void
+dispose (GObject *object)
+{
+ ExchangeConfigListener *config_listener =
+ EXCHANGE_CONFIG_LISTENER (object);
+
+ if (config_listener->priv->idle_id) {
+ g_source_remove (config_listener->priv->idle_id);
+ config_listener->priv->idle_id = 0;
+ }
+
+ if (config_listener->priv->gconf) {
+ g_object_unref (config_listener->priv->gconf);
+ config_listener->priv->gconf = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+ ExchangeConfigListener *config_listener =
+ EXCHANGE_CONFIG_LISTENER (object);
+
+ g_free (config_listener->priv->configured_name);
+ g_free (config_listener->priv->configured_uri);
+ g_free (config_listener->priv);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+E2K_MAKE_TYPE (exchange_config_listener, ExchangeConfigListener, class_init, init, PARENT_TYPE)
+
+
+#define EVOLUTION_URI_PREFIX "evolution:/"
+#define EVOLUTION_URI_PREFIX_LEN (sizeof (EVOLUTION_URI_PREFIX) - 1)
+
+static EFolder *
+standard_folder (ExchangeAccount *account, const char *folder_type)
+{
+ const char *uri;
+
+ uri = exchange_account_get_standard_uri (account, folder_type);
+ if (!uri)
+ return NULL;
+ return exchange_account_get_folder (account, uri);
+}
+
+static void
+set_special_mail_folder (ExchangeAccount *account, const char *folder_type,
+ char **physical_uri)
+{
+ EFolder *folder;
+
+ folder = standard_folder (account, folder_type);
+ if (!folder)
+ return;
+
+ g_free (*physical_uri);
+ *physical_uri = g_strdup (e_folder_get_physical_uri (folder));
+}
+
+static void
+add_defaults_for_account (ExchangeConfigListener *config_listener,
+ E2kContext *ctx,
+ ExchangeAccount *account)
+{
+ EAccount *eaccount;
+
+#if LDEAD
+ add_autocompletion_folders (config_listener->priv->gconf, account);
+#endif
+
+ eaccount = config_listener->priv->configured_account;
+ set_special_mail_folder (account, "drafts",
+ &eaccount->drafts_folder_uri);
+ set_special_mail_folder (account, "sentitems",
+ &eaccount->sent_folder_uri);
+ e_account_list_change (E_ACCOUNT_LIST (config_listener), eaccount);
+ e_account_list_save (E_ACCOUNT_LIST (config_listener));
+}
+
+
+static gboolean
+is_active_exchange_account (EAccount *account)
+{
+ if (!account->enabled)
+ return FALSE;
+ if (!account->source || !account->source->url)
+ return FALSE;
+ return (strncmp (account->source->url, EXCHANGE_URI_PREFIX, 11) == 0);
+}
+
+static void
+add_account_esources (ExchangeAccount *account,
+ GSList *folders)
+{
+ ESource *source = NULL;
+ ESourceGroup *cal_source_group = NULL;
+ ESourceGroup *tasks_source_group = NULL;
+ ESourceGroup *contacts_source_group = NULL;
+ char *relative_uri = NULL, *username = NULL;
+ GSList *ids;
+ GConfClient *client;
+ int mode;
+ ESourceList *cal_source_list, *tasks_source_list, *contacts_source_list;
+ FolderInfo *folder=NULL;
+ gboolean offline_mode = FALSE;
+
+ client = gconf_client_get_default ();
+
+ cal_source_list = e_source_list_new_for_gconf ( client, CONF_KEY_CAL);
+ tasks_source_list = e_source_list_new_for_gconf ( client, CONF_KEY_TASKS);
+ contacts_source_list = e_source_list_new_for_gconf ( client, CONF_KEY_CONTACTS);
+
+ exchange_account_is_offline_sync_set (account, &mode);
+ if (mode == OFFLINE_MODE) {
+ /* If account is marked for offline sync during account
+ * creation, mark all the folders for offline sync
+ */
+ offline_mode = TRUE;
+ }
+
+ username = exchange_account_get_username (account);
+
+ /* For each component create a source group */
+
+ cal_source_group = e_source_group_new (account->account_name,
+ EXCHANGE_URI_PREFIX);
+ tasks_source_group = e_source_group_new (account->account_name,
+ EXCHANGE_URI_PREFIX);
+ contacts_source_group = e_source_group_new (account->account_name,
+ EXCHANGE_URI_PREFIX);
+
+ if (!e_source_list_add_group (contacts_source_list, contacts_source_group, -1) ||
+ !e_source_list_add_group (cal_source_list, cal_source_group, -1) ||
+ !e_source_list_add_group (tasks_source_list, tasks_source_group, -1)) {
+ goto done;
+ }
+ for ( ; folders != NULL ; folders = g_slist_next (folders)) {
+ /* Create source for each folder and add to the group */
+
+ folder = folders->data;
+ if (folder->type == EXCHANGE_CONTACTS_FOLDER) {
+ source = e_source_new_with_absolute_uri (folder->name,
+ folder->uri);
+ if (offline_mode)
+ e_source_set_property (source, "offline_sync", "1");
+ if (username)
+ e_source_set_property (source, "username", username);
+ e_source_group_add_source (contacts_source_group,
+ source, -1);
+ g_object_unref (source);
+ }
+ else if (folder->type == EXCHANGE_CALENDAR_FOLDER){
+ relative_uri = g_strdup (folder->uri +
+ strlen (EXCHANGE_URI_PREFIX));
+ source = e_source_new (folder->name, relative_uri);
+ if (offline_mode)
+ e_source_set_property (source, "offline_sync", "1");
+ if (username)
+ e_source_set_property (source, "username", username);
+ e_source_group_add_source (cal_source_group,
+ source, -1);
+
+ ids = gconf_client_get_list (client,
+ CONF_KEY_SELECTED_CAL_SOURCES,
+ GCONF_VALUE_STRING, NULL);
+ ids = g_slist_append (ids,
+ g_strdup (e_source_peek_uid (source)));
+ gconf_client_set_list (client,
+ CONF_KEY_SELECTED_CAL_SOURCES,
+ GCONF_VALUE_STRING, ids, NULL);
+ g_slist_foreach (ids, (GFunc) g_free, NULL);
+ g_slist_free (ids);
+ g_object_unref (source);
+ g_free (relative_uri);
+
+ }
+ else if (folder->type == EXCHANGE_TASKS_FOLDER){
+ relative_uri = g_strdup (folder->uri +
+ strlen (EXCHANGE_URI_PREFIX));
+ source = e_source_new (folder->name, relative_uri);
+ if (offline_mode)
+ e_source_set_property (source, "offline_sync", "1");
+ if (username)
+ e_source_set_property (source, "username", username);
+ e_source_group_add_source (tasks_source_group,
+ source, -1);
+
+ ids = gconf_client_get_list (client,
+ CONF_KEY_SELECTED_TASKS_SOURCES,
+ GCONF_VALUE_STRING, NULL);
+
+ ids = g_slist_append (ids,
+ g_strdup (e_source_peek_uid (source)));
+ gconf_client_set_list (client,
+ CONF_KEY_SELECTED_TASKS_SOURCES,
+ GCONF_VALUE_STRING, ids, NULL);
+ g_slist_foreach (ids, (GFunc) g_free, NULL);
+ g_slist_free (ids);
+ g_object_unref (source);
+ g_free (relative_uri);
+ }
+ }
+
+ e_source_list_sync (cal_source_list, NULL);
+ e_source_list_sync (tasks_source_list, NULL);
+ e_source_list_sync (contacts_source_list, NULL);
+
+done:
+ g_object_unref (cal_source_group);
+ g_object_unref (tasks_source_group);
+ g_object_unref (contacts_source_group);
+
+ g_object_unref (cal_source_list);
+ g_object_unref (tasks_source_list);
+ g_object_unref (contacts_source_list);
+
+ g_object_unref (client);
+}
+
+void
+add_folder_esource (ExchangeAccount *account,
+ FolderType folder_type,
+ const char *folder_name,
+ const char *physical_uri)
+{
+ ESource *source = NULL;
+ ESourceGroup *source_group = NULL;
+ char *relative_uri = NULL, *username = NULL;
+ GSList *ids;
+ GConfClient *client;
+ gboolean is_contacts_folder = TRUE, group_new = FALSE, source_new = FALSE;
+ const char *offline = NULL;
+ int mode;
+ ESourceList *source_list;
+
+ client = gconf_client_get_default ();
+
+ username = exchange_account_get_username (account);
+
+ if (folder_type == EXCHANGE_CONTACTS_FOLDER) {
+ source_list = e_source_list_new_for_gconf ( client,
+ CONF_KEY_CONTACTS);
+ }
+ else if (folder_type == EXCHANGE_CALENDAR_FOLDER) {
+ source_list = e_source_list_new_for_gconf ( client,
+ CONF_KEY_CAL);
+ relative_uri = g_strdup (physical_uri + strlen (EXCHANGE_URI_PREFIX));
+ is_contacts_folder = FALSE;
+ }
+ else if (folder_type == EXCHANGE_TASKS_FOLDER) {
+ source_list = e_source_list_new_for_gconf ( client,
+ CONF_KEY_TASKS);
+ relative_uri = g_strdup (physical_uri + strlen (EXCHANGE_URI_PREFIX));
+ is_contacts_folder = FALSE;
+ }
+
+ exchange_account_is_offline_sync_set (account, &mode);
+
+ if ((source_group = e_source_list_peek_group_by_name (source_list,
+ account->account_name)) == NULL) {
+ source_group = e_source_group_new (account->account_name,
+ EXCHANGE_URI_PREFIX);
+ if (!e_source_list_add_group (source_list, source_group, -1)) {
+ g_object_unref (source_list);
+ g_object_unref (source_group);
+ g_object_unref (client);
+ g_free (relative_uri);
+ return;
+ }
+ if (is_contacts_folder)
+ source = e_source_new_with_absolute_uri (folder_name,
+ physical_uri);
+ else
+ source = e_source_new (folder_name, relative_uri);
+
+ if (mode == OFFLINE_MODE) {
+ /* If account is marked for offline sync during account
+ * creation, mark all the folders for offline sync
+ */
+ e_source_set_property (source, "offline_sync", "1");
+ }
+ if (username)
+ e_source_set_property (source, "username", username);
+ e_source_group_add_source (source_group, source, -1);
+ e_source_list_sync (source_list, NULL);
+ group_new = source_new = TRUE;
+ }
+ else {
+ /* source group already exists*/
+ if((source = e_source_group_peek_source_by_name (source_group,
+ folder_name)) == NULL) {
+ printf("old group, new source\n");
+ if (is_contacts_folder)
+ source = e_source_new_with_absolute_uri (
+ folder_name, physical_uri);
+ else
+ source = e_source_new (folder_name, relative_uri);
+
+ if (mode == OFFLINE_MODE)
+ e_source_set_property (source, "offline_sync", "1");
+ if (username)
+ e_source_set_property (source, "username", username);
+
+ e_source_group_add_source (source_group, source, -1);
+ source_new = TRUE;
+ e_source_list_sync (source_list, NULL);
+ } else {
+ /* source group and source both already exist */
+ offline = e_source_get_property (source, "offline_sync");
+ if (!offline) {
+ /* Folder doesn't have any offline property set */
+ if (mode == OFFLINE_MODE)
+ e_source_set_property (source, "offline_sync", "1");
+ }
+ }
+ }
+
+ if (source && !is_contacts_folder) {
+
+ /* Select the folder created */
+ if (folder_type == EXCHANGE_CALENDAR_FOLDER) {
+ ids = gconf_client_get_list (client,
+ CONF_KEY_SELECTED_CAL_SOURCES,
+ GCONF_VALUE_STRING, NULL);
+ ids = g_slist_append (ids,
+ g_strdup (e_source_peek_uid (source)));
+ gconf_client_set_list (client,
+ CONF_KEY_SELECTED_CAL_SOURCES,
+ GCONF_VALUE_STRING, ids, NULL);
+ g_slist_foreach (ids, (GFunc) g_free, NULL);
+ g_slist_free (ids);
+ }
+ else if (folder_type == EXCHANGE_TASKS_FOLDER) {
+
+ ids = gconf_client_get_list (client,
+ CONF_KEY_SELECTED_TASKS_SOURCES,
+ GCONF_VALUE_STRING, NULL);
+
+ ids = g_slist_append (ids,
+ g_strdup (e_source_peek_uid (source)));
+ gconf_client_set_list (client,
+ CONF_KEY_SELECTED_TASKS_SOURCES,
+ GCONF_VALUE_STRING, ids, NULL);
+ g_slist_foreach (ids, (GFunc) g_free, NULL);
+ g_slist_free (ids);
+ }
+ }
+
+ g_free (relative_uri);
+
+ if (source_new)
+ g_object_unref (source);
+ if (group_new)
+ g_object_unref (source_group);
+ g_object_unref (source_list);
+ g_object_unref (client);
+}
+
+static void
+add_sources (ExchangeAccount *account)
+{
+ GPtrArray *exchange_folders;
+
+ exchange_folders = exchange_account_get_folders (account);
+ if (exchange_folders && exchange_folders->len > 0) {
+ int i;
+ const char *folder_type;
+ EFolder *folder;
+ GSList *folders = NULL;
+
+ for (i = 0; i < exchange_folders->len; i++) {
+ FolderInfo *folder_info = g_new0 (FolderInfo, 1);
+
+ folder = exchange_folders->pdata[i];
+ folder_type = e_folder_get_type_string (folder);
+
+ if (!(strcmp (folder_type, "calendar")) ||
+ !(strcmp (folder_type, "calendar/public"))) {
+ folder_info->name = e_folder_get_name (folder);
+ folder_info->uri = e_folder_get_physical_uri (folder);
+ folder_info->type = EXCHANGE_CALENDAR_FOLDER;
+ folders = g_slist_append (folders, folder_info);
+ }
+ else if (!(strcmp (folder_type, "tasks")) ||
+ !(strcmp (folder_type, "tasks/public"))) {
+ folder_info->name = e_folder_get_name (folder);
+ folder_info->uri = e_folder_get_physical_uri (folder);
+ folder_info->type = EXCHANGE_TASKS_FOLDER;
+ folders = g_slist_append (folders, folder_info);
+ }
+ else if (!(strcmp (folder_type, "contacts")) ||
+ !(strcmp (folder_type, "contacts/public")) ||
+ !(strcmp (folder_type, "contacts/ldap"))) {
+ folder_info->name = e_folder_get_name (folder);
+ folder_info->uri = e_folder_get_physical_uri (folder);
+ folder_info->type = EXCHANGE_CONTACTS_FOLDER;
+ folders = g_slist_append (folders, folder_info);
+ }
+ else
+ g_free (folder_info);
+ }
+ /* Add e-sources for all the folders */
+ add_account_esources (account, folders);
+ g_slist_foreach (folders, (GFunc) g_free, NULL);
+ g_slist_free (folders);
+ }
+}
+
+static void
+remove_account_esource (ExchangeAccount *account,
+ FolderType folder_type)
+{
+ ESourceGroup *group;
+ ESource *source = NULL;
+ GSList *groups;
+ GSList *sources;
+ GSList *ids, *node_to_be_deleted;
+ gboolean found_group;
+ const char *source_uid;
+ GConfClient *client;
+ ESourceList *source_list;
+
+ /* Remove the ESource group, to remove all the folders in a component */
+
+ client = gconf_client_get_default ();
+
+ if (folder_type == EXCHANGE_CONTACTS_FOLDER)
+ source_list = e_source_list_new_for_gconf ( client,
+ CONF_KEY_CONTACTS);
+ else if (folder_type == EXCHANGE_CALENDAR_FOLDER)
+ source_list = e_source_list_new_for_gconf ( client,
+ CONF_KEY_CAL);
+ else if (folder_type == EXCHANGE_TASKS_FOLDER)
+ source_list = e_source_list_new_for_gconf ( client,
+ CONF_KEY_TASKS);
+
+ groups = e_source_list_peek_groups (source_list);
+ found_group = FALSE;
+
+ for ( ; groups != NULL && !found_group; groups = g_slist_next (groups)) {
+ group = E_SOURCE_GROUP (groups->data);
+
+ if (strcmp (e_source_group_peek_name (group), account->account_name) == 0
+ &&
+ strcmp (e_source_group_peek_base_uri (group), EXCHANGE_URI_PREFIX) == 0) {
+ sources = e_source_group_peek_sources (group);
+
+ for( ; sources != NULL; sources = g_slist_next (sources)) {
+ source = E_SOURCE (sources->data);
+ source_uid = e_source_peek_uid (source);
+
+ /* Remove from the selected folders */
+ if (folder_type == EXCHANGE_CALENDAR_FOLDER) {
+ ids = gconf_client_get_list (
+ client,
+ CONF_KEY_SELECTED_CAL_SOURCES ,
+ GCONF_VALUE_STRING, NULL);
+ if (ids) {
+ node_to_be_deleted = g_slist_find_custom (
+ ids,
+ source_uid,
+ (GCompareFunc) strcmp);
+ if (node_to_be_deleted) {
+ g_free (node_to_be_deleted->data);
+ ids = g_slist_delete_link (ids,
+ node_to_be_deleted);
+ gconf_client_set_list (client,
+ CONF_KEY_SELECTED_CAL_SOURCES,
+ GCONF_VALUE_STRING, ids, NULL);
+ }
+ g_slist_foreach (ids, (GFunc) g_free, NULL);
+ g_slist_free (ids);
+ }
+ }
+ else if (folder_type == EXCHANGE_TASKS_FOLDER) {
+ ids = gconf_client_get_list (client,
+ CONF_KEY_SELECTED_TASKS_SOURCES ,
+ GCONF_VALUE_STRING, NULL);
+ if (ids) {
+ node_to_be_deleted = g_slist_find_custom (
+ ids,
+ source_uid,
+ (GCompareFunc) strcmp);
+ if (node_to_be_deleted) {
+ g_free (node_to_be_deleted->data);
+ ids = g_slist_delete_link (ids,
+ node_to_be_deleted);
+ gconf_client_set_list (client,
+ CONF_KEY_SELECTED_TASKS_SOURCES,
+ GCONF_VALUE_STRING, ids, NULL);
+ }
+ g_slist_foreach (ids, (GFunc) g_free, NULL);
+ g_slist_free (ids);
+ }
+ }
+ e_source_list_remove_group (source_list, group);
+ e_source_list_sync (source_list, NULL);
+ found_group = TRUE;
+ break;
+ }
+ }
+ }
+ g_object_unref (source_list);
+ g_object_unref (client);
+}
+
+void
+remove_folder_esource (ExchangeAccount *account,
+ FolderType folder_type,
+ const char *physical_uri)
+{
+ ESourceGroup *group;
+ ESource *source;
+ GSList *groups;
+ GSList *sources;
+ gboolean found_group, is_contacts_folder = TRUE;
+ char *relative_uri = NULL;
+ const char *source_uid;
+ GSList *ids, *temp_ids, *node_to_be_deleted;
+ GConfClient *client;
+ ESourceList *source_list;
+
+ client = gconf_client_get_default ();
+
+ /* Remove ESource for a given folder */
+ if (folder_type == EXCHANGE_CONTACTS_FOLDER) {
+ source_list = e_source_list_new_for_gconf ( client,
+ CONF_KEY_CONTACTS);
+ }
+ else if (folder_type == EXCHANGE_CALENDAR_FOLDER) {
+ source_list = e_source_list_new_for_gconf ( client,
+ CONF_KEY_CAL);
+ relative_uri = g_strdup (physical_uri + strlen (EXCHANGE_URI_PREFIX));
+ is_contacts_folder = FALSE;
+ }
+ else if (folder_type == EXCHANGE_TASKS_FOLDER) {
+ source_list = e_source_list_new_for_gconf ( client,
+ CONF_KEY_TASKS);
+ relative_uri = g_strdup (physical_uri + strlen (EXCHANGE_URI_PREFIX));
+ is_contacts_folder = FALSE;
+ }
+
+ groups = e_source_list_peek_groups (source_list);
+ found_group = FALSE;
+
+ for ( ; groups != NULL && !found_group; groups = g_slist_next (groups)) {
+ group = E_SOURCE_GROUP (groups->data);
+
+ if (strcmp (e_source_group_peek_name (group), account->account_name) == 0
+ &&
+ strcmp (e_source_group_peek_base_uri (group), EXCHANGE_URI_PREFIX) == 0) {
+
+ sources = e_source_group_peek_sources (group);
+
+ for( ; sources != NULL; sources = g_slist_next (sources)) {
+
+ source = E_SOURCE (sources->data);
+
+ if (((!is_contacts_folder &&
+ strcmp (e_source_peek_relative_uri (source),
+ relative_uri) == 0)) ||
+ (is_contacts_folder &&
+ strcmp (e_source_peek_absolute_uri (source),
+ physical_uri) == 0)) {
+
+ source_uid = e_source_peek_uid (source);
+ /* Folder Deleted - Remove only the source */
+ /*
+ e_source_group_remove_source_by_uid (
+ group,
+ source_uid);
+ */
+ e_source_group_remove_source (
+ group,
+ source);
+ e_source_list_sync (source_list, NULL);
+ if (!is_contacts_folder) {
+ /* Remove from the selected folders */
+ if (folder_type == EXCHANGE_CALENDAR_FOLDER) {
+ ids = gconf_client_get_list (
+ client,
+ CONF_KEY_SELECTED_CAL_SOURCES,
+ GCONF_VALUE_STRING, NULL);
+ if (ids) {
+ node_to_be_deleted = g_slist_find_custom (ids,
+ source_uid,
+ (GCompareFunc) strcmp);
+ if (node_to_be_deleted) {
+ g_free (node_to_be_deleted->data);
+ ids = g_slist_delete_link (ids,
+ node_to_be_deleted);
+ }
+ }
+ temp_ids = ids;
+ for (; temp_ids != NULL; temp_ids = g_slist_next (temp_ids))
+ g_free (temp_ids->data);
+ g_slist_free (ids);
+ }
+ else if (folder_type == EXCHANGE_TASKS_FOLDER) {
+ ids = gconf_client_get_list (client,
+ CONF_KEY_SELECTED_TASKS_SOURCES,
+ GCONF_VALUE_STRING, NULL);
+ if (ids) {
+ node_to_be_deleted = g_slist_find_custom (ids,
+ source_uid,
+ (GCompareFunc) strcmp);
+ if (node_to_be_deleted) {
+ g_free (node_to_be_deleted->data);
+ ids = g_slist_delete_link (ids,
+ node_to_be_deleted);
+ }
+ }
+ temp_ids = ids;
+ for (; temp_ids != NULL; temp_ids = g_slist_next (temp_ids))
+ g_free (temp_ids->data);
+ g_slist_free (ids);
+ }
+ }
+ found_group = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ g_object_unref (source_list);
+ g_free (relative_uri);
+ g_object_unref (client);
+}
+
+static void
+remove_account_esources (ExchangeAccount *account)
+{
+ /* Remove ESources for all the folders in all the components */
+
+ remove_account_esource (account, EXCHANGE_CALENDAR_FOLDER);
+ remove_account_esource (account, EXCHANGE_TASKS_FOLDER);
+ remove_account_esource (account, EXCHANGE_CONTACTS_FOLDER);
+}
+
+static void
+account_added (EAccountList *account_list, EAccount *account)
+{
+ ExchangeConfigListener *config_listener;
+ ExchangeAccount *exchange_account;
+
+ if (!is_active_exchange_account (account))
+ return;
+
+ config_listener = EXCHANGE_CONFIG_LISTENER (account_list);
+ if (config_listener->priv->configured_account) {
+ /* Multiple accounts configured. */
+ /* SURF : e_notice (NULL, GTK_MESSAGE_ERROR,
+ _("You may only configure a single Exchange account"));
+ */
+ return;
+ }
+
+ /* New account! Yippee! */
+ exchange_account = exchange_account_new (account_list, account);
+ if (!exchange_account) {
+ g_warning ("Could not parse exchange uri '%s'",
+ account->source->url);
+ return;
+ }
+
+ config_listener->priv->exchange_account = exchange_account;
+ config_listener->priv->configured_account = account;
+
+ g_free (config_listener->priv->configured_uri);
+ config_listener->priv->configured_uri = g_strdup (account->source->url);
+ g_free (config_listener->priv->configured_name);
+ config_listener->priv->configured_name = g_strdup (account->name);
+
+ if (account == e_account_list_get_default (account_list)) {
+ g_signal_connect_swapped (config_listener->priv->exchange_account,
+ "connected",
+ G_CALLBACK (add_defaults_for_account),
+ config_listener);
+ }
+
+ g_signal_emit (config_listener, signals[EXCHANGE_ACCOUNT_CREATED], 0,
+ exchange_account);
+ add_sources (exchange_account);
+ exchange_account_connect (exchange_account);
+}
+
+struct account_update_data {
+ EAccountList *account_list;
+ EAccount *account;
+};
+
+static void
+configured_account_destroyed (gpointer user_data, GObject *where_account_was)
+{
+ struct account_update_data *aud = user_data;
+
+ if (!EXCHANGE_CONFIG_LISTENER (aud->account_list)->priv->configured_account)
+ account_added (aud->account_list, aud->account);
+
+ g_object_unref (aud->account_list);
+ g_object_unref (aud->account);
+ g_free (aud);
+}
+
+static gboolean
+requires_relogin (char *current_url, char *new_url)
+{
+ E2kUri *current_uri, *new_uri;
+ const char *current_param_val, *new_param_val;
+ const char *params [] = { "owa_url", "ad_server", "use_ssl" };
+ const int n_params = G_N_ELEMENTS (params);
+ int i;
+ gboolean relogin = FALSE;
+
+ current_uri = e2k_uri_new (current_url);
+ new_uri = e2k_uri_new (new_url);
+
+ if (strcmp (current_uri->user, new_uri->user) ||
+ strcmp (current_uri->host, new_uri->host)) {
+ relogin = TRUE;
+ goto end;
+ }
+
+ if (current_uri->authmech || new_uri->authmech) {
+ if (current_uri->authmech && new_uri->authmech) {
+ if (strcmp (current_uri->authmech, new_uri->authmech)) {
+ /* Auth mechanism has changed */
+ relogin = TRUE;
+ goto end;
+ }
+ }
+ else {
+ /* Auth mechanism is set for the first time */
+ relogin = TRUE;
+ goto end;
+ }
+ }
+
+ for (i=0; i<n_params; i++) {
+ current_param_val = e2k_uri_get_param (current_uri, params[i]);
+ new_param_val = e2k_uri_get_param (new_uri, params[i]);
+
+ if (current_param_val && new_param_val) {
+ /* both the urls have params to be compared */
+ if (strcmp (current_param_val, new_param_val)) {
+ relogin = TRUE;
+ break;
+ }
+ }
+ else if (current_param_val || new_param_val){
+ /* check for added or deleted parameter */
+ relogin = TRUE;
+ break;
+ }
+ }
+end:
+ e2k_uri_free (new_uri);
+ e2k_uri_free (current_uri);
+ return relogin;
+}
+
+static void
+account_changed (EAccountList *account_list, EAccount *account)
+{
+ ExchangeConfigListener *config_listener =
+ EXCHANGE_CONFIG_LISTENER (account_list);
+ ExchangeConfigListenerPrivate *priv = config_listener->priv;
+
+ if (account != config_listener->priv->configured_account) {
+ if (!is_active_exchange_account (account))
+ return;
+
+ /* The user has converted an existing non-Exchange
+ * account to an Exchange account, so treat it like an
+ * add.
+ */
+ account_added (account_list, account);
+ return;
+ } else if (!is_active_exchange_account (account)) {
+ /* The user has disabled the Exchange account or
+ * converted it to non-Exchange, so treat it like a
+ * remove.
+ */
+ account_removed (account_list, account);
+ return;
+ }
+
+ if (!strcmp (config_listener->priv->configured_uri, account->source->url) &&
+ !strcmp (config_listener->priv->configured_name, account->name)) {
+ /* The user changed something we don't care about. */
+ return;
+ }
+
+ /* OK, so he modified the active account in a way we care
+ * about. If the user hasn't connected yet, we're still ok.
+ */
+ if (!exchange_account_get_context (config_listener->priv->exchange_account)) {
+ /* Good. Remove the current account, and wait for it
+ * to actually go away (which may not happen immediately
+ * since there may be a function higher up on the stack
+ * still holding a ref on it). Then create the new one.
+ * (We have to wait for it to go away because the new
+ * storage probably still has the same name as the old
+ * one, so trying to create it before the old one is
+ * removed would fail.)
+ */
+ struct account_update_data *aud;
+
+ aud = g_new (struct account_update_data, 1);
+ aud->account = g_object_ref (account);
+ aud->account_list = g_object_ref (account_list);
+ g_object_weak_ref (G_OBJECT (config_listener->priv->exchange_account), configured_account_destroyed, aud);
+
+ account_removed (account_list, account);
+ return;
+ }
+
+ /* If account name has changed, or the url value has changed, which
+ * could be due to change in hostname or some parameter value,
+ * remove old e-sources
+ */
+ if (strcmp (config_listener->priv->configured_uri, account->source->url)) {
+ /* This condition will be true always as order of parameters in
+ * configured_uri and source->url will not match
+ */
+ remove_account_esources (priv->exchange_account);
+
+ /* Ask user to authenticate at next login if username, hostname,
+ * OWA URL or GC server values are changed.
+ */
+ if (requires_relogin (config_listener->priv->configured_uri,
+ account->source->url)) {
+ exchange_account_forget_password (priv->exchange_account);
+ }
+ else {
+ /* FIXME: modify esources and don't ask for re-login */
+ /* modify_esource (priv->exchange_account,
+ * account->source->url);
+ * return;
+ */
+ }
+ }
+ else if (strcmp (config_listener->priv->configured_name, account->name))
+ remove_account_esources (priv->exchange_account);
+
+ /* Nope. Let the user know we're ignoring him. */
+ /* SURF : e_notice (NULL, GTK_MESSAGE_WARNING,
+ _("Changes to Exchange account configuration will "
+ "take\nplace after you quit and restart Evolution."));
+ */
+
+ /* But note the new URI so if he changes something else, we
+ * only warn again if he changes again.
+ */
+ g_free (config_listener->priv->configured_uri);
+ config_listener->priv->configured_uri = g_strdup (account->source->url);
+ g_free (config_listener->priv->configured_name);
+ config_listener->priv->configured_name = g_strdup (account->name);
+}
+
+static void
+account_removed (EAccountList *account_list, EAccount *account)
+{
+ ExchangeConfigListener *config_listener =
+ EXCHANGE_CONFIG_LISTENER (account_list);
+ ExchangeConfigListenerPrivate *priv = config_listener->priv;
+
+ if (account != priv->configured_account)
+ return;
+
+ /* Remove all ESources */
+ remove_account_esources (priv->exchange_account);
+
+ exchange_account_forget_password (priv->exchange_account);
+
+ if (!exchange_account_get_context (priv->exchange_account)) {
+ /* The account isn't connected yet, so we can destroy
+ * it without problems.
+ */
+ g_signal_emit (config_listener,
+ signals[EXCHANGE_ACCOUNT_REMOVED], 0,
+ priv->exchange_account);
+
+ g_object_unref (priv->exchange_account);
+ priv->exchange_account = NULL;
+
+ priv->configured_account = NULL;
+ g_free (priv->configured_uri);
+ priv->configured_uri = NULL;
+ g_free (priv->configured_name);
+ priv->configured_name = NULL;
+ } else {
+ if (account->enabled) {
+ /* SURF : e_notice (NULL, GTK_MESSAGE_INFO,
+ _("The Exchange account will be removed when you quit Evolution"));
+ */
+ }
+ else {
+ /* The account is in use. We can't remove it. */
+ /* SURF : e_notice (NULL, GTK_MESSAGE_INFO,
+ _("The Exchange account will be disabled when you quit Evolution"));
+ */
+ }
+ }
+}
+
+static gboolean
+idle_construct (gpointer data)
+{
+ ExchangeConfigListener *config_listener = data;
+
+ config_listener->priv->idle_id = 0;
+ e_account_list_construct (E_ACCOUNT_LIST (config_listener),
+ config_listener->priv->gconf);
+ return FALSE;
+}
+
+/**
+ * exchange_config_listener_new:
+ *
+ * This creates and returns a new #ExchangeConfigListener, which
+ * monitors GConf and creates and (theoretically) destroys accounts
+ * accordingly. It will emit an %account_created signal when a new
+ * account is created (or shortly after the listener itself is created
+ * if an account already exists).
+ *
+ * Due to various constraints, the user is currently limited to a
+ * single account, and it is not possible to destroy an existing
+ * account. Thus, the %account_created signal will never be emitted
+ * more than once currently.
+ *
+ * Return value: the new config listener.
+ **/
+ExchangeConfigListener *
+exchange_config_listener_new (void)
+{
+ ExchangeConfigListener *config_listener;
+
+ config_listener = g_object_new (EXCHANGE_TYPE_CONFIG_LISTENER, NULL);
+ config_listener->priv->gconf = gconf_client_get_default ();
+
+ config_listener->priv->idle_id =
+ g_idle_add (idle_construct, config_listener);
+
+ return config_listener;
+}
+
+GSList *
+exchange_config_listener_get_accounts (ExchangeConfigListener *config_listener)
+{
+ g_return_val_if_fail (EXCHANGE_IS_CONFIG_LISTENER (config_listener), NULL);
+
+ if (config_listener->priv->exchange_account)
+ return g_slist_append (NULL, config_listener->priv->exchange_account);
+ else
+ return NULL;
+}
+