[evolution-mapi] Bug #601382 - Support for subscribe to other user's folder
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-mapi] Bug #601382 - Support for subscribe to other user's folder
- Date: Tue, 17 Jan 2012 15:21:07 +0000 (UTC)
commit 14377ea958dbd54627bf7cc786a88e758dab5865
Author: Milan Crha <mcrha redhat com>
Date: Tue Jan 17 16:20:21 2012 +0100
Bug #601382 - Support for subscribe to other user's folder
configure.ac | 1 +
po/POTFILES.in | 2 +
src/account-setup-eplugin/Makefile.am | 8 +-
.../e-mapi-account-listener.c | 216 +----
.../e-mapi-account-listener.h | 2 -
.../e-mapi-account-settings.c | 172 +++-
src/account-setup-eplugin/e-mapi-account-setup.c | 280 +++++-
src/account-setup-eplugin/e-mapi-account-setup.h | 18 +-
.../e-mapi-subscribe-foreign-folder.c | 647 ++++++++++++
.../e-mapi-subscribe-foreign-folder.h | 34 +
.../org-gnome-exchange-mapi.eplug.xml | 1 +
src/addressbook/e-book-backend-mapi-contacts.c | 111 ++-
src/calendar/e-cal-backend-mapi.c | 123 ++--
src/camel/camel-mapi-folder.c | 178 +++--
src/camel/camel-mapi-store-summary.c | 28 +-
src/camel/camel-mapi-store-summary.h | 6 +-
src/camel/camel-mapi-store.c | 382 +++++++-
src/camel/camel-mapi-store.h | 8 +-
src/libexchangemapi/e-mapi-cal-utils.c | 13 +-
src/libexchangemapi/e-mapi-connection.c | 1047 +++++++++++++-------
src/libexchangemapi/e-mapi-connection.h | 78 +-
src/libexchangemapi/e-mapi-folder.c | 332 ++++++-
src/libexchangemapi/e-mapi-folder.h | 57 +-
23 files changed, 2813 insertions(+), 931 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index f8bddf9..46ae992 100644
--- a/configure.ac
+++ b/configure.ac
@@ -109,6 +109,7 @@ dnl ********************************
dnl Check for evolution-data-server
dnl ********************************
PKG_CHECK_MODULES(EVOLUTION_DATA_SERVER, evolution-data-server-$EDS_PACKAGE >= eds_minimum_version)
+PKG_CHECK_MODULES(LIBEDATASERVERUI, libedataserverui-3.0 >= eds_minimum_version)
PKG_CHECK_MODULES(LIBEDATASERVER, libedataserver-$EDS_PACKAGE >= eds_minimum_version)
PKG_CHECK_MODULES(LIBEBACKEND, libebackend-$EDS_PACKAGE >= eds_minimum_version)
PKG_CHECK_MODULES(LIBECAL, libecal-$EDS_PACKAGE >= eds_minimum_version)
diff --git a/po/POTFILES.in b/po/POTFILES.in
index de222c0..1cdc8dc 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,6 +1,7 @@
src/account-setup-eplugin/e-mapi-account-listener.c
src/account-setup-eplugin/e-mapi-account-setup.c
src/account-setup-eplugin/e-mapi-account-settings.c
+src/account-setup-eplugin/e-mapi-subscribe-foreign-folder.c
src/account-setup-eplugin/org-gnome-exchange-mapi.eplug.xml
src/addressbook/e-book-backend-mapi.c
src/addressbook/e-book-backend-mapi-contacts.c
@@ -12,3 +13,4 @@ src/camel/camel-mapi-store.c
src/camel/camel-mapi-transport.c
src/libexchangemapi/e-mapi-cal-utils.c
src/libexchangemapi/e-mapi-connection.c
+src/libexchangemapi/e-mapi-folder.c
diff --git a/src/account-setup-eplugin/Makefile.am b/src/account-setup-eplugin/Makefile.am
index 76af68c..6058f40 100644
--- a/src/account-setup-eplugin/Makefile.am
+++ b/src/account-setup-eplugin/Makefile.am
@@ -1,8 +1,10 @@
AM_CPPFLAGS = -I . \
-DEVOLUTION_GLADEDIR=\""$(gladedir)"\" \
-DCONNECTOR_GLADEDIR=\""$(gladedir)"\" \
+ -I$(top_srcdir)/src/ \
-I$(top_srcdir)/src/libexchangemapi/ \
$(EVOLUTION_PLUGIN_CFLAGS) \
+ $(LIBEDATASERVERUI_CFLAGS) \
$(CAMEL_CFLAGS) \
$(LIBECAL_CFLAGS) \
$(LIBMAPI_CFLAGS)
@@ -19,11 +21,15 @@ liborg_gnome_exchange_mapi_la_SOURCES = \
e-mapi-account-setup.h \
e-mapi-account-settings.c \
e-mapi-account-listener.c \
- e-mapi-account-listener.h
+ e-mapi-account-listener.h \
+ e-mapi-subscribe-foreign-folder.c \
+ e-mapi-subscribe-foreign-folder.h
liborg_gnome_exchange_mapi_la_LIBADD = \
$(top_builddir)/src/libexchangemapi/libexchangemapi-1.0.la \
+ $(top_builddir)/src/camel/libcamelmapi.la \
$(EVOLUTION_PLUGIN_LIBS) \
+ $(LIBEDATASERVERUI_LIBS) \
$(CAMEL_LIBS) \
$(LIBECAL_LIBS) \
$(LIBMAPI_LIBS)
diff --git a/src/account-setup-eplugin/e-mapi-account-listener.c b/src/account-setup-eplugin/e-mapi-account-listener.c
index 85ebe54..5ea1c8b 100644
--- a/src/account-setup-eplugin/e-mapi-account-listener.c
+++ b/src/account-setup-eplugin/e-mapi-account-listener.c
@@ -217,14 +217,6 @@ find_source_by_fid (GSList *sources, const gchar *fid)
return NULL;
}
-#define CALENDAR_SOURCES "/apps/evolution/calendar/sources"
-#define TASK_SOURCES "/apps/evolution/tasks/sources"
-#define JOURNAL_SOURCES "/apps/evolution/memos/sources"
-#define SELECTED_CALENDARS "/apps/evolution/calendar/display/selected_calendars"
-#define SELECTED_TASKS "/apps/evolution/calendar/tasks/selected_tasks"
-#define SELECTED_JOURNALS "/apps/evolution/calendar/memos/selected_memos"
-#define ADDRESSBOOK_SOURCES "/apps/evolution/addressbook/sources"
-
static void
add_cal_esource (EAccount *account, GSList *folders, EMapiFolderType folder_type, CamelURL *url, CamelSettings *settings, mapi_id_t trash_fid)
{
@@ -249,13 +241,13 @@ add_cal_esource (EAccount *account, GSList *folders, EMapiFolderType folder_type
kerberos = camel_mapi_settings_get_kerberos (mapi_settings) ? "required" : NULL;
stay_synchronized = camel_offline_settings_get_stay_synchronized (CAMEL_OFFLINE_SETTINGS (settings));
- if (folder_type == MAPI_FOLDER_TYPE_APPOINTMENT) {
+ if (folder_type == E_MAPI_FOLDER_TYPE_APPOINTMENT) {
conf_key = CALENDAR_SOURCES;
source_selection_key = SELECTED_CALENDARS;
- } else if (folder_type == MAPI_FOLDER_TYPE_TASK) {
+ } else if (folder_type == E_MAPI_FOLDER_TYPE_TASK) {
conf_key = TASK_SOURCES;
source_selection_key = SELECTED_TASKS;
- } else if (folder_type == MAPI_FOLDER_TYPE_MEMO) {
+ } else if (folder_type == E_MAPI_FOLDER_TYPE_MEMO) {
conf_key = JOURNAL_SOURCES;
source_selection_key = SELECTED_JOURNALS;
} else {
@@ -350,32 +342,11 @@ add_cal_esource (EAccount *account, GSList *folders, EMapiFolderType folder_type
e_source_set_property (source, "acl-owner-name", account->id->name);
e_source_set_property (source, "acl-owner-email", account->id->address);
- if (folder_type != MAPI_FOLDER_TYPE_APPOINTMENT)
+ if (folder_type != E_MAPI_FOLDER_TYPE_APPOINTMENT)
e_source_set_property (source, "alarm", "never");
if (is_new_source || !e_source_peek_color_spec (source)) {
- static gint color_mover = 0;
- static gint color_indexer = -1;
- const guint32 colors[] = {
- 0x1464ae, /* dark blue */
- 0x14ae64, /* dark green */
- 0xae1464, /* dark red */
- 0
- };
- guint32 color;
- gchar *color_str;
-
- color_indexer++;
- if (colors[color_indexer] == 0) {
- color_mover += 1;
- color_indexer = 0;
- }
-
- color = colors[color_indexer];
- color = (color & ~(0xFF << (color_indexer * 8))) |
- (((((color >> (color_indexer * 8)) & 0xFF) + (0x33 * color_mover)) % 0xFF) << (color_indexer * 8));
-
- color_str = g_strdup_printf ("#%06x", color);
+ gchar *color_str = e_mapi_folder_pick_color_spec (1, folder_type != E_MAPI_FOLDER_TYPE_APPOINTMENT);
e_source_set_color_spec (source, color_str);
g_free (color_str);
}
@@ -403,7 +374,8 @@ add_cal_esource (EAccount *account, GSList *folders, EMapiFolderType folder_type
ESource *source = temp_list->data;
if (source && E_IS_SOURCE (source)) {
- if (g_strcmp0 (e_source_get_property (source, "public"), "yes") != 0)
+ if (!e_source_get_property (source, "foreign-username") &&
+ g_strcmp0 (e_source_get_property (source, "public"), "yes") != 0)
e_source_group_remove_source (group, source);
}
}
@@ -422,157 +394,6 @@ add_cal_esource (EAccount *account, GSList *folders, EMapiFolderType folder_type
g_object_unref (client);
}
-void e_mapi_add_esource (CamelService *service, const gchar *folder_name, const gchar *fid, gint folder_type)
-{
- CamelNetworkSettings *network_settings;
- CamelOfflineSettings *offline_settings;
- CamelMapiSettings *mapi_settings;
- CamelSettings *settings;
- ESourceList *source_list = NULL;
- ESourceGroup *group = NULL;
- const gchar *conf_key = NULL, *kerberos = NULL;
- GConfClient* client;
- GSList *sources;
- ESource *source = NULL;
- gchar *relative_uri = NULL;
- gchar *base_uri = NULL;
- const gchar *host;
- const gchar *user;
-
- g_return_if_fail (CAMEL_IS_SERVICE (service));
-
- if (folder_type == MAPI_FOLDER_TYPE_APPOINTMENT)
- conf_key = CALENDAR_SOURCES;
- else if (folder_type == MAPI_FOLDER_TYPE_TASK)
- conf_key = TASK_SOURCES;
- else if (folder_type == MAPI_FOLDER_TYPE_MEMO)
- conf_key = JOURNAL_SOURCES;
- else if (folder_type == MAPI_FOLDER_TYPE_JOURNAL)
- conf_key = JOURNAL_SOURCES;
- else if (folder_type == MAPI_FOLDER_TYPE_CONTACT)
- conf_key = ADDRESSBOOK_SOURCES;
- else {
- g_warning ("%s: %s: Unknown EMapiFolderType\n", G_STRLOC, G_STRFUNC);
- return;
- }
-
- settings = camel_service_get_settings (service);
-
- network_settings = CAMEL_NETWORK_SETTINGS (settings);
- host = camel_network_settings_get_host (network_settings);
- user = camel_network_settings_get_user (network_settings);
-
- client = gconf_client_get_default ();
- source_list = e_source_list_new_for_gconf (client, conf_key);
- base_uri = g_strdup_printf ("%s%s %s/", MAPI_URI_PREFIX, user, host);
- group = e_source_list_peek_group_by_base_uri (source_list, base_uri);
- sources = e_source_group_peek_sources (group);
- for (; sources != NULL; sources = g_slist_next (sources)) {
- ESource *source = E_SOURCE (sources->data);
- gchar * folder_id = e_source_get_duped_property (source, "folder-id");
- if (folder_id && fid) {
- if (strcmp (fid, folder_id) != 0)
- continue;
- else {
- g_warning ("%s: %s: Esource Already exist \n", G_STRLOC, G_STRFUNC);
- return;
- }
- }
- }
-
- mapi_settings = CAMEL_MAPI_SETTINGS (settings);
- offline_settings = CAMEL_OFFLINE_SETTINGS (settings);
-
- relative_uri = g_strconcat (";", fid, NULL);
- kerberos = camel_mapi_settings_get_kerberos (mapi_settings) ? "required" : NULL;
- source = e_source_new (folder_name, relative_uri);
- e_source_set_property (source, "auth", "1");
- e_source_set_property (source, "auth-type", "plain/password");
- e_source_set_property (source, "username", user);
- e_source_set_property (source, "host", host);
- e_source_set_property (source, "profile", camel_mapi_settings_get_profile (mapi_settings));
- e_source_set_property (source, "domain", camel_mapi_settings_get_domain (mapi_settings));
- e_source_set_property (source, "realm", camel_mapi_settings_get_realm (mapi_settings));
- e_source_set_property (source, "folder-id", fid);
- e_source_set_property (source, "offline_sync", camel_offline_settings_get_stay_synchronized (offline_settings) ? "1" : "0");
- e_source_set_property (source, "public", "yes");
- e_source_set_property (source, "delete", "yes");
- SET_KRB_SSO(source, kerberos);
-
- e_source_group_add_source (group, source, -1);
-
- g_object_unref (source);
- g_free (relative_uri);
-
- if (!e_source_list_add_group (source_list, group, -1))
- return;
-
- if (!e_source_list_sync (source_list, NULL))
- return;
-
- g_object_unref (group);
- g_object_unref (source_list);
- g_object_unref (client);
-}
-
-void e_mapi_remove_esource (CamelService *service, const gchar * folder_name, const gchar *fid, gint folder_type)
-{
- CamelNetworkSettings *network_settings;
- CamelSettings *settings;
- ESourceList *source_list = NULL;
- ESourceGroup *group = NULL;
- const gchar *conf_key = NULL;
- GConfClient* client;
- GSList *sources=NULL;
- gchar *base_uri = NULL;
- const gchar *host;
- const gchar *user;
-
- g_return_if_fail (CAMEL_IS_SERVICE (service));
-
- if (folder_type == MAPI_FOLDER_TYPE_APPOINTMENT)
- conf_key = CALENDAR_SOURCES;
- else if (folder_type == MAPI_FOLDER_TYPE_TASK)
- conf_key = TASK_SOURCES;
- else if (folder_type == MAPI_FOLDER_TYPE_MEMO)
- conf_key = JOURNAL_SOURCES;
- else if (folder_type == MAPI_FOLDER_TYPE_JOURNAL)
- conf_key = JOURNAL_SOURCES;
- else if (folder_type == MAPI_FOLDER_TYPE_CONTACT)
- conf_key = ADDRESSBOOK_SOURCES;
- else {
- g_warning ("%s: %s: Unknown EMapiFolderType\n", G_STRLOC, G_STRFUNC);
- return;
- }
-
- settings = camel_service_get_settings (service);
-
- network_settings = CAMEL_NETWORK_SETTINGS (settings);
- host = camel_network_settings_get_host (network_settings);
- user = camel_network_settings_get_user (network_settings);
-
- client = gconf_client_get_default ();
- source_list = e_source_list_new_for_gconf (client, conf_key);
- base_uri = g_strdup_printf ("%s%s %s/", MAPI_URI_PREFIX, user, host);
- group = e_source_list_peek_group_by_base_uri (source_list, base_uri);
- sources = e_source_group_peek_sources (group);
-
- for (; sources != NULL; sources = g_slist_next (sources)) {
- ESource *source = E_SOURCE (sources->data);
- gchar * folder_id = e_source_get_duped_property (source, "folder-id");
- if (folder_id && fid)
- if (strcmp(fid, folder_id) == 0) {
- e_source_group_remove_source(group, source);
- break;
- }
- }
-
- g_free (base_uri);
- g_object_unref (source_list);
- g_object_unref (client);
-
-}
-
static void
remove_cal_esource (EAccount *existing_account_info, EMapiFolderType folder_type, CamelURL *url)
{
@@ -584,13 +405,13 @@ remove_cal_esource (EAccount *existing_account_info, EMapiFolderType folder_type
GSList *node_tobe_deleted;
gchar *base_uri;
- if (folder_type == MAPI_FOLDER_TYPE_APPOINTMENT) {
+ if (folder_type == E_MAPI_FOLDER_TYPE_APPOINTMENT) {
conf_key = CALENDAR_SOURCES;
source_selection_key = SELECTED_CALENDARS;
- } else if (folder_type == MAPI_FOLDER_TYPE_TASK) {
+ } else if (folder_type == E_MAPI_FOLDER_TYPE_TASK) {
conf_key = TASK_SOURCES;
source_selection_key = SELECTED_TASKS;
- } else if (folder_type == MAPI_FOLDER_TYPE_MEMO) {
+ } else if (folder_type == E_MAPI_FOLDER_TYPE_MEMO) {
conf_key = JOURNAL_SOURCES;
source_selection_key = SELECTED_JOURNALS;
} else {
@@ -653,9 +474,9 @@ add_calendar_sources (EAccount *account, GSList *folders, mapi_id_t trash_fid)
settings = g_object_new (CAMEL_TYPE_MAPI_SETTINGS, NULL);
camel_settings_load_from_url (settings, url);
- add_cal_esource (account, folders, MAPI_FOLDER_TYPE_APPOINTMENT, url, settings, trash_fid);
- add_cal_esource (account, folders, MAPI_FOLDER_TYPE_TASK, url, settings, trash_fid);
- add_cal_esource (account, folders, MAPI_FOLDER_TYPE_MEMO, url, settings, trash_fid);
+ add_cal_esource (account, folders, E_MAPI_FOLDER_TYPE_APPOINTMENT, url, settings, trash_fid);
+ add_cal_esource (account, folders, E_MAPI_FOLDER_TYPE_TASK, url, settings, trash_fid);
+ add_cal_esource (account, folders, E_MAPI_FOLDER_TYPE_MEMO, url, settings, trash_fid);
g_object_unref (settings);
camel_url_free (url);
@@ -677,9 +498,9 @@ remove_calendar_sources_async (gpointer worker_data, gboolean cancelled, gpointe
url = camel_url_new (account->source->url, NULL);
if (url) {
- remove_cal_esource (account, MAPI_FOLDER_TYPE_APPOINTMENT, url);
- remove_cal_esource (account, MAPI_FOLDER_TYPE_TASK, url);
- remove_cal_esource (account, MAPI_FOLDER_TYPE_MEMO, url);
+ remove_cal_esource (account, E_MAPI_FOLDER_TYPE_APPOINTMENT, url);
+ remove_cal_esource (account, E_MAPI_FOLDER_TYPE_TASK, url);
+ remove_cal_esource (account, E_MAPI_FOLDER_TYPE_MEMO, url);
camel_url_free (url);
}
@@ -763,7 +584,7 @@ add_addressbook_sources (EAccount *account, GSList *folders, mapi_id_t trash_fid
gchar *fid, *relative_uri;
gboolean is_new_source = FALSE;
- if (folder->container_class != MAPI_FOLDER_TYPE_CONTACT || trash_fid == e_mapi_folder_get_parent_id (folder))
+ if (folder->container_class != E_MAPI_FOLDER_TYPE_CONTACT || trash_fid == e_mapi_folder_get_parent_id (folder))
continue;
fid = e_mapi_util_mapi_id_to_string (folder->folder_id);
@@ -869,7 +690,8 @@ add_addressbook_sources (EAccount *account, GSList *folders, mapi_id_t trash_fid
ESource *source = temp_list->data;
if (source && E_IS_SOURCE (source)) {
- if (g_strcmp0 (e_source_get_property (source, "public"), "yes") != 0)
+ if (!e_source_get_property (source, "foreign-username") &&
+ g_strcmp0 (e_source_get_property (source, "public"), "yes") != 0)
e_source_group_remove_source (group, source);
}
}
diff --git a/src/account-setup-eplugin/e-mapi-account-listener.h b/src/account-setup-eplugin/e-mapi-account-listener.h
index ff65549..795b19b 100644
--- a/src/account-setup-eplugin/e-mapi-account-listener.h
+++ b/src/account-setup-eplugin/e-mapi-account-listener.h
@@ -47,8 +47,6 @@ struct _EMapiAccountListenerClass {
GObjectClass parent_class;
};
-void e_mapi_add_esource (CamelService *service, const gchar *folder_name, const gchar *fid, gint folder_type);
-void e_mapi_remove_esource (CamelService *service, const gchar *folder_name, const gchar *fid, gint folder_type);
GType e_mapi_account_listener_get_type (void);
EMapiAccountListener * e_mapi_account_listener_new (void);
diff --git a/src/account-setup-eplugin/e-mapi-account-settings.c b/src/account-setup-eplugin/e-mapi-account-settings.c
index ae55590..aab4d08 100644
--- a/src/account-setup-eplugin/e-mapi-account-settings.c
+++ b/src/account-setup-eplugin/e-mapi-account-settings.c
@@ -48,12 +48,11 @@
#include <mail/em-folder-tree.h>
#include "e-mapi-account-listener.h"
+#include "e-mapi-subscribe-foreign-folder.h"
#define FOLDERSIZE_MENU_ITEM 0
-gboolean e_plugin_ui_init (GtkUIManager *ui_manager,
- EShellView *shell_view);
-
+gboolean e_plugin_ui_init (GtkUIManager *ui_manager, EShellView *shell_view);
GtkWidget *org_gnome_e_mapi_settings (EPlugin *epl, EConfigHookItemFactoryData *data);
enum {
@@ -218,9 +217,10 @@ folder_size_clicked (GtkButton *button,
mapi_settings_run_folder_size_dialog (profile, NULL);
}
-static void
-action_folder_size_cb (GtkAction *action,
- EShellView *shell_view)
+static gchar *
+get_profile_name_from_folder_tree (EShellView *shell_view,
+ gchar **pfolder_uri,
+ CamelStore **pstore)
{
EShellSidebar *shell_sidebar;
EMFolderTree *folder_tree;
@@ -260,11 +260,31 @@ action_folder_size_cb (GtkAction *action,
service = CAMEL_SERVICE (store);
settings = camel_service_get_settings (service);
g_object_get (settings, "profile", &profile, NULL);
+
+ if (pstore && profile)
+ *pstore = g_object_ref (store);
}
}
}
g_object_unref (folder_tree);
+
+ if (pfolder_uri)
+ *pfolder_uri = folder_uri;
+ else
+ g_free (folder_uri);
+
+ return profile;
+}
+
+static void
+action_folder_size_cb (GtkAction *action,
+ EShellView *shell_view)
+{
+ gchar *folder_uri = NULL;
+ gchar *profile = NULL;
+
+ profile = get_profile_name_from_folder_tree (shell_view, &folder_uri, NULL);
g_return_if_fail (folder_uri != NULL);
if (g_str_has_prefix (folder_uri, "mapi://"))
@@ -275,47 +295,29 @@ action_folder_size_cb (GtkAction *action,
}
static void
-folder_size_actions_update_cb (EShellView *shell_view, GtkActionEntry *entries)
+action_subscribe_foreign_folder_cb (GtkAction *action,
+ EShellView *shell_view)
{
- EShellWindow *shell_window;
- GtkActionGroup *action_group;
- GtkUIManager *ui_manager;
- GtkAction *folder_size_action;
-
- EShellSidebar *shell_sidebar;
- EMFolderTree *folder_tree;
- gchar *folder_uri = NULL;
- CamelURL *url = NULL;
- gboolean show_menu_entry = FALSE;
+ gchar *profile;
+ GtkWindow *parent;
+ EShellBackend *backend;
+ CamelSession *session = NULL;
+ CamelStore *store = NULL;
- shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
- g_object_get (shell_sidebar, "folder-tree", &folder_tree, NULL);
- folder_uri = em_folder_tree_get_selected_uri (folder_tree);
- g_object_unref (folder_tree);
- if (!(folder_uri && *folder_uri)) {
- g_free (folder_uri);
+ profile = get_profile_name_from_folder_tree (shell_view, NULL, &store);
+ if (!profile)
return;
- }
- shell_window = e_shell_view_get_shell_window (shell_view);
+ g_free (profile);
- ui_manager = e_shell_window_get_ui_manager (shell_window);
- action_group = e_lookup_action_group (ui_manager, "mail");
+ parent = GTK_WINDOW (e_shell_view_get_shell_window (shell_view));
+ backend = e_shell_view_get_shell_backend (shell_view);
+ g_object_get (G_OBJECT (backend), "session", &session, NULL);
- folder_size_action = gtk_action_group_get_action (action_group,
- "mail-mapi-folder-size");
+ e_mapi_subscribe_foreign_folder (parent, session, store);
- /* Show / Hide action entry */
- if (g_str_has_prefix (folder_uri, "mapi://")) {
- show_menu_entry = TRUE;
- url = camel_url_new (folder_uri, NULL);
- if (url && url->path && strlen (url->path) > 1)
- show_menu_entry = FALSE;
- camel_url_free (url);
- }
-
- gtk_action_set_visible (folder_size_action, show_menu_entry);
- g_free (folder_uri);
+ g_object_unref (session);
+ g_object_unref (store);
}
/* used only in Account Editor */
@@ -377,16 +379,96 @@ org_gnome_e_mapi_settings (EPlugin *epl, EConfigHookItemFactoryData *data)
return GTK_WIDGET (vsettings);
}
-static GtkActionEntry folder_size_entries[] = {
+static GtkActionEntry folder_context_entries[] = {
{ "mail-mapi-folder-size",
NULL,
- N_("Folder size"),
+ N_("Folder size..."),
NULL,
NULL, /* XXX Add a tooltip! */
- G_CALLBACK (action_folder_size_cb) }
+ G_CALLBACK (action_folder_size_cb) },
+
+ { "mail-mapi-subscribe-foreign-folder",
+ NULL,
+ N_("Subscribe to other user's folder..."),
+ NULL,
+ NULL, /* XXX Add a tooltip! */
+ G_CALLBACK (action_subscribe_foreign_folder_cb) }
};
+static void
+mapi_plugin_update_actions_cb (EShellView *shell_view,
+ GtkActionEntry *entries)
+{
+ EShellWindow *shell_window;
+ GtkActionGroup *action_group;
+ GtkUIManager *ui_manager;
+ EShellSidebar *shell_sidebar;
+ EMFolderTree *folder_tree;
+ gchar *folder_uri = NULL;
+ CamelURL *url = NULL;
+ gboolean show_menu_entry = FALSE;
+ gint ii;
+ GSList *actions = NULL, *iter;
+ gboolean online = FALSE;
+
+ shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
+ g_object_get (shell_sidebar, "folder-tree", &folder_tree, NULL);
+ folder_uri = em_folder_tree_get_selected_uri (folder_tree);
+ g_object_unref (folder_tree);
+ if (!(folder_uri && *folder_uri)) {
+ g_free (folder_uri);
+ return;
+ }
+
+ shell_window = e_shell_view_get_shell_window (shell_view);
+
+ ui_manager = e_shell_window_get_ui_manager (shell_window);
+ action_group = e_lookup_action_group (ui_manager, "mail");
+
+ for (ii = 0; ii < G_N_ELEMENTS (folder_context_entries); ii++) {
+ GtkAction *action;
+
+ action = gtk_action_group_get_action (action_group, folder_context_entries[ii].name);
+ if (action)
+ actions = g_slist_prepend (actions, action);
+ }
+
+ /* Show / Hide action entry */
+ if (g_str_has_prefix (folder_uri, "mapi://")) {
+ show_menu_entry = TRUE;
+ url = camel_url_new (folder_uri, NULL);
+ if (url && url->path && strlen (url->path) > 1)
+ show_menu_entry = FALSE;
+ camel_url_free (url);
+ }
+
+ g_free (folder_uri);
+
+ if (show_menu_entry) {
+ EShellBackend *backend;
+ CamelSession *session = NULL;
+
+ backend = e_shell_view_get_shell_backend (shell_view);
+ g_object_get (G_OBJECT (backend), "session", &session, NULL);
+
+ online = session && camel_session_get_online (session);
+
+ if (session)
+ g_object_unref (session);
+ }
+
+ for (iter = actions; iter; iter = iter->next) {
+ GtkAction *action = iter->data;
+
+ gtk_action_set_visible (action, show_menu_entry);
+ if (show_menu_entry)
+ gtk_action_set_sensitive (action, online);
+ }
+
+ g_slist_free (actions);
+}
+
gboolean
e_plugin_ui_init (GtkUIManager *ui_manager,
EShellView *shell_view)
@@ -399,11 +481,11 @@ e_plugin_ui_init (GtkUIManager *ui_manager,
/* Add actions to the "mail" action group. */
e_action_group_add_actions_localized (action_group, GETTEXT_PACKAGE,
- folder_size_entries, G_N_ELEMENTS (folder_size_entries), shell_view);
+ folder_context_entries, G_N_ELEMENTS (folder_context_entries), shell_view);
/* Decide whether we want this option to be visible or not */
g_signal_connect (shell_view, "update-actions",
- G_CALLBACK (folder_size_actions_update_cb),
+ G_CALLBACK (mapi_plugin_update_actions_cb),
shell_view);
g_object_unref (action_group);
diff --git a/src/account-setup-eplugin/e-mapi-account-setup.c b/src/account-setup-eplugin/e-mapi-account-setup.c
index 10cd1f4..03d18ef 100644
--- a/src/account-setup-eplugin/e-mapi-account-setup.c
+++ b/src/account-setup-eplugin/e-mapi-account-setup.c
@@ -579,7 +579,7 @@ traverse_tree (GtkTreeModel *model, GtkTreeIter iter, EMapiFolderType folder_typ
}
gtk_tree_model_get (model, &iter, FOLDER_COL, &folder, -1);
- if (folder && (e_mapi_folder_get_type (folder) == folder_type || (folder_type == MAPI_FOLDER_TYPE_MEMO && e_mapi_folder_get_type (folder) == MAPI_FOLDER_TYPE_JOURNAL))) {
+ if (folder && (e_mapi_folder_get_type (folder) == folder_type || (folder_type == E_MAPI_FOLDER_TYPE_MEMO && e_mapi_folder_get_type (folder) == E_MAPI_FOLDER_TYPE_JOURNAL))) {
sub_used = TRUE;
}
@@ -689,6 +689,20 @@ e_mapi_cursor_change (GtkTreeView *treeview, ESource *source)
}
}
+static EMapiFolderCategory
+e_mapi_source_to_folder_category (ESource *source)
+{
+ g_return_val_if_fail (source != NULL, E_MAPI_FOLDER_CATEGORY_UNKNOWN);
+
+ if (e_source_get_property (source, "foreign-username"))
+ return E_MAPI_FOLDER_CATEGORY_FOREIGN;
+
+ if (g_strcmp0 (e_source_get_property (source, "public"), "yes") == 0)
+ return E_MAPI_FOLDER_CATEGORY_PUBLIC;
+
+ return E_MAPI_FOLDER_CATEGORY_PERSONAL;
+}
+
static GtkWidget *
e_mapi_create (GtkWidget *parent, ESource *source, EMapiFolderType folder_type)
{
@@ -715,6 +729,15 @@ e_mapi_create (GtkWidget *parent, ESource *source, EMapiFolderType folder_type)
e_plugin_util_add_check (parent, _("Lis_ten for server notifications"), source, "server-notification", "true", NULL);
+ switch (e_mapi_source_to_folder_category (source)) {
+ case E_MAPI_FOLDER_CATEGORY_FOREIGN:
+ case E_MAPI_FOLDER_CATEGORY_PUBLIC:
+ /* no extra options for subscribed folders */
+ return NULL;
+ default:
+ break;
+ }
+
folders = NULL;
group = e_source_peek_group (source);
profile = g_strdup (e_source_get_property (source, "profile"));
@@ -736,7 +759,7 @@ e_mapi_create (GtkWidget *parent, ESource *source, EMapiFolderType folder_type)
table = g_object_new (GTK_TYPE_TABLE, NULL);
- if (folder_type == MAPI_FOLDER_TYPE_CONTACT) {
+ if (folder_type == E_MAPI_FOLDER_TYPE_CONTACT) {
gtk_container_add (GTK_CONTAINER (parent), table);
} else {
g_object_get (parent, "n-rows", &row, NULL);
@@ -781,7 +804,7 @@ e_mapi_create_addressbook (EPlugin *epl, EConfigHookItemFactoryData *data)
{
EABConfigTargetSource *t = (EABConfigTargetSource *) data->target;
- return e_mapi_create (data->parent, t->source, MAPI_FOLDER_TYPE_CONTACT);
+ return e_mapi_create (data->parent, t->source, E_MAPI_FOLDER_TYPE_CONTACT);
}
GtkWidget *
@@ -792,13 +815,13 @@ e_mapi_create_calendar (EPlugin *epl, EConfigHookItemFactoryData *data)
switch (t->source_type) {
case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
- folder_type = MAPI_FOLDER_TYPE_APPOINTMENT;
+ folder_type = E_MAPI_FOLDER_TYPE_APPOINTMENT;
break;
case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
- folder_type = MAPI_FOLDER_TYPE_TASK;
+ folder_type = E_MAPI_FOLDER_TYPE_TASK;
break;
case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
- folder_type = MAPI_FOLDER_TYPE_MEMO;
+ folder_type = E_MAPI_FOLDER_TYPE_MEMO;
break;
default:
g_return_val_if_reached (NULL);
@@ -817,22 +840,49 @@ e_mapi_book_check (EPlugin *epl, EConfigHookPageCheckData *data)
if (!uri_text)
return TRUE;
- /* FIXME: Offline handling */
-
/* not a MAPI account */
if (g_ascii_strncasecmp (uri_text, MAPI_URI_PREFIX, MAPI_PREFIX_LENGTH)) {
g_free (uri_text);
return TRUE;
}
+ g_free (uri_text);
+
/* does not have a parent-fid which is needed for folder creation on server */
- if (!e_source_get_property (source, "parent-fid")) {
- g_free (uri_text);
- return FALSE;
- }
+ return e_source_get_property (source, "parent-fid") ||
+ e_source_get_property (source, "foreign-username") ||
+ g_strcmp0 (e_source_get_property (source, "public"), "yes") == 0;
+}
- g_free (uri_text);
- return TRUE;
+static gboolean
+emas_open_folder (ESource *source,
+ EMapiConnection *conn,
+ mapi_id_t fid,
+ mapi_object_t *obj_folder,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ gchar *foreign_username;
+ gboolean is_public_folder;
+ gboolean res;
+
+ g_return_val_if_fail (source != NULL, FALSE);
+ g_return_val_if_fail (conn != NULL, FALSE);
+ g_return_val_if_fail (obj_folder != NULL, FALSE);
+
+ is_public_folder = g_strcmp0 (e_source_get_property (source, "public"), "yes") == 0;
+ foreign_username = e_source_get_duped_property (source, "foreign-username");
+
+ if (foreign_username)
+ res = e_mapi_connection_open_foreign_folder (conn, foreign_username, fid, obj_folder, cancellable, perror);
+ else if (is_public_folder)
+ res = e_mapi_connection_open_public_folder (conn, fid, obj_folder, cancellable, perror);
+ else
+ res = e_mapi_connection_open_personal_folder (conn, fid, obj_folder, cancellable, perror);
+
+ g_free (foreign_username);
+
+ return res;
}
void
@@ -845,19 +895,35 @@ e_mapi_book_commit (EPlugin *epl, EConfigTarget *target)
ESourceGroup *grp;
EMapiConnection *conn;
mapi_id_t fid, pfid;
+ mapi_object_t obj_folder;
GError *mapi_error = NULL;
uri_text = e_source_get_uri (source);
if (uri_text && g_ascii_strncasecmp (uri_text, MAPI_URI_PREFIX, MAPI_PREFIX_LENGTH))
return;
+ switch (e_mapi_source_to_folder_category (source)) {
+ case E_MAPI_FOLDER_CATEGORY_FOREIGN:
+ case E_MAPI_FOLDER_CATEGORY_PUBLIC:
+ /* no extra changes for subscribed folders */
+ return;
+ default:
+ break;
+ }
+
e_mapi_util_mapi_id_from_string (e_source_get_property (source, "parent-fid"), &pfid);
/* the profile should be already connected */
conn = e_mapi_connection_find (e_source_get_property (source, "profile"));
g_return_if_fail (conn != NULL);
- fid = e_mapi_connection_create_folder (conn, olFolderContacts, pfid, 0, e_source_peek_name (source), NULL, &mapi_error);
+ fid = 0;
+ if (emas_open_folder (source, conn, pfid, &obj_folder, NULL, NULL)) {
+ if (!e_mapi_connection_create_folder (conn, &obj_folder, e_source_peek_name (source), IPF_CONTACT, &fid, NULL, &mapi_error))
+ fid = 0;
+ e_mapi_connection_close_folder (conn, &obj_folder, NULL, NULL);
+ }
+
g_object_unref (conn);
if (!fid) {
@@ -875,7 +941,6 @@ e_mapi_book_commit (EPlugin *epl, EConfigTarget *target)
r_uri = g_strconcat (";", sfid, NULL);
e_source_set_relative_uri (source, r_uri);
- //FIXME: Offline handling
grp = e_source_peek_group (source);
e_source_set_property (source, "auth", "plain/password");
e_source_set_property(source, "user", NULL);
@@ -896,7 +961,6 @@ e_mapi_book_commit (EPlugin *epl, EConfigTarget *target)
e_source_set_property (source, "public", "no");
e_source_set_property (source, "folder-id", sfid);
- // Update the folder list in the plugin and EMapiFolder
g_free (r_uri);
g_free (sfid);
@@ -914,8 +978,6 @@ e_mapi_cal_check (EPlugin *epl, EConfigHookPageCheckData *data)
if (!uri_text)
return TRUE;
- /* FIXME: Offline handling */
-
/* not a MAPI account */
if (g_ascii_strncasecmp (uri_text, MAPI_URI_PREFIX, MAPI_PREFIX_LENGTH)) {
g_free (uri_text);
@@ -924,13 +986,9 @@ e_mapi_cal_check (EPlugin *epl, EConfigHookPageCheckData *data)
g_free (uri_text);
- /* FIXME: Offline handling */
-
- /* does not have a parent-fid which is needed for folder creation on server */
- if (!e_source_get_property (source, "parent-fid"))
- return FALSE;
-
- return TRUE;
+ return e_source_get_property (source, "parent-fid") ||
+ e_source_get_property (source, "foreign-username") ||
+ g_strcmp0 (e_source_get_property (source, "public"), "yes") == 0;
}
void
@@ -942,7 +1000,8 @@ e_mapi_cal_commit (EPlugin *epl, EConfigTarget *target)
ESource *source = t->source;
gchar *tmp, *sfid;
mapi_id_t fid, pfid;
- uint32_t type;
+ mapi_object_t obj_folder;
+ const gchar *type;
gchar *uri_text = e_source_get_uri (source);
GError *mapi_error = NULL;
@@ -950,30 +1009,43 @@ e_mapi_cal_commit (EPlugin *epl, EConfigTarget *target)
return;
g_free (uri_text);
+ switch (e_mapi_source_to_folder_category (source)) {
+ case E_MAPI_FOLDER_CATEGORY_FOREIGN:
+ case E_MAPI_FOLDER_CATEGORY_PUBLIC:
+ /* no extra changes for subscribed folders */
+ return;
+ default:
+ break;
+ }
+
switch (t->source_type) {
case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
- type = olFolderCalendar;
+ type = IPF_APPOINTMENT;
break;
case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
- type = olFolderTasks;
+ type = IPF_TASK;
break;
case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
- type = olFolderNotes;
+ type = IPF_STICKYNOTE;
break;
default:
g_warning ("%s: %s: Unknown EMapiFolderType\n", G_STRLOC, G_STRFUNC);
return;
}
- /* FIXME: Offline handling */
-
e_mapi_util_mapi_id_from_string (e_source_get_property (source, "parent-fid"), &pfid);
/* the profile should be already connected */
conn = e_mapi_connection_find (e_source_get_property (source, "profile"));
g_return_if_fail (conn != NULL);
- fid = e_mapi_connection_create_folder (conn, type, pfid, 0, e_source_peek_name (source), NULL, &mapi_error);
+ fid = 0;
+ if (emas_open_folder (source, conn, pfid, &obj_folder, NULL, NULL)) {
+ if (!e_mapi_connection_create_folder (conn, &obj_folder, e_source_peek_name (source), type, &fid, NULL, &mapi_error))
+ fid = 0;
+ e_mapi_connection_close_folder (conn, &obj_folder, NULL, NULL);
+ }
+
g_object_unref (conn);
if (!fid) {
@@ -1050,3 +1122,145 @@ e_mapi_cal_commit (EPlugin *epl, EConfigTarget *target)
// Update the folder list in the plugin and EMapiFolder
return;
}
+
+struct RunWithFeedbackData
+{
+ GtkWindow *parent;
+ GtkWidget *dialog;
+ GCancellable *cancellable;
+ GObject *with_object;
+ EMapiSetupFunc thread_func;
+ EMapiSetupFunc idle_func;
+ gpointer user_data;
+ GDestroyNotify free_user_data;
+ GError *error;
+};
+
+static void
+free_run_with_feedback_data (gpointer ptr)
+{
+ struct RunWithFeedbackData *rfd = ptr;
+
+ if (!rfd)
+ return;
+
+ if (rfd->dialog)
+ gtk_widget_destroy (rfd->dialog);
+
+ g_object_unref (rfd->cancellable);
+ g_object_unref (rfd->with_object);
+
+ if (rfd->free_user_data)
+ rfd->free_user_data (rfd->user_data);
+
+ g_clear_error (&rfd->error);
+
+ g_free (rfd);
+}
+
+static gboolean
+run_with_feedback_idle (gpointer user_data)
+{
+ struct RunWithFeedbackData *rfd = user_data;
+ gboolean was_cancelled = FALSE;
+
+ g_return_val_if_fail (rfd != NULL, FALSE);
+
+ if (!g_cancellable_is_cancelled (rfd->cancellable)) {
+ if (rfd->idle_func && !rfd->error)
+ rfd->idle_func (rfd->with_object, rfd->user_data, rfd->cancellable, &rfd->error);
+
+ was_cancelled = g_cancellable_is_cancelled (rfd->cancellable);
+
+ if (rfd->dialog) {
+ gtk_widget_destroy (rfd->dialog);
+ rfd->dialog = NULL;
+ }
+ }
+
+ if (!was_cancelled) {
+ if (rfd->error)
+ e_notice (rfd->parent, GTK_MESSAGE_ERROR, "%s", rfd->error->message);
+ }
+
+ free_run_with_feedback_data (rfd);
+
+ return FALSE;
+}
+
+static gpointer
+run_with_feedback_thread (gpointer user_data)
+{
+ struct RunWithFeedbackData *rfd = user_data;
+
+ g_return_val_if_fail (rfd != NULL, NULL);
+ g_return_val_if_fail (rfd->thread_func != NULL, NULL);
+
+ if (!g_cancellable_is_cancelled (rfd->cancellable))
+ rfd->thread_func (rfd->with_object, rfd->user_data, rfd->cancellable, &rfd->error);
+
+ g_idle_add (run_with_feedback_idle, rfd);
+
+ return NULL;
+}
+
+static void
+run_with_feedback_response_cb (GtkWidget *dialog,
+ gint resonse_id,
+ struct RunWithFeedbackData *rfd)
+{
+ g_return_if_fail (rfd != NULL);
+
+ rfd->dialog = NULL;
+ g_cancellable_cancel (rfd->cancellable);
+
+ gtk_widget_destroy (dialog);
+}
+
+void
+e_mapi_run_in_thread_with_feedback (GtkWindow *parent,
+ GObject *with_object,
+ const gchar *description,
+ EMapiSetupFunc thread_func,
+ EMapiSetupFunc idle_func,
+ gpointer user_data,
+ GDestroyNotify free_user_data)
+{
+ GtkWidget *dialog, *label, *content;
+ struct RunWithFeedbackData *rfd;
+
+ g_return_if_fail (with_object != NULL);
+ g_return_if_fail (description != NULL);
+ g_return_if_fail (thread_func != NULL);
+
+ dialog = gtk_dialog_new_with_buttons ("",
+ parent,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ NULL);
+
+ label = gtk_label_new (description);
+ gtk_widget_show (label);
+
+ content = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+ gtk_container_add (GTK_CONTAINER (content), label);
+ gtk_container_set_border_width (GTK_CONTAINER (content), 12);
+
+ rfd = g_new0 (struct RunWithFeedbackData, 1);
+ rfd->parent = parent;
+ rfd->dialog = dialog;
+ rfd->cancellable = g_cancellable_new ();
+ rfd->with_object = g_object_ref (with_object);
+ rfd->thread_func = thread_func;
+ rfd->idle_func = idle_func;
+ rfd->user_data = user_data;
+ rfd->free_user_data = free_user_data;
+ rfd->error = NULL;
+
+ g_signal_connect (dialog, "response", G_CALLBACK (run_with_feedback_response_cb), rfd);
+
+ gtk_widget_show (dialog);
+
+ g_return_if_fail (g_thread_create (run_with_feedback_thread, rfd, FALSE, NULL));
+}
diff --git a/src/account-setup-eplugin/e-mapi-account-setup.h b/src/account-setup-eplugin/e-mapi-account-setup.h
index e268dd6..7551db8 100644
--- a/src/account-setup-eplugin/e-mapi-account-setup.h
+++ b/src/account-setup-eplugin/e-mapi-account-setup.h
@@ -24,12 +24,26 @@
#ifndef E_MAPI_ACCOUNT_SETUP_H
#define E_MAPI_ACCOUNT_SETUP_H
+#include <gtk/gtk.h>
+
#include "e-mapi-account-listener.h"
#define MAPI_URI_PREFIX "mapi://"
#define MAPI_PREFIX_LENGTH 7
-EMapiAccountListener *
-e_mapi_accounts_peek_config_listener (void);
+EMapiAccountListener * e_mapi_accounts_peek_config_listener (void);
+
+typedef void (* EMapiSetupFunc) (GObject *with_object,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror);
+
+void e_mapi_run_in_thread_with_feedback (GtkWindow *parent,
+ GObject *with_object,
+ const gchar *description,
+ EMapiSetupFunc thread_func,
+ EMapiSetupFunc idle_func,
+ gpointer user_data,
+ GDestroyNotify free_user_data);
#endif /* E_MAPI_ACCOUNT_SETUP_H */
diff --git a/src/account-setup-eplugin/e-mapi-subscribe-foreign-folder.c b/src/account-setup-eplugin/e-mapi-subscribe-foreign-folder.c
new file mode 100644
index 0000000..e2e1dd5
--- /dev/null
+++ b/src/account-setup-eplugin/e-mapi-subscribe-foreign-folder.c
@@ -0,0 +1,647 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Milan Crha <mcrha redhat com>
+ *
+ * Copyright (C) 2012 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+
+#include <libedataserverui/e-name-selector.h>
+
+#include "camel/camel-mapi-store.h"
+#include "camel/camel-mapi-store-summary.h"
+
+#include "e-mapi-account-setup.h"
+#include "e-mapi-subscribe-foreign-folder.h"
+#include "e-mapi-debug.h"
+#include "e-mapi-utils.h"
+
+#ifndef PidTagMailboxOwnerName
+#define PidTagMailboxOwnerName PR_USER_NAME_UNICODE
+#endif
+
+#define STR_USER_NAME_SELECTOR_ENTRY "e-mapi-name-selector-entry"
+#define STR_FOLDER_NAME_COMBO "e-mapi-folder-name-combo"
+#define STR_MAPI_CAMEL_SESSION "e-mapi-camel-session"
+#define STR_MAPI_CAMEL_STORE "e-mapi-camel-store"
+
+static gboolean
+add_foreign_folder_to_camel (CamelMapiStore *mapi_store,
+ const gchar *foreign_username,
+ mapi_id_t folder_id,
+ mapi_id_t parent_fid,
+ const gchar *display_username,
+ const gchar *display_foldername,
+ GError **perror)
+{
+ gint ii, sz;
+ gboolean res = TRUE;
+ gchar *parent_path = NULL;
+ CamelStoreInfo *parent_si = NULL;
+
+ g_return_val_if_fail (mapi_store != NULL, FALSE);
+ g_return_val_if_fail (mapi_store->summary != NULL, FALSE);
+ g_return_val_if_fail (foreign_username != NULL, FALSE);
+ g_return_val_if_fail (folder_id != 0, FALSE);
+ g_return_val_if_fail (folder_id != parent_fid, FALSE);
+ g_return_val_if_fail (display_username != NULL, FALSE);
+ g_return_val_if_fail (display_foldername != NULL, FALSE);
+
+ sz = camel_store_summary_count (mapi_store->summary);
+ for (ii = 0; res && ii < sz; ii++) {
+ CamelStoreInfo *si;
+ CamelMapiStoreInfo *msi;
+
+ si = camel_store_summary_index (mapi_store->summary, ii);
+ if (!si)
+ continue;
+
+ msi = (CamelMapiStoreInfo *) si;
+
+ /* folder_id is unique even between users, thus can just check for it */
+ if (msi->folder_id == folder_id) {
+ res = FALSE;
+ g_propagate_error (perror,
+ g_error_new (E_MAPI_ERROR, MAPI_E_INVALID_PARAMETER,
+ _("Cannot add folder, folder already exists as '%s'"), camel_store_info_path (mapi_store->summary, si)));
+ } else if (parent_fid != 0 && msi->folder_id == parent_fid) {
+ if (g_strcmp0 (foreign_username, msi->foreign_username) == 0) {
+ g_free (parent_path);
+ parent_path = g_strdup (camel_store_info_path (mapi_store->summary, si));
+ parent_si = si;
+ camel_store_summary_info_ref (mapi_store->summary, parent_si);
+ } else {
+ g_debug ("%s: parent folder '%s' with other user '%s' than expected '%s', skipping chain",
+ G_STRFUNC, camel_store_info_path (mapi_store->summary, si), msi->foreign_username, foreign_username);
+ }
+ }
+
+ camel_store_summary_info_free (mapi_store->summary, si);
+ }
+
+ if (res) {
+ gchar *path;
+
+ if (!parent_path) {
+ gchar *mailbox;
+
+ /* Translators: The '%s' is replaced with user name, to whom the foreign mailbox belongs.
+ Example result: "Mailbox - John Smith"
+ */
+ mailbox = g_strdup_printf (C_("ForeignFolder", "Mailbox - %s"), display_username);
+ parent_path = g_strdup_printf ("%s/%s", DISPLAY_NAME_FOREIGN_FOLDERS, mailbox);
+
+ g_free (mailbox);
+ }
+
+ path = g_strconcat (parent_path, "/", display_foldername, NULL);
+
+ /* make sure the path is unique */
+ camel_mapi_store_ensure_unique_path (mapi_store, &path);
+
+ if (camel_mapi_store_summary_add_from_full (mapi_store->summary, path, folder_id, parent_fid,
+ CAMEL_STORE_INFO_FOLDER_SUBSCRIBED | CAMEL_FOLDER_NOCHILDREN | CAMEL_FOLDER_SUBSCRIBED,
+ CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN | CAMEL_MAPI_STORE_FOLDER_FLAG_MAIL,
+ foreign_username)) {
+ if (parent_si) {
+ CamelMapiStoreInfo *msi = (CamelMapiStoreInfo *) parent_si;
+
+ msi->camel_folder_flags = msi->camel_folder_flags & (~CAMEL_FOLDER_NOCHILDREN);
+ }
+
+ camel_store_summary_touch (mapi_store->summary);
+ camel_store_summary_save (mapi_store->summary);
+
+ camel_mapi_store_announce_subscribed_folder (mapi_store, path);
+ } else {
+ res = FALSE;
+ g_propagate_error (perror,
+ g_error_new (E_MAPI_ERROR, MAPI_E_INVALID_PARAMETER,
+ _("Cannot add folder, failed to add to store's summary")));
+ }
+
+ g_free (path);
+ }
+
+ if (parent_si)
+ camel_store_summary_info_free (mapi_store->summary, parent_si);
+ g_free (parent_path);
+
+ return res;
+}
+
+static void
+name_entry_changed_cb (GObject *dialog)
+{
+ GtkEntry *entry;
+ const gchar *text;
+
+ g_return_if_fail (dialog != NULL);
+
+ entry = g_object_get_data (dialog, STR_USER_NAME_SELECTOR_ENTRY);
+ g_return_if_fail (entry != NULL);
+
+ text = gtk_entry_get_text (entry);
+
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, text && *text && *text != ' ' && *text != ',');
+}
+
+struct EMapiCheckForeignFolderData
+{
+ GtkWidget *dialog;
+ gchar *username;
+ gchar *user_displayname;
+ gchar *orig_foldername;
+ gchar *use_foldername;
+ gchar *folder_displayname;
+ gchar *folder_container_class;
+ mapi_id_t folder_id;
+ mapi_id_t parent_folder_id;
+};
+
+static void
+e_mapi_check_foreign_folder_data_free (gpointer ptr)
+{
+ struct EMapiCheckForeignFolderData *cffd = ptr;
+
+ if (!cffd)
+ return;
+
+ g_free (cffd->username);
+ g_free (cffd->user_displayname);
+ g_free (cffd->orig_foldername);
+ g_free (cffd->use_foldername);
+ g_free (cffd->folder_displayname);
+ g_free (cffd->folder_container_class);
+
+ /* folder_id tells whether successfully finished,
+ then the dialog can be destroyed */
+ if (cffd->folder_id && cffd->dialog)
+ gtk_widget_destroy (cffd->dialog);
+
+ g_free (cffd);
+}
+
+static gboolean
+check_foreign_username_resolved_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ /* const */ struct mapi_SPropValue_array *properties,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ struct EMapiCheckForeignFolderData *cffd = user_data;
+
+ g_return_val_if_fail (properties != NULL, FALSE);
+ g_return_val_if_fail (cffd != NULL, FALSE);
+ g_return_val_if_fail (cffd->user_displayname == NULL, FALSE);
+
+ cffd->user_displayname = g_strdup (e_mapi_util_find_array_propval (properties, PidTagDisplayName));
+
+ return TRUE;
+}
+
+static gboolean
+foreign_folder_add_props_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ struct SPropTagArray *props,
+ gpointer data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ g_return_val_if_fail (mem_ctx != NULL, FALSE);
+ g_return_val_if_fail (props != NULL, FALSE);
+
+ SPropTagArray_add (mem_ctx, props, PidTagDisplayName);
+ SPropTagArray_add (mem_ctx, props, PidTagContainerClass);
+ SPropTagArray_add (mem_ctx, props, PidTagParentFolderId);
+
+ return TRUE;
+}
+
+static gboolean
+foreign_folder_get_props_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ /* const */ struct mapi_SPropValue_array *properties,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ struct EMapiCheckForeignFolderData *cffd = user_data;
+ const mapi_id_t *pid;
+
+ g_return_val_if_fail (properties != NULL, FALSE);
+ g_return_val_if_fail (cffd != NULL, FALSE);
+ g_return_val_if_fail (cffd->folder_displayname == NULL, FALSE);
+ g_return_val_if_fail (cffd->folder_container_class == NULL, FALSE);
+
+ pid = e_mapi_util_find_array_propval (properties, PidTagParentFolderId);
+
+ cffd->folder_displayname = g_strdup (e_mapi_util_find_array_propval (properties, PidTagDisplayName));
+ cffd->folder_container_class = g_strdup (e_mapi_util_find_array_propval (properties, PidTagContainerClass));
+ cffd->parent_folder_id = pid ? *pid : 0;
+
+ return TRUE;
+}
+
+static void
+check_foreign_folder_thread (GObject *with_object,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ struct EMapiCheckForeignFolderData *cffd = user_data;
+ GError *local_error = NULL;
+ EMapiConnection *conn;
+ mapi_object_t obj_folder;
+ mapi_id_t fid = 0;
+
+ g_return_if_fail (with_object != NULL);
+ g_return_if_fail (CAMEL_IS_MAPI_STORE (with_object));
+ g_return_if_fail (user_data != NULL);
+ g_return_if_fail (cffd->username != NULL);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+ return;
+
+ conn = camel_mapi_store_get_connection (CAMEL_MAPI_STORE (with_object));
+ if (!conn || !e_mapi_connection_connected (conn)) {
+ make_mapi_error (perror, "EMapiConnection", MAPI_E_NOT_INITIALIZED);
+ return;
+ }
+
+ if (!e_mapi_connection_resolve_username (conn, cffd->username,
+ NULL, NULL,
+ check_foreign_username_resolved_cb, cffd,
+ cancellable, perror)) {
+ make_mapi_error (perror, "e_mapi_connection_resolve_username", MAPI_E_CALL_FAILED);
+ return;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ return;
+ }
+
+ if (!e_mapi_connection_test_foreign_folder (conn, cffd->username,
+ cffd->use_foldername ? cffd->use_foldername : cffd->orig_foldername,
+ &fid, cancellable, &local_error)) {
+ if (g_error_matches (local_error, E_MAPI_ERROR, MAPI_E_NOT_FOUND)) {
+ g_clear_error (&local_error);
+ local_error = g_error_new (E_MAPI_ERROR, MAPI_E_NOT_FOUND,
+ _("Folder '%s' not found. Either it does not exist or you do not have permission to access it."),
+ cffd->orig_foldername);
+ }
+
+ g_propagate_error (perror, local_error);
+ return;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ return;
+ }
+
+ if (!e_mapi_connection_open_foreign_folder (conn, cffd->username, fid, &obj_folder, cancellable, perror)) {
+ make_mapi_error (perror, "e_mapi_connection_open_foreign_folder", MAPI_E_CALL_FAILED);
+ return;
+ }
+
+ if (!e_mapi_connection_get_folder_properties (conn, &obj_folder,
+ foreign_folder_add_props_cb, NULL,
+ foreign_folder_get_props_cb, cffd,
+ cancellable, perror)) {
+ make_mapi_error (perror, "e_mapi_connection_get_folder_properties", MAPI_E_CALL_FAILED);
+
+ e_mapi_connection_close_folder (conn, &obj_folder, cancellable, perror);
+ return;
+ }
+
+ e_mapi_connection_close_folder (conn, &obj_folder, cancellable, perror);
+
+ if (!cffd->folder_container_class) {
+ g_propagate_error (perror, g_error_new_literal (E_MAPI_ERROR, MAPI_E_CALL_FAILED, _("Cannot add folder, cannot determine folder's type")));
+ return;
+ }
+
+ cffd->folder_id = fid;
+}
+
+static void
+check_foreign_folder_idle (GObject *with_object,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ struct EMapiCheckForeignFolderData *cffd = user_data;
+ gchar *fid, *folder_name;
+ const gchar *base_username, *base_foldername;
+ CamelSettings *settings;
+ CamelMapiSettings *mapi_settings;
+ CamelMapiStore *mapi_store;
+ CamelNetworkSettings *network_settings;
+ EMapiFolderType folder_type;
+
+ g_return_if_fail (with_object != NULL);
+ g_return_if_fail (CAMEL_IS_MAPI_STORE (with_object));
+ g_return_if_fail (user_data != NULL);
+ g_return_if_fail (cffd->username != NULL);
+ g_return_if_fail (cffd->folder_container_class != NULL);
+
+ if (!cffd->folder_id)
+ return;
+
+ fid = e_mapi_util_mapi_id_to_string (cffd->folder_id);
+ g_return_if_fail (fid != NULL);
+
+ base_username = cffd->user_displayname ? cffd->user_displayname : cffd->username;
+ base_foldername = cffd->folder_displayname ? cffd->folder_displayname : cffd->orig_foldername;
+
+ /* Translators: This is used to name foreign folder.
+ The first '%s' is replaced with user name to whom the folder belongs,
+ the second '%s' is replaced with folder name.
+ Example result: "John Smith - Calendar"
+ */
+ folder_name = g_strdup_printf (C_("ForeignFolder", "%s - %s"), base_username, base_foldername);
+
+ mapi_store = CAMEL_MAPI_STORE (with_object);
+ settings = camel_service_get_settings (CAMEL_SERVICE (mapi_store));
+ mapi_settings = CAMEL_MAPI_SETTINGS (settings);
+ network_settings = CAMEL_NETWORK_SETTINGS (settings);
+
+ folder_type = e_mapi_folder_type_from_string (cffd->folder_container_class);
+ if ((folder_type == E_MAPI_FOLDER_TYPE_MAIL &&
+ !add_foreign_folder_to_camel (mapi_store,
+ cffd->username,
+ cffd->folder_id,
+ cffd->parent_folder_id,
+ base_username,
+ base_foldername,
+ perror)) ||
+ (folder_type != E_MAPI_FOLDER_TYPE_MAIL && !e_mapi_folder_add_as_esource (folder_type,
+ camel_mapi_settings_get_profile (mapi_settings),
+ camel_mapi_settings_get_domain (mapi_settings),
+ camel_mapi_settings_get_realm (mapi_settings),
+ camel_network_settings_get_host (network_settings),
+ camel_network_settings_get_user (network_settings),
+ camel_mapi_settings_get_kerberos (mapi_settings),
+ camel_offline_settings_get_stay_synchronized (CAMEL_OFFLINE_SETTINGS (mapi_settings)),
+ E_MAPI_FOLDER_CATEGORY_FOREIGN,
+ cffd->username,
+ folder_name,
+ fid,
+ perror))) {
+ /* to not destroy the dialog on error */
+ cffd->folder_id = 0;
+ }
+
+ g_free (folder_name);
+ g_free (fid);
+}
+
+static void
+subscribe_foreign_response_cb (GObject *dialog,
+ gint response_id)
+{
+ struct EMapiCheckForeignFolderData *cffd;
+ ENameSelectorEntry *entry;
+ GtkComboBoxText *combo_text;
+ EDestinationStore *dest_store;
+ CamelStore *cstore;
+ gchar *description;
+ const gchar *username;
+ gchar *orig_foldername, *use_foldername = NULL;
+
+ if (response_id != GTK_RESPONSE_OK) {
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ return;
+ }
+
+ g_return_if_fail (dialog != NULL);
+
+ entry = g_object_get_data (dialog, STR_USER_NAME_SELECTOR_ENTRY);
+ combo_text = g_object_get_data (dialog, STR_FOLDER_NAME_COMBO);
+ cstore = g_object_get_data (dialog, STR_MAPI_CAMEL_STORE);
+
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (cstore != NULL);
+
+ username = NULL;
+ dest_store = e_name_selector_entry_peek_destination_store (entry);
+ if (dest_store && e_destination_store_get_destination_count (dest_store) > 0) {
+ EDestination *dest;
+ GList *dests = e_destination_store_list_destinations (dest_store);
+
+ g_return_if_fail (dests != NULL);
+
+ /* pick the first, there is no option to limit to only one destination */
+ dest = dests->data;
+ if (dest) {
+ username = e_destination_get_email (dest);
+ if (!username || !*username)
+ username = e_destination_get_name (dest);
+ }
+
+ g_list_free (dests);
+ }
+
+ if (!username || !*username)
+ username = gtk_entry_get_text (GTK_ENTRY (entry));
+
+ orig_foldername = gtk_combo_box_text_get_active_text (combo_text);
+ if (!orig_foldername)
+ orig_foldername = g_strdup ("");
+
+ /* convert well-known names to their non-localized form */
+ if (g_strcmp0 (orig_foldername, _("Inbox")) == 0) {
+ use_foldername = g_strdup ("Inbox");
+ } else if (g_strcmp0 (orig_foldername, _("Contacts")) == 0) {
+ use_foldername = g_strdup ("Contacts");
+ } else if (g_strcmp0 (orig_foldername, _("Calendar")) == 0) {
+ use_foldername = g_strdup ("Calendar");
+ } else if (g_strcmp0 (orig_foldername, _("Memos")) == 0) {
+ use_foldername = g_strdup ("Notes");
+ } else if (g_strcmp0 (orig_foldername, _("Tasks")) == 0) {
+ use_foldername = g_strdup ("Tasks");
+ }
+
+ cffd = g_new0 (struct EMapiCheckForeignFolderData, 1);
+ cffd->dialog = GTK_WIDGET (dialog);
+ cffd->username = g_strdup (username ? username : "");
+ cffd->orig_foldername = orig_foldername;
+ cffd->use_foldername = use_foldername;
+ cffd->folder_id = 0;
+ cffd->parent_folder_id = 0;
+
+ description = g_strdup_printf (_("Testing availability of folder '%s' of user '%s', please wait..."), cffd->orig_foldername, cffd->username);
+
+ e_mapi_run_in_thread_with_feedback (
+ GTK_WINDOW (dialog),
+ G_OBJECT (cstore),
+ description,
+ check_foreign_folder_thread,
+ check_foreign_folder_idle,
+ cffd,
+ e_mapi_check_foreign_folder_data_free);
+
+ g_free (description);
+}
+
+/* Opens dialog to subscribe to folders of other
+ users in the given store */
+void
+e_mapi_subscribe_foreign_folder (GtkWindow *parent,
+ CamelSession *session,
+ CamelStore *store)
+{
+ PangoAttrList *attrs;
+ ENameSelector *name_selector;
+ ENameSelectorModel *name_selector_model;
+ ENameSelectorDialog *name_selector_dialog;
+ GObject *dialog;
+ GtkWidget *content;
+ GtkWidget *label, *widget, *entry;
+ GtkGrid *grid;
+ GtkComboBoxText *combo_text;
+ gint row;
+
+ g_return_if_fail (session != NULL);
+ g_return_if_fail (store != NULL);
+ g_return_if_fail (CAMEL_IS_MAPI_STORE (store));
+
+ dialog = G_OBJECT (gtk_dialog_new_with_buttons (
+ _("Subscribe to other MAPI user's folder..."),
+ parent,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL));
+
+ g_signal_connect (dialog, "response", G_CALLBACK (subscribe_foreign_response_cb), NULL);
+
+ content = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+ grid = GTK_GRID (gtk_grid_new ());
+ gtk_grid_set_row_homogeneous (grid, FALSE);
+ gtk_grid_set_row_spacing (grid, 6);
+ gtk_grid_set_column_homogeneous (grid, FALSE);
+ gtk_grid_set_column_spacing (grid, 6);
+ gtk_container_set_border_width (GTK_CONTAINER (grid), 12);
+ gtk_container_add (GTK_CONTAINER (content), GTK_WIDGET (grid));
+
+ row = 0;
+
+ label = gtk_label_new (_("Account:"));
+ g_object_set (G_OBJECT (label),
+ "hexpand", FALSE,
+ "vexpand", FALSE,
+ "xalign", 0.0,
+ "halign", GTK_ALIGN_START,
+ NULL);
+
+ attrs = pango_attr_list_new ();
+ pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
+ widget = gtk_label_new (camel_service_get_display_name (CAMEL_SERVICE (store)));
+ g_object_set (G_OBJECT (widget),
+ "hexpand", TRUE,
+ "vexpand", FALSE,
+ "use-underline", FALSE,
+ "attributes", attrs,
+ "xalign", 0.0,
+ "halign", GTK_ALIGN_START,
+ NULL);
+ pango_attr_list_unref (attrs);
+
+ gtk_grid_attach (grid, label, 0, row, 1, 1);
+ gtk_grid_attach (grid, widget, 1, row, 3, 1);
+
+ row++;
+
+ name_selector = e_name_selector_new ();
+ name_selector_model = e_name_selector_peek_model (name_selector);
+ e_name_selector_model_add_section (name_selector_model, "User", _("User"), NULL);
+ name_selector_dialog = e_name_selector_peek_dialog (name_selector);
+ g_signal_connect (name_selector_dialog, "response", G_CALLBACK (gtk_widget_hide), name_selector);
+ e_name_selector_load_books (name_selector);
+
+ g_object_set_data_full (dialog, "e-mapi-name-selector", name_selector, g_object_unref);
+
+ label = gtk_label_new_with_mnemonic (_("_User:"));
+ g_object_set (G_OBJECT (label),
+ "hexpand", FALSE,
+ "vexpand", FALSE,
+ "xalign", 0.0,
+ NULL);
+
+ entry = GTK_WIDGET (e_name_selector_peek_section_entry (name_selector, "User"));
+ g_object_set (G_OBJECT (entry),
+ "hexpand", TRUE,
+ "vexpand", FALSE,
+ NULL);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
+ gtk_grid_attach (grid, label, 0, row, 1, 1);
+ gtk_grid_attach (grid, entry, 1, row, 1, 1);
+
+ row++;
+
+ label = gtk_label_new_with_mnemonic (_("_Folder name:"));
+ g_object_set (G_OBJECT (label),
+ "hexpand", FALSE,
+ "vexpand", FALSE,
+ "xalign", 0.0,
+ NULL);
+
+ widget = GTK_WIDGET (g_object_new (gtk_combo_box_text_get_type (),
+ "has-entry", TRUE,
+ "entry-text-column", 0,
+ "hexpand", TRUE,
+ "vexpand", FALSE,
+ NULL));
+
+ combo_text = GTK_COMBO_BOX_TEXT (widget);
+ gtk_combo_box_text_append_text (combo_text, _("Inbox"));
+ gtk_combo_box_text_append_text (combo_text, _("Contacts"));
+ gtk_combo_box_text_append_text (combo_text, _("Calendar"));
+ gtk_combo_box_text_append_text (combo_text, _("Memos"));
+ gtk_combo_box_text_append_text (combo_text, _("Tasks"));
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo_text), 0);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
+ gtk_grid_attach (grid, label, 0, row, 1, 1);
+ gtk_grid_attach (grid, widget, 1, row, 2, 1);
+
+ /* remember widgets for later use */
+ g_object_set_data (dialog, STR_USER_NAME_SELECTOR_ENTRY, entry);
+ g_object_set_data (dialog, STR_FOLDER_NAME_COMBO, widget);
+
+ g_object_set_data_full (dialog, STR_MAPI_CAMEL_SESSION, g_object_ref (session), g_object_unref);
+ g_object_set_data_full (dialog, STR_MAPI_CAMEL_STORE, g_object_ref (store), g_object_unref);
+
+ g_signal_connect_swapped (entry, "changed", G_CALLBACK (name_entry_changed_cb), dialog);
+
+ name_entry_changed_cb (dialog);
+
+ gtk_widget_show_all (content);
+ gtk_widget_show (GTK_WIDGET (dialog));
+}
diff --git a/src/account-setup-eplugin/e-mapi-subscribe-foreign-folder.h b/src/account-setup-eplugin/e-mapi-subscribe-foreign-folder.h
new file mode 100644
index 0000000..debf5b5
--- /dev/null
+++ b/src/account-setup-eplugin/e-mapi-subscribe-foreign-folder.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Milan Crha <mcrha redhat com>
+ *
+ * Copyright (C) 2012 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_MAPI_SUBSCRIBE_FOREIGN_FOLDER_H
+#define E_MAPI_SUBSCRIBE_FOREIGN_FOLDER_H
+
+#include <gtk/gtk.h>
+#include <camel/camel.h>
+
+void e_mapi_subscribe_foreign_folder (GtkWindow *parent,
+ CamelSession *session,
+ CamelStore *store);
+
+#endif /* E_MAPI_SUBSCRIBE_FOREIGN_FOLDER_H */
diff --git a/src/account-setup-eplugin/org-gnome-exchange-mapi.eplug.xml b/src/account-setup-eplugin/org-gnome-exchange-mapi.eplug.xml
index 30207c4..849aee0 100644
--- a/src/account-setup-eplugin/org-gnome-exchange-mapi.eplug.xml
+++ b/src/account-setup-eplugin/org-gnome-exchange-mapi.eplug.xml
@@ -82,6 +82,7 @@
<popup name="mail-folder-popup">
<placeholder name="mail-folder-popup-actions">
<menuitem action="mail-mapi-folder-size"/>
+ <menuitem action="mail-mapi-subscribe-foreign-folder"/>
</placeholder>
</popup>
</ui-manager>
diff --git a/src/addressbook/e-book-backend-mapi-contacts.c b/src/addressbook/e-book-backend-mapi-contacts.c
index 0b77f9f..32ef991 100644
--- a/src/addressbook/e-book-backend-mapi-contacts.c
+++ b/src/addressbook/e-book-backend-mapi-contacts.c
@@ -54,8 +54,33 @@ struct _EBookBackendMAPIContactsPrivate
{
mapi_id_t fid;
gboolean is_public_folder;
+ gchar *foreign_username; /* NULL, if not a foreign folder */
};
+static gboolean
+ebbm_contacts_open_folder (EBookBackendMAPIContacts *ebmac,
+ EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ gboolean res;
+
+ g_return_val_if_fail (ebmac != NULL, FALSE);
+ g_return_val_if_fail (ebmac->priv != NULL, FALSE);
+ g_return_val_if_fail (conn != NULL, FALSE);
+ g_return_val_if_fail (obj_folder != NULL, FALSE);
+
+ if (ebmac->priv->foreign_username)
+ res = e_mapi_connection_open_foreign_folder (conn, ebmac->priv->foreign_username, ebmac->priv->fid, obj_folder, cancellable, perror);
+ else if (ebmac->priv->is_public_folder)
+ res = e_mapi_connection_open_public_folder (conn, ebmac->priv->fid, obj_folder, cancellable, perror);
+ else
+ res = e_mapi_connection_open_personal_folder (conn, ebmac->priv->fid, obj_folder, cancellable, perror);
+
+ return res;
+}
+
typedef struct {
EContact *contact;
EBookBackendSqliteDB *db;
@@ -305,9 +330,14 @@ ebbm_contacts_open (EBookBackendMAPI *ebma, GCancellable *cancellable, gboolean
priv->fid = 0;
priv->is_public_folder = g_strcmp0 (e_source_get_property (source, "public"), "yes") == 0;
-
+ priv->foreign_username = e_source_get_duped_property (source, "foreign-username");
e_mapi_util_mapi_id_from_string (e_source_get_property (source, "folder-id"), &priv->fid);
+ if (priv->foreign_username && !*priv->foreign_username) {
+ g_free (priv->foreign_username);
+ priv->foreign_username = NULL;
+ }
+
/* Chain up to parent's op_load_source() method. */
if (E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_open)
E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_open (ebma, cancellable, only_if_exists, &err);
@@ -320,7 +350,6 @@ static void
ebbm_contacts_connection_status_changed (EBookBackendMAPI *ebma, gboolean is_online)
{
ESource *source;
- EBookBackendMAPIContactsPrivate *priv = ((EBookBackendMAPIContacts *) ebma)->priv;
e_book_backend_notify_readonly (E_BOOK_BACKEND (ebma), !is_online);
@@ -341,10 +370,7 @@ ebbm_contacts_connection_status_changed (EBookBackendMAPI *ebma, gboolean is_onl
return;
}
- if (priv->is_public_folder)
- status = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, NULL, NULL);
- else
- status = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, NULL, NULL);
+ status = ebbm_contacts_open_folder (E_BOOK_BACKEND_MAPI_CONTACTS (ebma), conn, &obj_folder, NULL, NULL);
if (status) {
e_mapi_connection_enable_notifications (conn, &obj_folder,
@@ -381,7 +407,7 @@ ebbm_contacts_remove (EBookBackendMAPI *ebma, GCancellable *cancellable, GError
return;
}
- if (!priv->is_public_folder) {
+ if (!priv->is_public_folder && !priv->foreign_username) {
EMapiConnection *conn;
e_book_backend_mapi_lock_connection (ebma);
@@ -390,7 +416,10 @@ ebbm_contacts_remove (EBookBackendMAPI *ebma, GCancellable *cancellable, GError
if (!conn) {
g_propagate_error (error, EDB_ERROR (OFFLINE_UNAVAILABLE));
} else {
- e_mapi_connection_remove_folder (conn, priv->fid, 0, cancellable, &mapi_error);
+ mapi_object_t *obj_store = NULL;
+
+ if (e_mapi_connection_peek_store (conn, priv->foreign_username ? FALSE : priv->is_public_folder, priv->foreign_username, &obj_store, cancellable, &mapi_error))
+ e_mapi_connection_remove_folder (conn, obj_store, priv->fid, cancellable, &mapi_error);
if (mapi_error) {
mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to remove public folder"));
@@ -451,10 +480,7 @@ ebbm_contacts_create_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable
e_book_backend_mapi_get_db (ebma, &mcd.db);
mcd.contact = contact;
- if (priv->is_public_folder)
- status = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
- else
- status = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
+ status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
if (status) {
e_mapi_connection_create_object (conn, &obj_folder, E_MAPI_CREATE_FLAG_NONE,
@@ -495,6 +521,7 @@ ebbm_contacts_remove_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable
GError *mapi_error = NULL;
GSList *to_remove;
const GSList *l;
+ mapi_object_t obj_folder;
e_return_data_book_error_if_fail (ebma != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_MAPI_CONTACTS (ebma), E_DATA_BOOK_STATUS_INVALID_ARG);
@@ -531,7 +558,10 @@ ebbm_contacts_remove_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable
}
}
- e_mapi_connection_remove_items (conn, olFolderContacts, priv->fid, priv->is_public_folder ? MAPI_OPTIONS_USE_PFSTORE : 0, to_remove, cancellable, &mapi_error);
+ if (ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error)) {
+ e_mapi_connection_remove_items (conn, &obj_folder, to_remove, cancellable, &mapi_error);
+ e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
+ }
e_book_backend_mapi_unlock_connection (ebma);
@@ -599,10 +629,7 @@ ebbm_contacts_modify_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable
mapi_object_t obj_folder;
gboolean status;
- if (priv->is_public_folder)
- status = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
- else
- status = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
+ status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
if (status) {
status = e_mapi_connection_modify_object (conn, &obj_folder, mid,
@@ -672,10 +699,7 @@ ebbm_contacts_get_contact (EBookBackendMAPI *ebma, GCancellable *cancellable, co
return;
}
- if (priv->is_public_folder)
- status = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
- else
- status = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
+ status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
if (status) {
status = e_mapi_util_mapi_id_from_string (id, &mid);
@@ -758,10 +782,7 @@ ebbm_contacts_get_contact_list (EBookBackendMAPI *ebma, GCancellable *cancellabl
tcd.ebma = ebma;
tcd.cards = vCards;
- if (priv->is_public_folder)
- status = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
- else
- status = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
+ status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
if (status) {
status = e_mapi_connection_list_objects (conn, &obj_folder,
@@ -811,7 +832,6 @@ ebbm_contacts_get_contacts_count (EBookBackendMAPI *ebma,
GError **error)
{
EBookBackendMAPIContacts *ebmac;
- EBookBackendMAPIContactsPrivate *priv;
EMapiConnection *conn;
gboolean status;
mapi_object_t obj_folder;
@@ -824,8 +844,6 @@ ebbm_contacts_get_contacts_count (EBookBackendMAPI *ebma,
e_return_data_book_error_if_fail (ebmac != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (ebmac->priv != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- priv = ebmac->priv;
-
e_book_backend_mapi_lock_connection (ebma);
conn = e_book_backend_mapi_get_connection (ebma);
@@ -835,10 +853,7 @@ ebbm_contacts_get_contacts_count (EBookBackendMAPI *ebma,
return;
}
- if (priv->is_public_folder)
- status = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
- else
- status = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
+ status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
if (status) {
struct FolderBasicPropertiesData fbp = { 0 };
@@ -869,7 +884,6 @@ ebbm_contacts_list_known_uids (EBookBackendMAPI *ebma,
GError **error)
{
EBookBackendMAPIContacts *ebmac;
- EBookBackendMAPIContactsPrivate *priv;
EMapiConnection *conn;
gboolean status;
mapi_object_t obj_folder;
@@ -884,8 +898,6 @@ ebbm_contacts_list_known_uids (EBookBackendMAPI *ebma,
e_return_data_book_error_if_fail (ebmac != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
e_return_data_book_error_if_fail (ebmac->priv != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- priv = ebmac->priv;
-
e_book_backend_mapi_lock_connection (ebma);
conn = e_book_backend_mapi_get_connection (ebma);
@@ -895,10 +907,7 @@ ebbm_contacts_list_known_uids (EBookBackendMAPI *ebma,
return;
}
- if (priv->is_public_folder)
- status = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
- else
- status = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
+ status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
if (status) {
status = e_mapi_connection_list_objects (conn, &obj_folder, build_rs_cb, build_rs_cb_data,
@@ -955,10 +964,7 @@ ebbm_contacts_transfer_contacts (EBookBackendMAPI *ebma,
tcd.book_view = book_view;
tcd.notify_contact_data = notify_contact_data;
- if (priv->is_public_folder)
- status = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
- else
- status = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
+ status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
if (status) {
GSList *mids = NULL;
@@ -999,15 +1005,34 @@ static void
e_book_backend_mapi_contacts_init (EBookBackendMAPIContacts *backend)
{
backend->priv = G_TYPE_INSTANCE_GET_PRIVATE (backend, E_TYPE_BOOK_BACKEND_MAPI_CONTACTS, EBookBackendMAPIContactsPrivate);
+
+ backend->priv->foreign_username = NULL;
+}
+
+static void
+ebbm_contacts_finalize (GObject *object)
+{
+ EBookBackendMAPIContactsPrivate *priv;
+
+ priv = E_BOOK_BACKEND_MAPI_CONTACTS (object)->priv;
+
+ g_free (priv->foreign_username);
+ priv->foreign_username = NULL;
+
+ G_OBJECT_CLASS (e_book_backend_mapi_contacts_parent_class)->finalize (object);
}
static void
e_book_backend_mapi_contacts_class_init (EBookBackendMAPIContactsClass *klass)
{
EBookBackendMAPIClass *parent_class;
+ GObjectClass *object_class;
g_type_class_add_private (klass, sizeof (EBookBackendMAPIContactsPrivate));
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = ebbm_contacts_finalize;
+
parent_class = E_BOOK_BACKEND_MAPI_CLASS (klass);
/* Set the virtual methods. */
diff --git a/src/calendar/e-cal-backend-mapi.c b/src/calendar/e-cal-backend-mapi.c
index b8356fa..1947d63 100644
--- a/src/calendar/e-cal-backend-mapi.c
+++ b/src/calendar/e-cal-backend-mapi.c
@@ -68,9 +68,9 @@ struct _ECalBackendMAPIPrivate {
EMapiOperationQueue *op_queue;
mapi_id_t fid;
- uint32_t olFolder;
gchar *profile;
gboolean is_public_folder;
+ gchar *foreign_username;
EMapiConnection *conn;
/* These fields are entirely for access rights */
@@ -102,6 +102,30 @@ struct _ECalBackendMAPIPrivate {
GCancellable *cancellable;
};
+static gboolean
+ecbm_open_folder (ECalBackendMAPI *ecbm,
+ EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ gboolean res;
+
+ g_return_val_if_fail (ecbm != NULL, FALSE);
+ g_return_val_if_fail (ecbm->priv != NULL, FALSE);
+ g_return_val_if_fail (conn != NULL, FALSE);
+ g_return_val_if_fail (obj_folder != NULL, FALSE);
+
+ if (ecbm->priv->foreign_username)
+ res = e_mapi_connection_open_foreign_folder (conn, ecbm->priv->foreign_username, ecbm->priv->fid, obj_folder, cancellable, perror);
+ else if (ecbm->priv->is_public_folder)
+ res = e_mapi_connection_open_public_folder (conn, ecbm->priv->fid, obj_folder, cancellable, perror);
+ else
+ res = e_mapi_connection_open_personal_folder (conn, ecbm->priv->fid, obj_folder, cancellable, perror);
+
+ return res;
+}
+
#define CACHE_REFRESH_INTERVAL 600000
static GStaticMutex auth_mutex = G_STATIC_MUTEX_INIT;
@@ -295,10 +319,12 @@ ecbm_remove (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, GEr
g_propagate_error (perror, EDC_ERROR (RepositoryOffline));
return;
}
- if (!priv->is_public_folder) {
+ if (!priv->is_public_folder && !priv->foreign_username) {
GError *mapi_error = NULL;
+ mapi_object_t *obj_store = NULL;
- if (!e_mapi_connection_remove_folder (priv->conn, priv->fid, 0, cancellable, &mapi_error)) {
+ if (!e_mapi_connection_peek_store (priv->conn, priv->foreign_username ? FALSE : priv->is_public_folder, priv->foreign_username, &obj_store, cancellable, &mapi_error) ||
+ !e_mapi_connection_remove_folder (priv->conn, obj_store, priv->fid, cancellable, &mapi_error)) {
mapi_error_to_edc_error (perror, mapi_error, OtherError, _("Failed to remove public folder"));
if (mapi_error)
g_error_free (mapi_error);
@@ -712,12 +738,7 @@ update_local_cache (ECalBackendMAPI *cbmapi, GCancellable *cancellable)
conn = g_object_ref (priv->conn);
- if (priv->is_public_folder) {
- success = e_mapi_connection_open_public_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
- } else {
- success = e_mapi_connection_open_personal_folder (conn, priv->fid, &obj_folder, cancellable, &mapi_error);
- }
-
+ success = ecbm_open_folder (cbmapi, conn, &obj_folder, cancellable, &mapi_error);
if (!success) {
notify_error (cbmapi, mapi_error, _("Failed to open folder: %s"));
goto cleanup;
@@ -1155,11 +1176,7 @@ ecbm_connect_user (ECalBackend *backend, GCancellable *cancellable, const gchar
mapi_object_t obj_folder;
gboolean status;
- if (priv->is_public_folder)
- status = e_mapi_connection_open_public_folder (priv->conn, priv->fid, &obj_folder, NULL, NULL);
- else
- status = e_mapi_connection_open_personal_folder (priv->conn, priv->fid, &obj_folder, NULL, NULL);
-
+ status = ecbm_open_folder (cbmapi, priv->conn, &obj_folder, NULL, NULL);
if (status) {
e_mapi_connection_enable_notifications (priv->conn, &obj_folder,
fnevObjectCreated | fnevObjectModified | fnevObjectDeleted | fnevObjectMoved | fnevObjectCopied,
@@ -1199,7 +1216,6 @@ ecbm_open (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, gbool
ESource *esource;
const gchar *fid = NULL;
const gchar *cache_dir, *krb_sso = NULL;
- uint32_t olFolder = 0;
if (e_cal_backend_is_opened (E_CAL_BACKEND (backend))) {
e_cal_backend_notify_opened (backend, NULL);
@@ -1221,19 +1237,6 @@ ecbm_open (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, gbool
cbmapi->priv->read_only = FALSE;
- switch (e_cal_backend_get_kind (E_CAL_BACKEND (cbmapi))) {
- default:
- case ICAL_VEVENT_COMPONENT:
- olFolder = olFolderCalendar;
- break;
- case ICAL_VTODO_COMPONENT:
- olFolder = olFolderTasks;
- break;
- case ICAL_VJOURNAL_COMPONENT:
- olFolder = olFolderNotes;
- break;
- }
-
if (priv->store) {
g_object_unref (priv->store);
priv->store = NULL;
@@ -1281,8 +1284,13 @@ ecbm_open (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, gbool
priv->owner_email = g_strdup (e_source_get_property (esource, "acl-owner-email"));
e_mapi_util_mapi_id_from_string (fid, &priv->fid);
- priv->olFolder = olFolder;
priv->is_public_folder = g_strcmp0 (e_source_get_property (esource, "public"), "yes") == 0;
+ priv->foreign_username = e_source_get_duped_property (esource, "foreign-username");
+
+ if (priv->foreign_username && !*priv->foreign_username) {
+ g_free (priv->foreign_username);
+ priv->foreign_username = NULL;
+ }
krb_sso = e_source_get_property (esource, "kerberos");
g_mutex_unlock (priv->mutex);
@@ -1434,7 +1442,7 @@ get_server_data (ECalBackendMAPI *cbmapi,
icalcomp = e_cal_component_get_icalcomponent (comp);
get_comp_mid (icalcomp, &mid);
- if (!e_mapi_connection_open_personal_folder (priv->conn, priv->fid, &obj_folder, cancellable, NULL))
+ if (!ecbm_open_folder (cbmapi, priv->conn, &obj_folder, cancellable, NULL))
return;
if (!e_mapi_connection_transfer_object (priv->conn, &obj_folder, mid, ecbm_capture_req_props, cbdata, cancellable, &error)) {
@@ -1561,12 +1569,7 @@ ecbm_create_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
cbdata.globalid = NULL;
cbdata.cleanglobalid = NULL;
- if (priv->is_public_folder) {
- status = e_mapi_connection_open_public_folder (priv->conn, priv->fid, &obj_folder, cancellable, &mapi_error);
- } else {
- status = e_mapi_connection_open_personal_folder (priv->conn, priv->fid, &obj_folder, cancellable, &mapi_error);
- }
-
+ status = ecbm_open_folder (cbmapi, priv->conn, &obj_folder, cancellable, &mapi_error);
if (status) {
e_mapi_connection_create_object (priv->conn, &obj_folder, E_MAPI_CREATE_FLAG_NONE,
e_mapi_cal_utils_comp_to_object, &cbdata,
@@ -1767,12 +1770,7 @@ ecbm_modify_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
cbdata.meeting_type = has_attendees ? MEETING_OBJECT_RCVD : NOT_A_MEETING;
}
- if (priv->is_public_folder) {
- status = e_mapi_connection_open_public_folder (priv->conn, priv->fid, &obj_folder, cancellable, &mapi_error);
- } else {
- status = e_mapi_connection_open_personal_folder (priv->conn, priv->fid, &obj_folder, cancellable, &mapi_error);
- }
-
+ status = ecbm_open_folder (cbmapi, priv->conn, &obj_folder, cancellable, &mapi_error);
if (status) {
status = e_mapi_connection_modify_object (priv->conn, &obj_folder, mid,
e_mapi_cal_utils_comp_to_object, &cbdata,
@@ -1861,29 +1859,31 @@ ecbm_remove_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellab
ecbm_modify_object (backend, cal, cancellable, new_calobj, CALOBJ_MOD_ALL, old_ecalcomp, new_ecalcomp, &err);
g_free (new_calobj);
} else {
+ mapi_object_t obj_folder;
GSList *list=NULL, *l, *comp_list = e_cal_backend_store_get_components_by_uid (priv->store, uid);
GError *ri_error = NULL;
+ mapi_id_t *pmid = g_new (mapi_id_t, 1);
- /*if (e_cal_component_has_attendees (E_CAL_COMPONENT (comp_list->data))) {
- } else {*/
- mapi_id_t *pmid = g_new (mapi_id_t, 1);
- *pmid = mid;
- list = g_slist_prepend (list, pmid);
- /* } */
-
- if (e_mapi_connection_remove_items (priv->conn, priv->olFolder, priv->fid, 0, list, cancellable, &ri_error)) {
- for (l = comp_list; l; l = l->next) {
- ECalComponent *comp = E_CAL_COMPONENT (l->data);
- ECalComponentId *id = e_cal_component_get_id (comp);
-
- e_cal_backend_store_remove_component (priv->store, id->uid, id->rid);
- if (!id->rid || !g_str_equal (id->rid, rid))
- e_cal_backend_notify_component_removed (E_CAL_BACKEND (cbmapi), id, comp, NULL);
- e_cal_component_free_id (id);
+ *pmid = mid;
+ list = g_slist_prepend (list, pmid);
- g_object_unref (comp);
+ if (ecbm_open_folder (cbmapi, priv->conn, &obj_folder, cancellable, &ri_error)) {
+ if (e_mapi_connection_remove_items (priv->conn, &obj_folder, list, cancellable, &ri_error)) {
+ for (l = comp_list; l; l = l->next) {
+ ECalComponent *comp = E_CAL_COMPONENT (l->data);
+ ECalComponentId *id = e_cal_component_get_id (comp);
+
+ e_cal_backend_store_remove_component (priv->store, id->uid, id->rid);
+ if (!id->rid || !g_str_equal (id->rid, rid))
+ e_cal_backend_notify_component_removed (E_CAL_BACKEND (cbmapi), id, comp, NULL);
+ e_cal_component_free_id (id);
+
+ g_object_unref (comp);
+ }
}
+ e_mapi_connection_close_folder (priv->conn, &obj_folder, cancellable, &ri_error);
+
*old_ecalcomp = e_cal_component_new_from_icalcomponent (icalparser_parse_string (calobj));
*new_ecalcomp = NULL;
err = NULL; /* Success */
@@ -3338,6 +3338,11 @@ ecbm_finalize (GObject *object)
priv->sendoptions_sync_timeout = 0;
}
+ if (priv->foreign_username) {
+ g_free (priv->foreign_username);
+ priv->foreign_username = NULL;
+ }
+
if (priv->conn) {
g_object_unref (priv->conn);
priv->conn = NULL;
diff --git a/src/camel/camel-mapi-folder.c b/src/camel/camel-mapi-folder.c
index 543db40..0eaa248 100644
--- a/src/camel/camel-mapi-folder.c
+++ b/src/camel/camel-mapi-folder.c
@@ -54,11 +54,34 @@
extern gint camel_application_is_exiting;
struct _CamelMapiFolderPrivate {
-
GStaticMutex search_lock; /* for locking the search object */
+ gchar *foreign_username;
};
+static gboolean
+cmf_open_folder (CamelMapiFolder *mapi_folder,
+ EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ gboolean res;
+
+ g_return_val_if_fail (mapi_folder != NULL, FALSE);
+ g_return_val_if_fail (conn != NULL, FALSE);
+ g_return_val_if_fail (obj_folder != NULL, FALSE);
+
+ if ((mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0)
+ res = e_mapi_connection_open_foreign_folder (conn, mapi_folder->priv->foreign_username, mapi_folder->folder_id, obj_folder, cancellable, perror);
+ else if ((mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0)
+ res = e_mapi_connection_open_public_folder (conn, mapi_folder->folder_id, obj_folder, cancellable, perror);
+ else
+ res = e_mapi_connection_open_personal_folder (conn, mapi_folder->folder_id, obj_folder, cancellable, perror);
+
+ return res;
+}
+
/*for syncing flags back to server*/
typedef struct {
guint32 changed;
@@ -691,11 +714,6 @@ camel_mapi_folder_fetch_summary (CamelFolder *folder, GCancellable *cancellable,
camel_service_lock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
- if ((CAMEL_MAPI_FOLDER (folder)->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0)
- status = e_mapi_connection_open_public_folder (conn, mapi_folder->folder_id, &obj_folder, cancellable, mapi_error);
- else
- status = e_mapi_connection_open_personal_folder (conn, mapi_folder->folder_id, &obj_folder, cancellable, mapi_error);
-
si = camel_mapi_store_summary_get_folder_id (mapi_store->summary, mapi_folder->folder_id);
msi = (CamelMapiStoreInfo *) si;
@@ -709,6 +727,8 @@ camel_mapi_folder_fetch_summary (CamelFolder *folder, GCancellable *cancellable,
return FALSE;
}
+ status = cmf_open_folder (mapi_folder, conn, &obj_folder, cancellable, mapi_error);
+
if (status) {
status = e_mapi_connection_get_folder_properties (conn, &obj_folder, NULL, NULL, e_mapi_utils_get_folder_basic_properties_cb, &fbp, cancellable, mapi_error);
if (status) {
@@ -1114,7 +1134,7 @@ mapi_folder_append_message_sync (CamelFolder *folder,
/* Convert MIME to Item */
conn = camel_mapi_store_get_connection (mapi_store);
- if (e_mapi_connection_open_personal_folder (conn, fid, &obj_folder, cancellable, &mapi_error)) {
+ if (cmf_open_folder (CAMEL_MAPI_FOLDER (folder), conn, &obj_folder, cancellable, &mapi_error)) {
struct CamelMapiCreateData cmc;
cmc.message = message;
@@ -1161,6 +1181,7 @@ mapi_folder_expunge_sync (CamelFolder *folder,
gboolean delete = FALSE, status = FALSE;
GSList *deleted_items, *deleted_head;
GSList *deleted_items_uid, *deleted_items_uid_head;
+ EMapiConnection *conn;
deleted_items = deleted_head = NULL;
deleted_items_uid = deleted_items_uid_head = NULL;
@@ -1169,8 +1190,10 @@ mapi_folder_expunge_sync (CamelFolder *folder,
mapi_folder = CAMEL_MAPI_FOLDER (folder);
mapi_store = CAMEL_MAPI_STORE (parent_store);
+ conn = camel_mapi_store_get_connection (mapi_store);
if ((mapi_folder->camel_folder_flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_TRASH) {
+ mapi_object_t obj_folder;
GError *mapi_error = NULL;
GPtrArray *folders;
gint ii;
@@ -1195,7 +1218,11 @@ mapi_folder_expunge_sync (CamelFolder *folder,
g_ptr_array_free (folders, TRUE);
camel_service_lock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
- status = e_mapi_connection_empty_folder (camel_mapi_store_get_connection (mapi_store), mapi_folder->folder_id, 0, cancellable, &mapi_error);
+ status = cmf_open_folder (mapi_folder, conn, &obj_folder, cancellable, &mapi_error);
+ if (status) {
+ status = e_mapi_connection_empty_folder (conn, &obj_folder, cancellable, &mapi_error);
+ e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
+ }
camel_service_unlock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
if (status) {
@@ -1248,9 +1275,15 @@ mapi_folder_expunge_sync (CamelFolder *folder,
deleted_items_uid_head = deleted_items_uid;
if (deleted_items) {
+ mapi_object_t obj_folder;
+
camel_service_lock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
- status = e_mapi_connection_remove_items (camel_mapi_store_get_connection (mapi_store), 0, mapi_folder->folder_id, 0, deleted_items, cancellable, NULL);
+ status = cmf_open_folder (mapi_folder, conn, &obj_folder, cancellable, NULL);
+ if (status) {
+ status = e_mapi_connection_remove_items (conn, &obj_folder, deleted_items, cancellable, NULL);
+ e_mapi_connection_close_folder (conn, &obj_folder, cancellable, NULL);
+ }
camel_service_unlock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
@@ -1406,11 +1439,7 @@ mapi_folder_get_message_sync (CamelFolder *folder,
conn = camel_mapi_store_get_connection (mapi_store);
- if (mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC)
- success = e_mapi_connection_open_public_folder (conn, mapi_folder->folder_id, &obj_folder, cancellable, &mapi_error);
- else
- success = e_mapi_connection_open_personal_folder (conn, mapi_folder->folder_id, &obj_folder, cancellable, &mapi_error);
-
+ success = cmf_open_folder (mapi_folder, conn, &obj_folder, cancellable, &mapi_error);
if (success) {
success = e_mapi_connection_transfer_object (conn, &obj_folder, id_message, transfer_mail_object_cb, &msg, cancellable, &mapi_error);
@@ -1463,15 +1492,16 @@ mapi_folder_synchronize_sync (CamelFolder *folder,
CamelFolderChangeInfo *changes = NULL;
CamelServiceConnectionStatus status;
CamelService *service;
+ EMapiConnection *conn;
GPtrArray *known_uids;
GSList *read_items = NULL, *unread_items = NULL, *to_free = NULL, *junk_items = NULL, *deleted_items = NULL, *l;
flags_diff_t diff, unset_flags;
const gchar *folder_id;
const gchar *full_name;
- mapi_id_t fid, deleted_items_fid;
+ mapi_id_t fid;
gint i;
- guint32 options =0;
- gboolean is_junk_folder;
+ gboolean is_junk_folder, has_obj_folder = FALSE;
+ mapi_object_t obj_folder;
full_name = camel_folder_get_full_name (folder);
parent_store = camel_folder_get_parent_store (folder);
@@ -1487,9 +1517,6 @@ mapi_folder_synchronize_sync (CamelFolder *folder,
return TRUE;
}
- if (((CamelMapiFolder *)folder)->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC)
- options |= MAPI_OPTIONS_USE_PFSTORE;
-
folder_id = camel_mapi_store_folder_id_lookup (mapi_store, full_name);
e_mapi_util_mapi_id_from_string (folder_id, &fid);
@@ -1572,28 +1599,36 @@ mapi_folder_synchronize_sync (CamelFolder *folder,
Evo doesnt not take care of it, as I find that scenario to be impractical.
*/
- if (read_items) {
+ conn = camel_mapi_store_get_connection (mapi_store);
+ has_obj_folder = cmf_open_folder (mapi_folder, conn, &obj_folder, cancellable, NULL);
+
+ if (read_items && has_obj_folder) {
camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
- e_mapi_connection_set_flags (camel_mapi_store_get_connection (mapi_store), 0, fid, options, read_items, 0, cancellable, NULL);
+ e_mapi_connection_set_flags (conn, &obj_folder, read_items, 0, cancellable, NULL);
camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
}
- if (unread_items) {
+ if (unread_items && has_obj_folder) {
camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
- e_mapi_connection_set_flags (camel_mapi_store_get_connection (mapi_store), 0, fid, options, unread_items, CLEAR_READ_FLAG, cancellable, NULL);
+ e_mapi_connection_set_flags (conn, &obj_folder, unread_items, CLEAR_READ_FLAG, cancellable, NULL);
camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
}
/* Remove messages from server*/
- if (deleted_items) {
+ if (deleted_items && has_obj_folder) {
camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
if ((mapi_folder->camel_folder_flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_TRASH) {
- e_mapi_connection_remove_items (camel_mapi_store_get_connection (mapi_store), 0, fid, options, deleted_items, cancellable, NULL);
+ e_mapi_connection_remove_items (conn, &obj_folder, deleted_items, cancellable, NULL);
} else {
GError *err = NULL;
+ mapi_id_t deleted_items_fid;
+ mapi_object_t deleted_obj_folder;
e_mapi_util_mapi_id_from_string (camel_mapi_store_system_folder_fid (mapi_store, olFolderDeletedItems), &deleted_items_fid);
- e_mapi_connection_move_items (camel_mapi_store_get_connection (mapi_store), fid, options, deleted_items_fid, 0, deleted_items, cancellable, &err);
+ if (e_mapi_connection_open_personal_folder (conn, deleted_items_fid, &deleted_obj_folder, cancellable, &err)) {
+ e_mapi_connection_copymove_items (conn, &obj_folder, &deleted_obj_folder, FALSE, deleted_items, cancellable, &err);
+ e_mapi_connection_close_folder (conn, &deleted_obj_folder, cancellable, &err);
+ }
if (err) {
g_warning ("%s: Failed to move deleted items: %s", G_STRFUNC, err->message);
@@ -1604,14 +1639,20 @@ mapi_folder_synchronize_sync (CamelFolder *folder,
camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
}
- if (junk_items) {
+ if (junk_items && has_obj_folder) {
mapi_id_t junk_fid = 0;
+ mapi_object_t junk_obj_folder;
GError *err = NULL;
- camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
- e_mapi_util_mapi_id_from_string (camel_mapi_store_system_folder_fid (mapi_store, olFolderJunk), &junk_fid);
- e_mapi_connection_move_items (camel_mapi_store_get_connection (mapi_store), fid, options, junk_fid, 0, junk_items, cancellable, &err);
- camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
+ if (has_obj_folder) {
+ camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
+ e_mapi_util_mapi_id_from_string (camel_mapi_store_system_folder_fid (mapi_store, olFolderJunk), &junk_fid);
+ if (e_mapi_connection_open_personal_folder (conn, junk_fid, &junk_obj_folder, cancellable, &err)) {
+ e_mapi_connection_copymove_items (conn, &obj_folder, &junk_obj_folder, FALSE, junk_items, cancellable, &err);
+ e_mapi_connection_close_folder (conn, &junk_obj_folder, cancellable, &err);
+ }
+ camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
+ }
/* in junk_items are only emails which are not deleted */
deleted_items = g_slist_concat (deleted_items, g_slist_copy (junk_items));
@@ -1622,6 +1663,9 @@ mapi_folder_synchronize_sync (CamelFolder *folder,
}
}
+ if (has_obj_folder)
+ e_mapi_connection_close_folder (conn, &obj_folder, cancellable, NULL);
+
/*Remove messages from local cache*/
for (l = deleted_items; l; l = l->next) {
gchar *deleted_msg_uid = e_mapi_util_mapi_id_to_string (*((mapi_id_t *) l->data));
@@ -1667,8 +1711,6 @@ mapi_folder_transfer_messages_to_sync (CamelFolder *source,
GCancellable *cancellable,
GError **error)
{
- guint32 src_fid_options, dest_fid_options;
-
CamelOfflineStore *offline;
CamelMapiStore *mapi_store;
CamelFolderChangeInfo *changes = NULL;
@@ -1678,6 +1720,10 @@ mapi_folder_transfer_messages_to_sync (CamelFolder *source,
gint i = 0;
GSList *src_msg_ids = NULL;
gboolean success = TRUE;
+ GError *err = NULL;
+ mapi_object_t src_obj_folder, des_obj_folder;
+ gboolean copymoved = FALSE;
+ EMapiConnection *conn;
if (CAMEL_IS_MAPI_FOLDER (source)) {
/* make sure changed flags are written into the server */
@@ -1709,10 +1755,7 @@ mapi_folder_transfer_messages_to_sync (CamelFolder *source,
return FALSE;
src_mapi_folder = CAMEL_MAPI_FOLDER (source);
- src_fid_options = (src_mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0 ? MAPI_OPTIONS_USE_PFSTORE : 0;
-
des_mapi_folder = CAMEL_MAPI_FOLDER (destination);
- dest_fid_options = (des_mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0 ? MAPI_OPTIONS_USE_PFSTORE : 0;
for (i=0; i < uids->len; i++) {
mapi_id_t *mid = g_new0 (mapi_id_t, 1); /* FIXME : */
@@ -1722,40 +1765,38 @@ mapi_folder_transfer_messages_to_sync (CamelFolder *source,
src_msg_ids = g_slist_prepend (src_msg_ids, mid);
}
- if (delete_originals) {
- GError *err = NULL;
+ conn = camel_mapi_store_get_connection (mapi_store);
- if (!e_mapi_connection_move_items (camel_mapi_store_get_connection (mapi_store), src_mapi_folder->folder_id, src_fid_options, des_mapi_folder->folder_id, dest_fid_options, src_msg_ids, cancellable, &err)) {
- if (!e_mapi_utils_propagate_cancelled_error (err, error))
- g_set_error (
- error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
- "%s", err ? err->message : _("Unknown error"));
- g_clear_error (&err);
- success = FALSE;
- } else {
- changes = camel_folder_change_info_new ();
+ if (cmf_open_folder (src_mapi_folder, conn, &src_obj_folder, cancellable, &err)) {
+ if (cmf_open_folder (des_mapi_folder, conn, &des_obj_folder, cancellable, &err)) {
+ copymoved = e_mapi_connection_copymove_items (conn, &src_obj_folder, &des_obj_folder, !delete_originals, src_msg_ids, cancellable, &err);
+ e_mapi_connection_close_folder (conn, &des_obj_folder, cancellable, &err);
+ }
- for (i=0; i < uids->len; i++) {
- camel_folder_summary_remove_uid (source->summary, uids->pdata[i]);
- camel_folder_change_info_remove_uid (changes, uids->pdata[i]);
- }
- camel_folder_changed (source, changes);
- camel_folder_change_info_free (changes);
+ e_mapi_connection_close_folder (conn, &src_obj_folder, cancellable, &err);
+ }
- }
+ if (!copymoved) {
+ if (!e_mapi_utils_propagate_cancelled_error (err, error))
+ g_set_error (
+ error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
+ "%s", err ? err->message : _("Unknown error"));
+ g_clear_error (&err);
+ success = FALSE;
} else {
- GError *err = NULL;
+ changes = camel_folder_change_info_new ();
- if (!e_mapi_connection_copy_items (camel_mapi_store_get_connection (mapi_store), src_mapi_folder->folder_id, src_fid_options, des_mapi_folder->folder_id, dest_fid_options, src_msg_ids, cancellable, &err)) {
- if (!e_mapi_utils_propagate_cancelled_error (err, error))
- g_set_error (
- error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
- "%s", err ? err->message : _("Unknown error"));
- g_clear_error (&err);
- success = FALSE;
+ for (i=0; i < uids->len; i++) {
+ camel_folder_summary_remove_uid (source->summary, uids->pdata[i]);
+ camel_folder_change_info_remove_uid (changes, uids->pdata[i]);
}
+ camel_folder_changed (source, changes);
+ camel_folder_change_info_free (changes);
+
}
+ g_clear_error (&err);
+
g_slist_foreach (src_msg_ids, (GFunc) g_free, NULL);
g_slist_free (src_msg_ids);
@@ -1906,6 +1947,11 @@ camel_mapi_folder_new (CamelStore *store, const gchar *folder_name, const gchar
mapi_folder->mapi_folder_flags = msi->mapi_folder_flags;
mapi_folder->camel_folder_flags = msi->camel_folder_flags;
mapi_folder->folder_id = msi->folder_id;
+ if ((mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0) {
+ mapi_folder->priv->foreign_username = g_strdup (msi->foreign_username);
+ } else {
+ mapi_folder->priv->foreign_username = NULL;
+ }
if ((si->flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_TRASH)
folder->folder_flags |= CAMEL_FOLDER_IS_TRASH;
@@ -1920,5 +1966,11 @@ camel_mapi_folder_new (CamelStore *store, const gchar *folder_name, const gchar
((CamelMapiStore *) store)->summary,
folder_name, folder->summary);
+ /* sanity checking */
+ if ((mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0)
+ g_return_val_if_fail (mapi_folder->priv->foreign_username != NULL, folder);
+ if ((mapi_folder->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0)
+ g_return_val_if_fail (mapi_folder->priv->foreign_username == NULL, folder);
+
return folder;
}
diff --git a/src/camel/camel-mapi-store-summary.c b/src/camel/camel-mapi-store-summary.c
index 5a1bbfd..a21f2af 100644
--- a/src/camel/camel-mapi-store-summary.c
+++ b/src/camel/camel-mapi-store-summary.c
@@ -137,15 +137,15 @@ store_info_load (CamelStoreSummary *s, FILE *in)
|| camel_file_util_decode_string (in, &parent_id_str) == -1
|| camel_file_util_decode_uint32 (in, &msi->camel_folder_flags) == -1
|| camel_file_util_decode_uint32 (in, &msi->mapi_folder_flags) == -1
- || camel_file_util_decode_string (in, &msi->foreign_user_name) == -1
+ || camel_file_util_decode_string (in, &msi->foreign_username) == -1
|| !e_mapi_util_mapi_id_from_string (folder_id_str, &msi->folder_id)
|| !e_mapi_util_mapi_id_from_string (parent_id_str, &msi->parent_id)) {
camel_store_summary_info_free (s, si);
si = NULL;
} else {
- if (msi->foreign_user_name && !*msi->foreign_user_name) {
- g_free (msi->foreign_user_name);
- msi->foreign_user_name = NULL;
+ if (msi->foreign_username && !*msi->foreign_username) {
+ g_free (msi->foreign_username);
+ msi->foreign_username = NULL;
}
}
@@ -174,7 +174,7 @@ store_info_save (CamelStoreSummary *s, FILE *out, CamelStoreInfo *si)
|| camel_file_util_encode_string (out, parent_id_str) == -1
|| camel_file_util_encode_uint32 (out, msi->camel_folder_flags) == -1
|| camel_file_util_encode_uint32 (out, msi->mapi_folder_flags) == -1
- || camel_file_util_encode_string (out, msi->foreign_user_name ? msi->foreign_user_name : "") == -1)
+ || camel_file_util_encode_string (out, msi->foreign_username ? msi->foreign_username : "") == -1)
res = -1;
else
res = 0;
@@ -190,7 +190,7 @@ store_info_free (CamelStoreSummary *s, CamelStoreInfo *si)
{
CamelMapiStoreInfo *msi = (CamelMapiStoreInfo *) si;
- g_free (msi->foreign_user_name);
+ g_free (msi->foreign_username);
CAMEL_STORE_SUMMARY_CLASS (camel_mapi_store_summary_parent_class)->store_info_free (s, si);
}
@@ -200,8 +200,8 @@ store_info_string (CamelStoreSummary *s, const CamelStoreInfo *si, gint type)
{
CamelMapiStoreInfo *msi = (CamelMapiStoreInfo *) si;
- if (type == CAMEL_MAPI_STORE_INFO_FOREIGN_USER_NAME)
- return msi->foreign_user_name;
+ if (type == CAMEL_MAPI_STORE_INFO_FOREIGN_USERNAME)
+ return msi->foreign_username;
return CAMEL_STORE_SUMMARY_CLASS (camel_mapi_store_summary_parent_class)->store_info_string (s, si, type);
}
@@ -211,9 +211,9 @@ store_info_set_string (CamelStoreSummary *s, CamelStoreInfo *si, gint type, cons
{
CamelMapiStoreInfo *msi = (CamelMapiStoreInfo *) si;
- if (type == CAMEL_MAPI_STORE_INFO_FOREIGN_USER_NAME) {
- g_free (msi->foreign_user_name);
- msi->foreign_user_name = g_strdup (str);
+ if (type == CAMEL_MAPI_STORE_INFO_FOREIGN_USERNAME) {
+ g_free (msi->foreign_username);
+ msi->foreign_username = g_strdup (str);
camel_store_summary_touch (s);
} else
@@ -233,7 +233,7 @@ camel_mapi_store_summary_add_from_full (CamelStoreSummary *s,
mapi_id_t parent_id,
guint32 camel_folder_flags,
guint32 mapi_folder_flags,
- const gchar *foreign_user_name)
+ const gchar *foreign_username)
{
CamelStoreInfo *si;
@@ -247,11 +247,13 @@ camel_mapi_store_summary_add_from_full (CamelStoreSummary *s,
if (si) {
CamelMapiStoreInfo *msi = (CamelMapiStoreInfo *) si;
+ si->flags = camel_folder_flags;
+
msi->folder_id = folder_id;
msi->parent_id = parent_id;
msi->camel_folder_flags = camel_folder_flags;
msi->mapi_folder_flags = mapi_folder_flags;
- msi->foreign_user_name = g_strdup ((foreign_user_name && *foreign_user_name) ? foreign_user_name : "");
+ msi->foreign_username = g_strdup ((foreign_username && *foreign_username) ? foreign_username : NULL);
msi->latest_last_modify = 0;
msi->last_obj_total = -1;
diff --git a/src/camel/camel-mapi-store-summary.h b/src/camel/camel-mapi-store-summary.h
index 3ae1390..8097d78 100644
--- a/src/camel/camel-mapi-store-summary.h
+++ b/src/camel/camel-mapi-store-summary.h
@@ -61,7 +61,7 @@ enum CamelMapiStoreFolderFlags {
};
enum {
- CAMEL_MAPI_STORE_INFO_FOREIGN_USER_NAME = CAMEL_STORE_INFO_LAST,
+ CAMEL_MAPI_STORE_INFO_FOREIGN_USERNAME = CAMEL_STORE_INFO_LAST,
CAMEL_MAPI_STORE_INFO_LAST
};
@@ -71,7 +71,7 @@ struct _CamelMapiStoreInfo {
mapi_id_t parent_id;
guint32 camel_folder_flags; /* CamelFolderInfo::flags */
guint32 mapi_folder_flags; /* bit-or of CamelMapiStoreFolderFlags */
- gchar *foreign_user_name; /* only if CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN is set */
+ gchar *foreign_username; /* only if CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN is set */
/* these are not saved */
time_t latest_last_modify;
@@ -95,7 +95,7 @@ CamelStoreInfo * camel_mapi_store_summary_add_from_full (CamelStoreSummary *s,
mapi_id_t parent_id,
guint32 camel_folder_flags, /* CamelFolderInfo::flags */
guint32 mapi_folder_flags, /* bit-or of CamelMapiStoreFolderFlags */
- const gchar *foreign_user_name); /* only if CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN is set */
+ const gchar *foreign_username); /* only if CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN is set */
CamelStoreInfo * camel_mapi_store_summary_get_folder_id (CamelStoreSummary *s,
mapi_id_t folder_id);
diff --git a/src/camel/camel-mapi-store.c b/src/camel/camel-mapi-store.c
index 97216d0..87ff10a 100644
--- a/src/camel/camel-mapi-store.c
+++ b/src/camel/camel-mapi-store.c
@@ -44,8 +44,9 @@
#include "camel-mapi-settings.h"
#include "camel-mapi-store-summary.h"
#include "camel-mapi-folder-summary.h"
-#include "account-setup-eplugin/e-mapi-account-listener.h"
+
#include <e-mapi-utils.h>
+#include <e-mapi-folder.h>
#define d(x)
@@ -107,6 +108,78 @@ static CamelFolderInfo *
GError **error);
static gboolean
+cms_open_folder (CamelMapiStore *mapi_store,
+ EMapiConnection *conn,
+ mapi_id_t fid,
+ mapi_object_t *obj_folder,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ CamelStoreInfo *si;
+ CamelMapiStoreInfo *msi;
+ gboolean res;
+
+ g_return_val_if_fail (mapi_store != NULL, FALSE);
+ g_return_val_if_fail (mapi_store->summary != NULL, FALSE);
+ g_return_val_if_fail (conn != NULL, FALSE);
+ g_return_val_if_fail (fid != 0, FALSE);
+ g_return_val_if_fail (obj_folder != NULL, FALSE);
+
+ si = camel_mapi_store_summary_get_folder_id (mapi_store->summary, fid);
+ if (!si) {
+ g_propagate_error (perror, g_error_new_literal (CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Cannot find folder in a local cache")));
+ return FALSE;
+ }
+
+ msi = (CamelMapiStoreInfo *) si;
+
+ if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0)
+ res = e_mapi_connection_open_foreign_folder (conn, msi->foreign_username, fid, obj_folder, cancellable, perror);
+ else if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0)
+ res = e_mapi_connection_open_public_folder (conn, fid, obj_folder, cancellable, perror);
+ else
+ res = e_mapi_connection_open_personal_folder (conn, fid, obj_folder, cancellable, perror);
+
+ return res;
+}
+
+static gboolean
+cms_peek_folder_store (CamelMapiStore *mapi_store,
+ EMapiConnection *conn,
+ mapi_id_t fid,
+ mapi_object_t **obj_store,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ CamelStoreInfo *si;
+ CamelMapiStoreInfo *msi;
+ gboolean res;
+
+ g_return_val_if_fail (mapi_store != NULL, FALSE);
+ g_return_val_if_fail (mapi_store->summary != NULL, FALSE);
+ g_return_val_if_fail (conn != NULL, FALSE);
+ g_return_val_if_fail (fid != 0, FALSE);
+ g_return_val_if_fail (obj_store != NULL, FALSE);
+
+ si = camel_mapi_store_summary_get_folder_id (mapi_store->summary, fid);
+ if (!si) {
+ g_propagate_error (perror, g_error_new_literal (CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Cannot find folder in a local cache")));
+ return FALSE;
+ }
+
+ msi = (CamelMapiStoreInfo *) si;
+
+ if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0)
+ res = e_mapi_connection_peek_store (conn, FALSE, msi->foreign_username, obj_store, cancellable, perror);
+ else if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0)
+ res = e_mapi_connection_peek_store (conn, TRUE, NULL, obj_store, cancellable, perror);
+ else
+ res = e_mapi_connection_peek_store (conn, FALSE, NULL, obj_store, cancellable, perror);
+
+ return res;
+}
+
+static gboolean
check_for_connection (CamelService *service, GError **error)
{
CamelMapiStore *store = CAMEL_MAPI_STORE (service);
@@ -269,16 +342,16 @@ mapi_convert_to_folder_info (CamelMapiStore *store,
fi->flags |= CAMEL_FOLDER_SYSTEM;
} else {
switch (e_mapi_folder_get_type (folder)) {
- case MAPI_FOLDER_TYPE_CONTACT:
+ case E_MAPI_FOLDER_TYPE_CONTACT:
fi->flags |= CAMEL_FOLDER_TYPE_CONTACTS;
break;
- case MAPI_FOLDER_TYPE_APPOINTMENT:
+ case E_MAPI_FOLDER_TYPE_APPOINTMENT:
fi->flags |= CAMEL_FOLDER_TYPE_EVENTS;
break;
- case MAPI_FOLDER_TYPE_MEMO:
+ case E_MAPI_FOLDER_TYPE_MEMO:
fi->flags |= CAMEL_FOLDER_TYPE_MEMOS;
break;
- case MAPI_FOLDER_TYPE_TASK:
+ case E_MAPI_FOLDER_TYPE_TASK:
fi->flags |= CAMEL_FOLDER_TYPE_TASKS;
break;
default:
@@ -286,7 +359,7 @@ mapi_convert_to_folder_info (CamelMapiStore *store,
}
}
- if (folder->category == MAPI_PERSONAL_FOLDER)
+ if (folder->category == E_MAPI_FOLDER_CATEGORY_PERSONAL)
fi->flags |= CAMEL_STORE_INFO_FOLDER_SUBSCRIBED; /*Set this default for mailbox.*/
if (folder->child_count <=0)
@@ -416,9 +489,11 @@ mapi_folders_sync (CamelMapiStore *store, guint32 flags, GCancellable *cancellab
continue;
/* those whose left in old_cache_folders are removed at the end,
- which is not good for public folders, thus preserve them from
- an automatic removal */
- if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) == 0 || (msi->info.flags & CAMEL_FOLDER_SUBSCRIBED) == 0)
+ which is not good for public and foreign folders, thus preserve
+ them from an automatic removal */
+ if (((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) == 0 &&
+ (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) == 0) ||
+ (msi->info.flags & CAMEL_FOLDER_SUBSCRIBED) == 0)
g_hash_table_insert (old_cache_folders, g_strdup (camel_store_info_path (store->summary, msi)), GINT_TO_POINTER (1));
camel_store_summary_info_free (store->summary, (CamelStoreInfo *) msi);
@@ -490,7 +565,7 @@ mapi_folders_sync (CamelMapiStore *store, guint32 flags, GCancellable *cancellab
if (folder->default_type == olPublicFoldersAllPublicFolders)
continue;
- if (folder->container_class == MAPI_FOLDER_TYPE_MAIL) {
+ if (folder->container_class == E_MAPI_FOLDER_TYPE_MAIL) {
info = mapi_convert_to_folder_info (store, folder, NULL);
msi = (CamelMapiStoreInfo *) camel_store_summary_path (store->summary, info->full_name);
@@ -500,7 +575,7 @@ mapi_folders_sync (CamelMapiStore *store, guint32 flags, GCancellable *cancellab
e_mapi_folder_get_fid (folder),
e_mapi_folder_get_parent_id (folder),
info->flags,
- folder->category == MAPI_PERSONAL_FOLDER ? CAMEL_MAPI_STORE_FOLDER_FLAG_PERSONAL:
+ folder->category == E_MAPI_FOLDER_CATEGORY_PERSONAL ? CAMEL_MAPI_STORE_FOLDER_FLAG_PERSONAL:
CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC,
NULL);
if (msi == NULL)
@@ -521,7 +596,7 @@ mapi_folders_sync (CamelMapiStore *store, guint32 flags, GCancellable *cancellab
camel_store_summary_info_free (store->summary, (CamelStoreInfo *) msi);
camel_folder_info_free (info);
- } else if (folder->category == MAPI_FAVOURITE_FOLDER) {
+ } else if (folder->category == E_MAPI_FOLDER_CATEGORY_PUBLIC) {
info = mapi_convert_to_folder_info (store, folder, NULL);
msi = (CamelMapiStoreInfo *) camel_store_summary_path (store->summary, info->full_name);
@@ -603,7 +678,7 @@ match_path (const gchar *path, const gchar *name)
}
static void
-fix_folder_names (CamelFolderInfo *fi)
+unescape_folder_names (CamelFolderInfo *fi)
{
while (fi) {
if (fi->display_name && strchr (fi->display_name, '\\')) {
@@ -615,7 +690,7 @@ fix_folder_names (CamelFolderInfo *fi)
}
if (fi->child)
- fix_folder_names (fi->child);
+ unescape_folder_names (fi->child);
fi = fi->next;
}
@@ -631,6 +706,7 @@ mapi_get_folder_info_offline (CamelStore *store, const gchar *top,
gchar *path;
gint i, count;
gboolean subscribed, subscription_list = FALSE;
+ gboolean has_public_folders = FALSE, has_foreign_folders = FALSE;
subscription_list = (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIPTION_LIST);
subscribed = (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED);
@@ -665,7 +741,8 @@ mapi_get_folder_info_offline (CamelStore *store, const gchar *top,
if (!subscription_list &&
!(msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_MAIL) &&
(si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) != 0 &&
- (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0) {
+ ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0 ||
+ (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0)) {
camel_store_summary_info_free (mapi_store->summary, si);
continue;
}
@@ -676,8 +753,11 @@ mapi_get_folder_info_offline (CamelStore *store, const gchar *top,
gchar *parent_name = NULL;
const gchar *folder_name = NULL;
+ has_public_folders = has_public_folders || (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0;
+ has_foreign_folders = has_foreign_folders || (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0;
+
if (subscribed && g_str_has_prefix (store_info_path, DISPLAY_NAME_ALL_PUBLIC_FOLDERS)) {
- parent_name = DISPLAY_NAME_FAVOURITES;
+ parent_name = DISPLAY_NAME_FAVORITES;
folder_name = strrchr (store_info_path, '/');
if (folder_name != NULL)
@@ -694,19 +774,28 @@ mapi_get_folder_info_offline (CamelStore *store, const gchar *top,
camel_store_summary_info_free (mapi_store->summary, si);
}
- if (!(subscription_list) && top[0] == '\0') {
- fi = mapi_build_folder_info (mapi_store, NULL, DISPLAY_NAME_FAVOURITES);
- fi->flags |= CAMEL_FOLDER_NOSELECT;
- fi->flags |= CAMEL_FOLDER_SYSTEM;
+ if (!subscription_list && !*top) {
+ if (has_public_folders) {
+ fi = mapi_build_folder_info (mapi_store, NULL, DISPLAY_NAME_FAVORITES);
+ fi->flags |= CAMEL_FOLDER_NOSELECT | CAMEL_FOLDER_SYSTEM;
- g_ptr_array_add (folders, fi);
+ g_ptr_array_add (folders, fi);
+ }
+
+ if (has_foreign_folders) {
+ fi = mapi_build_folder_info (mapi_store, NULL, DISPLAY_NAME_FOREIGN_FOLDERS);
+ fi->flags |= CAMEL_FOLDER_NOSELECT | CAMEL_FOLDER_SYSTEM;
+
+ g_ptr_array_add (folders, fi);
+ }
}
g_free (path);
+ /* this adds also fake folders, if missing */
fi = camel_folder_info_build (folders, top, '/', TRUE);
g_ptr_array_free (folders, TRUE);
- fix_folder_names (fi);
+ unescape_folder_names (fi);
return fi;
}
@@ -838,12 +927,20 @@ stop_pending_updates (CamelMapiStore *mapi_store)
static void
mapi_store_dispose (GObject *object)
{
+ CamelMapiStore *mapi_store;
CamelMapiStorePrivate *priv;
- priv = CAMEL_MAPI_STORE (object)->priv;
+ mapi_store = CAMEL_MAPI_STORE (object);
+ priv = mapi_store->priv;
stop_pending_updates (CAMEL_MAPI_STORE (object));
+ if (mapi_store->summary) {
+ camel_store_summary_save (mapi_store->summary);
+ g_object_unref (mapi_store->summary);
+ mapi_store->summary = NULL;
+ }
+
if (priv->conn != NULL) {
g_signal_handlers_disconnect_by_func (priv->conn, camel_mapi_store_server_notification_cb, object);
@@ -1057,6 +1154,8 @@ mapi_store_create_folder_sync (CamelStore *store,
CamelFolderInfo *root = NULL;
gchar *parent_id;
mapi_id_t parent_fid, new_folder_id;
+ mapi_object_t obj_folder;
+ EMapiConnection *conn;
GError *mapi_error = NULL;
if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store))) {
@@ -1074,11 +1173,6 @@ mapi_store_create_folder_sync (CamelStore *store,
return NULL;
}
- if (parent_name && (strlen(parent_name) > 0) )
- parent_id = g_strdup (g_hash_table_lookup (priv->name_hash, parent_name));
- else
- parent_id = g_strdup ("");
-
if (!mapi_connect_sync (CAMEL_SERVICE(store), cancellable, NULL)) {
g_set_error (
error, CAMEL_SERVICE_ERROR,
@@ -1089,19 +1183,54 @@ mapi_store_create_folder_sync (CamelStore *store,
camel_service_lock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+ if (parent_name && *parent_name)
+ parent_id = g_strdup (g_hash_table_lookup (priv->name_hash, parent_name));
+ else
+ parent_id = NULL;
+
+ if (!parent_id) {
+ camel_service_unlock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+ g_set_error (
+ error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_UNAVAILABLE,
+ _("Cannot find folder '%s'"), parent_name ? parent_name : "");
+ return NULL;
+ }
e_mapi_util_mapi_id_from_string (parent_id, &parent_fid);
- new_folder_id = e_mapi_connection_create_folder (priv->conn, olFolderInbox, parent_fid, 0, folder_name, cancellable, &mapi_error);
+ new_folder_id = 0;
+
+ conn = priv->conn;
+ if (!cms_open_folder (mapi_store, conn, parent_fid, &obj_folder, cancellable, error)) {
+ camel_service_unlock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+ return NULL;
+ }
+
+ if (!e_mapi_connection_create_folder (conn, &obj_folder, folder_name, IPF_NOTE, &new_folder_id, cancellable, &mapi_error))
+ new_folder_id = 0;
+ e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
+
if (new_folder_id != 0) {
gchar *folder_id_str;
+ CamelMapiStoreInfo *parent_msi;
+ gboolean is_public, is_foreign;
+
+ parent_msi = (CamelMapiStoreInfo *) camel_mapi_store_summary_get_folder_id (mapi_store->summary, parent_fid);
+ is_public = parent_msi && (parent_msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0;
+ is_foreign = parent_msi && (parent_msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0;
root = mapi_build_folder_info (mapi_store, parent_name, folder_name);
camel_mapi_store_summary_add_from_full (mapi_store->summary,
root->full_name,
new_folder_id,
parent_fid,
- root->flags,
- CAMEL_MAPI_STORE_FOLDER_FLAG_PERSONAL,
- NULL);
+ root->flags | ((is_public || is_foreign) ? CAMEL_FOLDER_SUBSCRIBED | CAMEL_STORE_INFO_FOLDER_SUBSCRIBED : 0),
+ (is_public ? CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC :
+ is_foreign ? CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN :
+ CAMEL_MAPI_STORE_FOLDER_FLAG_PERSONAL) | CAMEL_MAPI_STORE_FOLDER_FLAG_MAIL,
+ is_foreign ? parent_msi->foreign_username : NULL);
+
+ if (parent_msi)
+ camel_store_summary_info_free (mapi_store->summary, (CamelStoreInfo *) parent_msi);
camel_store_summary_save (mapi_store->summary);
@@ -1138,7 +1267,8 @@ mapi_store_delete_folder_sync (CamelStore *store,
{
CamelMapiStore *mapi_store = CAMEL_MAPI_STORE (store);
CamelMapiStorePrivate *priv = mapi_store->priv;
-
+ CamelMapiStoreInfo *msi;
+ mapi_object_t *obj_store = NULL;
const gchar *folder_id;
mapi_id_t folder_fid;
gboolean status = FALSE;
@@ -1160,13 +1290,22 @@ mapi_store_delete_folder_sync (CamelStore *store,
folder_id = g_hash_table_lookup (priv->name_hash, folder_name);
e_mapi_util_mapi_id_from_string (folder_id, &folder_fid);
- status = e_mapi_connection_remove_folder (priv->conn, folder_fid, 0, cancellable, &local_error);
+
+ msi = (CamelMapiStoreInfo *) camel_mapi_store_summary_get_folder_id (mapi_store->summary, folder_fid);
+ if (!msi ||
+ (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0 ||
+ (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0) {
+ /* do nore remove foreign or public folders, just unsubscribe from them,
+ even when there are folder delete permissons on the folder
+ */
+ status = TRUE;
+ } else if (cms_peek_folder_store (mapi_store, priv->conn, folder_fid, &obj_store, cancellable, &local_error))
+ status = e_mapi_connection_remove_folder (priv->conn, obj_store, folder_fid, cancellable, &local_error);
+ else
+ status = FALSE;
if (status) {
- /* Fixme ?? */
-/* if (mapi_store->current_folder) */
-/* g_object_unref (mapi_store->current_folder); */
- success = mapi_forget_folder(mapi_store,folder_name,error);
+ success = mapi_forget_folder (mapi_store,folder_name,error);
/* remove from name_cache at the end, because the folder_id is from there */
/*g_hash_table_remove (priv->parent_hash, folder_id);*/
@@ -1462,7 +1601,7 @@ mapi_store_subscribe_folder_sync (CamelSubscribable *subscribable,
if (g_str_has_prefix (folder_name, DISPLAY_NAME_ALL_PUBLIC_FOLDERS) ) {
const gchar *f_name = NULL;
- parent_name = DISPLAY_NAME_FAVOURITES;
+ parent_name = DISPLAY_NAME_FAVORITES;
f_name = strrchr (folder_name,'/');
if (!f_name) {
@@ -1500,11 +1639,34 @@ mapi_store_subscribe_folder_sync (CamelSubscribable *subscribable,
camel_subscribable_folder_subscribed (subscribable, fi);
camel_folder_info_free (fi);
} else {
- CamelService *service;
+ CamelSettings *settings;
+ CamelMapiSettings *mapi_settings;
+ CamelNetworkSettings *network_settings;
+
guint folder_type = mapi_folders_hash_table_type_lookup (mapi_store, folder_name);
- service = CAMEL_SERVICE (mapi_store);
- e_mapi_add_esource (service, use_folder_name, fid, folder_type);
+ settings = camel_service_get_settings (CAMEL_SERVICE (mapi_store));
+ mapi_settings = CAMEL_MAPI_SETTINGS (settings);
+ network_settings = CAMEL_NETWORK_SETTINGS (settings);
+
+ if (!e_mapi_folder_add_as_esource (folder_type,
+ camel_mapi_settings_get_profile (mapi_settings),
+ camel_mapi_settings_get_domain (mapi_settings),
+ camel_mapi_settings_get_realm (mapi_settings),
+ camel_network_settings_get_host (network_settings),
+ camel_network_settings_get_user (network_settings),
+ camel_mapi_settings_get_kerberos (mapi_settings),
+ camel_offline_settings_get_stay_synchronized (CAMEL_OFFLINE_SETTINGS (mapi_settings)),
+ E_MAPI_FOLDER_CATEGORY_PUBLIC,
+ NULL,
+ use_folder_name,
+ fid,
+ error)) {
+ camel_store_summary_info_free (mapi_store->summary, si);
+
+ return FALSE;
+ }
+
}
camel_store_summary_info_free (mapi_store->summary, si);
@@ -1517,7 +1679,6 @@ mapi_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
GCancellable *cancellable,
GError **error)
{
- CamelService *service;
CamelFolderInfo *fi;
CamelStoreInfo *si;
gchar *parent_name = NULL;
@@ -1526,7 +1687,6 @@ mapi_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
CamelMapiStore *mapi_store = CAMEL_MAPI_STORE (subscribable);
- service = CAMEL_SERVICE (mapi_store);
fid = camel_mapi_store_folder_id_lookup(mapi_store, folder_name);
si = camel_store_summary_path (mapi_store->summary, folder_name);
if (si) {
@@ -1541,7 +1701,7 @@ mapi_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
}
if (g_str_has_prefix (folder_name, DISPLAY_NAME_ALL_PUBLIC_FOLDERS) ) {
- parent_name = DISPLAY_NAME_FAVOURITES;
+ parent_name = DISPLAY_NAME_FAVORITES;
f_name = strrchr(folder_name,'/');
if (f_name != NULL)
@@ -1554,8 +1714,22 @@ mapi_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
camel_subscribable_folder_unsubscribed (subscribable, fi);
camel_folder_info_free (fi);
} else {
+ CamelSettings *settings;
+ CamelNetworkSettings *network_settings;
guint folder_type = mapi_folders_hash_table_type_lookup (mapi_store, use_folder_name);
- e_mapi_remove_esource (service, folder_name, fid, folder_type);
+
+ settings = camel_service_get_settings (CAMEL_SERVICE (mapi_store));
+ network_settings = CAMEL_NETWORK_SETTINGS (settings);
+
+ if (!e_mapi_folder_remove_as_esource (folder_type,
+ camel_network_settings_get_host (network_settings),
+ camel_network_settings_get_user (network_settings),
+ fid,
+ error)) {
+ camel_store_summary_info_free (mapi_store->summary, si);
+
+ return FALSE;
+ }
}
camel_store_summary_info_free (mapi_store->summary, si);
@@ -2397,3 +2571,119 @@ camel_mapi_store_get_connection (CamelMapiStore *mapi_store)
return mapi_store->priv->conn;
}
+/* ppath contains proposed path, this only makes sure that it's a unique path */
+void
+camel_mapi_store_ensure_unique_path (CamelMapiStore *mapi_store,
+ gchar **ppath)
+{
+ gboolean done;
+ guint counter = 0;
+ gchar *base_path = NULL;
+
+ g_return_if_fail (mapi_store != NULL);
+ g_return_if_fail (mapi_store->summary != NULL);
+ g_return_if_fail (ppath != NULL);
+ g_return_if_fail (*ppath != NULL);
+
+ done = FALSE;
+ while (!done) {
+ CamelStoreInfo *si;
+
+ done = TRUE;
+
+ si = camel_store_summary_path (mapi_store->summary, *ppath);
+ if (si) {
+ camel_store_summary_info_free (mapi_store->summary, si);
+
+ done = FALSE;
+ counter++;
+ if (!counter) {
+ g_debug ("%s: Counter overflow", G_STRFUNC);
+ break;
+ }
+
+ if (!base_path)
+ base_path = *ppath;
+ else
+ g_free (*ppath);
+
+ *ppath = g_strdup_printf ("%s_%u", base_path, counter);
+ }
+ }
+
+ g_free (base_path);
+}
+
+void
+camel_mapi_store_announce_subscribed_folder (CamelMapiStore *mapi_store,
+ const gchar *path)
+{
+ CamelStoreInfo *si;
+ CamelFolderInfo *fi;
+ CamelMapiStoreInfo *msi;
+ gchar **parts, *folder_id_str, *parent_id_str;
+ GString *partial_path;
+ gint ii;
+
+ g_return_if_fail (mapi_store != NULL);
+ g_return_if_fail (mapi_store->summary != NULL);
+ g_return_if_fail (path != NULL);
+
+ si = camel_store_summary_path (mapi_store->summary, path);
+ g_return_if_fail (si != NULL);
+
+ camel_store_summary_info_free (mapi_store->summary, si);
+
+ parts = g_strsplit (path, "/", -1);
+ g_return_if_fail (parts != NULL);
+
+ partial_path = g_string_new ("");
+
+ /* first announce about virtual parents */
+ for (ii = 0; parts[ii]; ii++) {
+ if (ii > 0)
+ g_string_append (partial_path, "/");
+ g_string_append (partial_path, parts[ii]);
+
+ si = camel_store_summary_path (mapi_store->summary, partial_path->str);
+ if (si) {
+ /* it's a known path, no need to announce it */
+ camel_store_summary_info_free (mapi_store->summary, si);
+ } else {
+ /* it's an unknown path, not a real path, thus announce it too,
+ to ensure the folder path for this new path will exist
+ */
+ fi = mapi_build_folder_info (mapi_store, NULL, partial_path->str);
+ fi->flags |= CAMEL_FOLDER_NOSELECT | CAMEL_FOLDER_SYSTEM;
+
+ camel_store_folder_created (CAMEL_STORE (mapi_store), fi);
+ camel_subscribable_folder_subscribed (CAMEL_SUBSCRIBABLE (mapi_store), fi);
+
+ camel_folder_info_free (fi);
+ }
+ }
+
+ g_string_free (partial_path, TRUE);
+ g_strfreev (parts);
+
+ /* finally announce about the path itself */
+ si = camel_store_summary_path (mapi_store->summary, path);
+ g_return_if_fail (si != NULL);
+
+ msi = (CamelMapiStoreInfo *) si;
+ folder_id_str = e_mapi_util_mapi_id_to_string (msi->folder_id);
+ parent_id_str = e_mapi_util_mapi_id_to_string (msi->parent_id);
+
+ fi = mapi_build_folder_info (mapi_store, NULL, camel_store_info_path (mapi_store->summary, si));
+ fi->flags = msi->camel_folder_flags;
+
+ mapi_update_folder_hash_tables (mapi_store, fi->full_name, folder_id_str, parent_id_str);
+
+ camel_store_folder_created (CAMEL_STORE (mapi_store), fi);
+ camel_subscribable_folder_subscribed (CAMEL_SUBSCRIBABLE (mapi_store), fi);
+
+ camel_folder_info_free (fi);
+ camel_store_summary_info_free (mapi_store->summary, si);
+ g_free (folder_id_str);
+ g_free (parent_id_str);
+}
diff --git a/src/camel/camel-mapi-store.h b/src/camel/camel-mapi-store.h
index 809ec48..41844be 100644
--- a/src/camel/camel-mapi-store.h
+++ b/src/camel/camel-mapi-store.h
@@ -50,8 +50,9 @@
(G_TYPE_INSTANCE_GET_CLASS \
((obj), CAMEL_TYPE_MAPI_STORE, CamelMapiStoreClass))
-#define DISPLAY_NAME_FAVOURITES _("Favorites")
-#define DISPLAY_NAME_ALL_PUBLIC_FOLDERS _("All Public Folders")
+#define DISPLAY_NAME_FAVORITES _("Favorites")
+#define DISPLAY_NAME_FOREIGN_FOLDERS _("Foreign folders")
+#define DISPLAY_NAME_ALL_PUBLIC_FOLDERS _("All Public Folders")
G_BEGIN_DECLS
@@ -80,6 +81,9 @@ const gchar * mapi_folders_hash_table_name_lookup (CamelMapiStore *store, const
EMapiConnection * camel_mapi_store_get_connection (CamelMapiStore *mapi_store);
+void camel_mapi_store_ensure_unique_path (CamelMapiStore *mapi_store, gchar **ppath);
+void camel_mapi_store_announce_subscribed_folder (CamelMapiStore *mapi_store, const gchar *path);
+
G_END_DECLS
#endif /* CAMEL_OPENCHANGE_STORE_H */
diff --git a/src/libexchangemapi/e-mapi-cal-utils.c b/src/libexchangemapi/e-mapi-cal-utils.c
index 690ea2c..7df766b 100644
--- a/src/libexchangemapi/e-mapi-cal-utils.c
+++ b/src/libexchangemapi/e-mapi-cal-utils.c
@@ -540,7 +540,7 @@ e_mapi_cal_utils_get_free_busy_data (EMapiConnection *conn, const GSList *users,
struct SRow aRow;
enum MAPISTATUS ms;
uint32_t i;
- mapi_object_t obj_store;
+ mapi_object_t obj_folder;
const GSList *l;
const uint32_t *publish_start;
@@ -562,12 +562,15 @@ e_mapi_cal_utils_get_free_busy_data (EMapiConnection *conn, const GSList *users,
*freebusy = NULL;
- if (!e_mapi_connection_get_public_folder (conn, &obj_store, cancellable, mapi_error)) {
+ mapi_object_init (&obj_folder);
+
+ if (!e_mapi_connection_get_public_folder (conn, &obj_folder, cancellable, mapi_error)) {
+ mapi_object_release (&obj_folder);
return FALSE;
}
for ( l = users; l != NULL; l = g_slist_next (l)) {
- ms = GetUserFreeBusyData (&obj_store, (const gchar *)l->data, &aRow);
+ ms = GetUserFreeBusyData (&obj_folder, (const gchar *)l->data, &aRow);
if (ms != MAPI_E_SUCCESS) {
gchar *context = g_strconcat ("GetUserFreeBusyData for ", l->data, NULL);
@@ -576,6 +579,8 @@ e_mapi_cal_utils_get_free_busy_data (EMapiConnection *conn, const GSList *users,
g_free (context);
+ mapi_object_release (&obj_folder);
+
return FALSE;
}
@@ -643,6 +648,8 @@ e_mapi_cal_utils_get_free_busy_data (EMapiConnection *conn, const GSList *users,
talloc_free (aRow.lpProps);
}
+ mapi_object_release (&obj_folder);
+
return TRUE;
}
diff --git a/src/libexchangemapi/e-mapi-connection.c b/src/libexchangemapi/e-mapi-connection.c
index f35cf9a..1433506 100644
--- a/src/libexchangemapi/e-mapi-connection.c
+++ b/src/libexchangemapi/e-mapi-connection.c
@@ -128,6 +128,8 @@ make_mapi_error (GError **perror, const gchar *context, enum MAPISTATUS mapi_sta
err (MAPI_E_INVALID_ACCESS_TIME, _("Invalid access time"));
err (MAPI_E_ACCOUNT_DISABLED, _("Account is disabled"));
err (MAPI_E_END_OF_SESSION, _("End of session"));
+ err (MAPI_E_NOT_INITIALIZED, _("MAPI is not initialized or connected"));
+ err (MAPI_E_NO_ACCESS, _("Permission denied"));
#undef err
@@ -173,6 +175,8 @@ struct _EMapiConnectionPrivate {
gboolean has_public_store; /* whether is 'public_store' filled */
mapi_object_t public_store;
+ GHashTable *foreign_stores; /* username (gchar *) => msg_store (mapi_object_t *); opened foreign stores */
+
GSList *folders; /* list of ExchangeMapiFolder pointers */
GStaticRecMutex folders_lock; /* lock for 'folders' variable */
@@ -242,6 +246,17 @@ stop_all_notifications (EMapiConnectionPrivate *priv)
priv->notification_thread = NULL;
}
+static void
+release_foreign_stores_cb (gpointer pusername, gpointer pmsg_store, gpointer user_data)
+{
+ mapi_object_t *msg_store = pmsg_store;
+
+ g_return_if_fail (msg_store != NULL);
+
+ mapi_object_release (msg_store);
+ talloc_free (msg_store);
+}
+
/* should have session_lock locked already, when calling this function */
static void
disconnect (EMapiConnectionPrivate *priv)
@@ -259,6 +274,10 @@ disconnect (EMapiConnectionPrivate *priv)
if (priv->has_public_store)
mapi_object_release (&priv->public_store);
+
+ g_hash_table_foreach (priv->foreign_stores, release_foreign_stores_cb, NULL);
+ g_hash_table_remove_all (priv->foreign_stores);
+
Logoff (&priv->msg_store);
/* it's released by the Logoff() call
mapi_object_release (&priv->msg_store); */
@@ -272,7 +291,8 @@ disconnect (EMapiConnectionPrivate *priv)
/* should have session_lock locked already, when calling this function */
static gboolean
-ensure_public_store (EMapiConnectionPrivate *priv, GError **perror)
+ensure_public_store (EMapiConnectionPrivate *priv,
+ GError **perror)
{
e_return_val_mapi_error_if_fail (priv != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
@@ -295,6 +315,51 @@ ensure_public_store (EMapiConnectionPrivate *priv, GError **perror)
return priv->has_public_store;
}
+/* should have session_lock locked already, when calling this function */
+static gboolean
+ensure_foreign_store (EMapiConnectionPrivate *priv,
+ const gchar *username,
+ mapi_object_t **pmsg_store,
+ GError **perror)
+{
+ enum MAPISTATUS ms;
+ mapi_object_t *msg_store;
+
+ e_return_val_mapi_error_if_fail (priv != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (username != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (pmsg_store != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+ *pmsg_store = NULL;
+
+ if (!priv->session)
+ return FALSE;
+
+ msg_store = g_hash_table_lookup (priv->foreign_stores, username);
+ if (msg_store) {
+ *pmsg_store = msg_store;
+ return TRUE;
+ }
+
+ msg_store = talloc_zero (priv->session, mapi_object_t);
+ mapi_object_init (msg_store);
+
+ ms = OpenUserMailbox (priv->session, username, msg_store);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "OpenUserMailbox", ms);
+
+ mapi_object_release (msg_store);
+ talloc_free (msg_store);
+
+ return FALSE;
+ }
+
+ g_hash_table_insert (priv->foreign_stores, g_strdup (username), msg_store);
+
+ *pmsg_store = msg_store;
+
+ return TRUE;
+}
+
static void
e_mapi_connection_dispose (GObject *object)
{
@@ -329,6 +394,10 @@ e_mapi_connection_finalize (GObject *object)
g_hash_table_destroy (priv->named_ids);
priv->named_ids = NULL;
+ if (priv->foreign_stores)
+ g_hash_table_destroy (priv->foreign_stores);
+ priv->foreign_stores = NULL;
+
UNLOCK ();
g_static_rec_mutex_free (&priv->session_lock);
g_static_rec_mutex_free (&priv->folders_lock);
@@ -382,6 +451,7 @@ e_mapi_connection_init (EMapiConnection *conn)
conn->priv->has_public_store = FALSE;
conn->priv->folders = NULL;
+ conn->priv->foreign_stores = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
conn->priv->named_ids = g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free, (GDestroyNotify) g_hash_table_destroy);
conn->priv->known_notifications = g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free, NULL);
@@ -653,8 +723,99 @@ may_skip_property (uint32_t proptag)
}
gboolean
+e_mapi_connection_test_foreign_folder (EMapiConnection *conn,
+ const gchar *username,
+ const gchar *folder_name,
+ mapi_id_t *fid, /* out */
+ GCancellable *cancellable,
+ GError **perror)
+{
+ enum MAPISTATUS ms;
+ mapi_id_t foreign_fid = 0;
+ mapi_object_t obj_store, obj_folder;
+
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (username != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (folder_name != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (fid != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+ LOCK ();
+
+ mapi_object_init (&obj_store);
+ mapi_object_init (&obj_folder);
+
+ ms = OpenUserMailbox (priv->session, username, &obj_store);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "OpenUserMailbox", ms);
+ goto cleanup;
+ }
+
+ if (folder_name[0] == '0' && folder_name[1] == 'x' && e_mapi_util_mapi_id_from_string (folder_name + 2, &foreign_fid)) {
+ ms = OpenFolder (&obj_store, foreign_fid, &obj_folder);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "OpenFolder", ms);
+ goto cleanup;
+ }
+ } else {
+ uint32_t def_folder_id = 0;
+
+ /* intentionally not localized strings */
+ if (g_ascii_strcasecmp (folder_name, "Inbox") == 0) {
+ def_folder_id = olFolderInbox;
+ } else if (g_ascii_strcasecmp (folder_name, "DeletedItems") == 0) {
+ def_folder_id = olFolderDeletedItems;
+ } else if (g_ascii_strcasecmp (folder_name, "Outbox") == 0) {
+ def_folder_id = olFolderOutbox;
+ } else if (g_ascii_strcasecmp (folder_name, "SentMail") == 0) {
+ def_folder_id = olFolderSentMail;
+ } else if (g_ascii_strcasecmp (folder_name, "Calendar") == 0) {
+ def_folder_id = olFolderCalendar;
+ } else if (g_ascii_strcasecmp (folder_name, "Contacts") == 0) {
+ def_folder_id = olFolderContacts;
+ } else if (g_ascii_strcasecmp (folder_name, "Notes") == 0) {
+ def_folder_id = olFolderNotes;
+ } else if (g_ascii_strcasecmp (folder_name, "Tasks") == 0) {
+ def_folder_id = olFolderTasks;
+ } else if (g_ascii_strcasecmp (folder_name, "Drafts") == 0) {
+ def_folder_id = olFolderDrafts;
+ } else if (g_ascii_strcasecmp (folder_name, "Junk") == 0) {
+ def_folder_id = olFolderJunk;
+ } else if (!e_mapi_util_mapi_id_from_string (folder_name, &foreign_fid)) {
+ ms = MAPI_E_CALL_FAILED;
+ g_propagate_error (perror, g_error_new (E_MAPI_ERROR, ms, _("Folder name '%s' is not a known default folder name, nor folder ID."), folder_name));
+ goto cleanup;
+ }
+
+ if (def_folder_id != 0) {
+ ms = GetDefaultFolder (&obj_store, &foreign_fid, def_folder_id);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "GetDefaultFolder", ms);
+ goto cleanup;
+ }
+ }
+
+ ms = OpenFolder (&obj_store, foreign_fid, &obj_folder);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "OpenFolder", ms);
+ goto cleanup;
+ }
+ }
+
+ *fid = mapi_object_get_id (&obj_folder);
+
+ cleanup:
+ mapi_object_release (&obj_folder);
+ mapi_object_release (&obj_store);
+
+ UNLOCK ();
+
+ return ms == MAPI_E_SUCCESS;
+}
+
+gboolean
e_mapi_connection_get_public_folder (EMapiConnection *conn,
- mapi_object_t *obj_store,
+ mapi_object_t *obj_folder,
GCancellable *cancellable,
GError **perror)
{
@@ -665,15 +826,13 @@ e_mapi_connection_get_public_folder (EMapiConnection *conn,
LOCK ();
- mapi_object_init (&priv->public_store);
-
- ms = OpenPublicFolder (priv->session, &priv->public_store);
+ mapi_object_init (obj_folder);
+ ms = OpenPublicFolder (priv->session, obj_folder);
if (ms != MAPI_E_SUCCESS) {
make_mapi_error (perror, "OpenPublicFolder", ms);
}
- *obj_store = priv->public_store;
UNLOCK ();
return ms == MAPI_E_SUCCESS;
@@ -712,6 +871,59 @@ open_folder (EMapiConnection *conn, uint32_t olFolder, mapi_id_t *fid, guint32 f
}
gboolean
+e_mapi_connection_peek_store (EMapiConnection *conn,
+ gboolean public_store,
+ const gchar *foreign_username,
+ mapi_object_t **obj_store, /* out */
+ GCancellable *cancellable,
+ GError **perror)
+{
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ if (public_store)
+ e_return_val_mapi_error_if_fail (foreign_username == NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ if (foreign_username)
+ e_return_val_mapi_error_if_fail (!public_store, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_store != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+ LOCK ();
+
+ if (public_store) {
+ if (!ensure_public_store (priv, perror)) {
+ UNLOCK ();
+ return FALSE;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ UNLOCK ();
+ return FALSE;
+ }
+
+ *obj_store = &priv->public_store;
+
+ UNLOCK ();
+
+ return TRUE;
+ }
+
+ if (foreign_username) {
+ if (!ensure_foreign_store (priv, foreign_username, obj_store, perror)) {
+ UNLOCK ();
+ return FALSE;
+ }
+
+ UNLOCK ();
+ return TRUE;
+ }
+
+ *obj_store = &priv->msg_store;
+
+ UNLOCK ();
+
+ return TRUE;
+}
+
+gboolean
e_mapi_connection_open_default_folder (EMapiConnection *conn,
uint32_t olFolderIdentifier,
mapi_object_t *obj_folder,
@@ -809,6 +1021,51 @@ e_mapi_connection_open_public_folder (EMapiConnection *conn,
}
gboolean
+e_mapi_connection_open_foreign_folder (EMapiConnection *conn,
+ const gchar *username,
+ mapi_id_t fid,
+ mapi_object_t *obj_folder, /* out */
+ GCancellable *cancellable,
+ GError **perror)
+{
+ enum MAPISTATUS ms;
+ mapi_object_t *msg_store = NULL;
+
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (username != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+ LOCK ();
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ UNLOCK ();
+ return FALSE;
+ }
+
+ if (!ensure_foreign_store (conn->priv, username, &msg_store, perror)) {
+ ms = MAPI_E_CALL_FAILED;
+ if (perror && !*perror)
+ g_propagate_error (perror, g_error_new (E_MAPI_ERROR, ms, _("Failed to open store for user '%s'"), username));
+ } else {
+ ms = MAPI_E_SUCCESS;
+ }
+
+ mapi_object_init (obj_folder);
+
+ if (ms == MAPI_E_SUCCESS) {
+ ms = OpenFolder (msg_store, fid, obj_folder);
+ if (ms == MAPI_E_NOT_FOUND)
+ g_propagate_error (perror, g_error_new (E_MAPI_ERROR, ms, _("Folder of user '%s' not found"), username));
+ else if (ms != MAPI_E_SUCCESS)
+ make_mapi_error (perror, "OpenFolder", ms);
+ }
+
+ UNLOCK ();
+
+ return ms == MAPI_E_SUCCESS;
+}
+
+gboolean
e_mapi_connection_close_folder (EMapiConnection *conn,
mapi_object_t *obj_folder,
GCancellable *cancellable,
@@ -826,13 +1083,87 @@ e_mapi_connection_close_folder (EMapiConnection *conn,
return TRUE;
}
+static void
+maybe_add_named_id_tag (uint32_t proptag,
+ EResolveNamedIDsData **named_ids_list,
+ guint *named_ids_len)
+{
+ g_return_if_fail (named_ids_list != NULL);
+ g_return_if_fail (named_ids_len != NULL);
+
+ if (((proptag >> 16) & 0xFFFF) >= 0x8000) {
+ if (!*named_ids_list) {
+ *named_ids_list = g_new0 (EResolveNamedIDsData, 1);
+ *named_ids_len = 0;
+ } else {
+ *named_ids_list = g_renew (EResolveNamedIDsData, *named_ids_list, *named_ids_len + 1);
+ }
+
+ (*named_ids_list)[*named_ids_len].pidlid_propid = proptag;
+ (*named_ids_list)[*named_ids_len].propid = MAPI_E_RESERVED;
+ (*named_ids_len) += 1;
+ }
+}
+
+/* free returned pointer with g_hash_table_destroy */
+static GHashTable *
+prepare_maybe_replace_hash (const EResolveNamedIDsData *named_ids_list,
+ guint named_ids_len,
+ gboolean to_server_ids)
+{
+ GHashTable *res;
+ gint ii;
+
+ if (!named_ids_list || !named_ids_len)
+ return NULL;
+
+ res = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ for (ii = 0; ii < named_ids_len; ii++) {
+ uint32_t search_tag = named_ids_list[ii].pidlid_propid;
+ uint32_t replace_with = named_ids_list[ii].propid;
+
+ if (!to_server_ids) {
+ uint32_t ui32;
+
+ ui32 = search_tag;
+ search_tag = replace_with;
+ replace_with = ui32;
+ }
+
+ g_hash_table_insert (res, GUINT_TO_POINTER (search_tag), GUINT_TO_POINTER (replace_with));
+
+ search_tag = (search_tag & ~0xFFFF) | PT_ERROR;
+ replace_with = (replace_with & ~0xFFFF) | PT_ERROR;
+
+ g_hash_table_insert (res, GUINT_TO_POINTER (search_tag), GUINT_TO_POINTER (replace_with));
+ }
+
+ return res;
+}
+
+static void
+maybe_replace_named_id_tag (uint32_t *pproptag,
+ GHashTable *replace_hash)
+{
+ gpointer key, value;
+
+ g_return_if_fail (pproptag != NULL);
+
+ if (!replace_hash)
+ return;
+
+ if (g_hash_table_lookup_extended (replace_hash, GUINT_TO_POINTER (*pproptag), &key, &value))
+ *pproptag = GPOINTER_TO_UINT (value);
+}
+
/* deals with named IDs transparently, if not using NULL bpr_cb, thus it's OK to check with PidLid and PidName constants only */
gboolean
e_mapi_connection_get_folder_properties (EMapiConnection *conn,
mapi_object_t *obj_folder,
BuildReadPropsCB brp_cb,
gpointer brp_cb_user_data,
- GetFolderPropertiesCB cb,
+ GetPropertiesCB cb,
gpointer cb_user_data,
GCancellable *cancellable,
GError **perror)
@@ -869,6 +1200,7 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
uint32_t prop_count = 0, k, ll;
EResolveNamedIDsData *named_ids_list = NULL;
guint named_ids_len = 0;
+ GHashTable *replace_hash = NULL;
lpProps = talloc_zero (mem_ctx, struct SPropValue);
@@ -881,12 +1213,8 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
name = "";
g_debug ("%s: Cannot fetch property 0x%08x %s", G_STRFUNC, proptag, name);
- } else if (((proptag >> 16) & 0xFFFF) >= 0x8000) {
- if (!named_ids_list)
- named_ids_list = g_new0 (EResolveNamedIDsData, spropTagArray->cValues - k + 1);
- named_ids_list[named_ids_len].pidlid_propid = proptag;
- named_ids_list[named_ids_len].propid = MAPI_E_RESERVED;
- named_ids_len++;
+ } else {
+ maybe_add_named_id_tag (proptag, &named_ids_list, &named_ids_len);
}
}
@@ -901,16 +1229,17 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
goto cleanup;
}
- for (k = 0, ll = 0; k < named_ids_len; k++) {
- if (named_ids_list[k].propid != MAPI_E_RESERVED) {
- while (ll < spropTagArray->cValues) {
- if (spropTagArray->aulPropTag[k] == named_ids_list[k].pidlid_propid) {
- spropTagArray->aulPropTag[k] = named_ids_list[k].propid;
- break;
- }
- ll++;
- }
+ replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, TRUE);
+ if (replace_hash) {
+ for (k = 0; k < spropTagArray->cValues; k++) {
+ uint32_t proptag = spropTagArray->aulPropTag[k];
+
+ maybe_replace_named_id_tag (&proptag, replace_hash);
+
+ spropTagArray->aulPropTag[k] = proptag;
}
+ g_hash_table_destroy (replace_hash);
+ replace_hash = NULL;
}
}
@@ -926,6 +1255,9 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
goto cleanup;
}
+ if (named_ids_list)
+ replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, FALSE);
+
/* Conversion from SPropValue to mapi_SPropValue. (no padding here) */
properties->cValues = prop_count;
properties->lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, prop_count + 1);
@@ -934,22 +1266,18 @@ e_mapi_connection_get_folder_properties (EMapiConnection *conn,
ll--;
properties->cValues--;
} else {
- if (named_ids_list) {
- guint m;
-
- for (m = 0; m < named_ids_len; m++) {
- if (lpProps[k].ulPropTag == named_ids_list[named_ids_len - m - 1].propid ||
- (((lpProps[k].ulPropTag & 0xFFFF) == PT_ERROR) &&
- (lpProps[k].ulPropTag & ~0xFFFF) == (named_ids_list[named_ids_len - m - 1].propid & ~0xFFFF))) {
- lpProps[k].ulPropTag = (lpProps[k].ulPropTag & 0xFFFF) | (named_ids_list[named_ids_len - m - 1].pidlid_propid & ~0xFFFF);
- break;
- }
- }
- }
+ uint32_t proptag = lpProps[k].ulPropTag;
+
+ maybe_replace_named_id_tag (&proptag, replace_hash);
+ lpProps[k].ulPropTag = proptag;
cast_mapi_SPropValue (mem_ctx, &properties->lpProps[ll], &lpProps[k]);
}
}
+
+ g_free (named_ids_list);
+ if (replace_hash)
+ g_hash_table_destroy (replace_hash);
} else {
ms = GetPropsAll (obj_folder, MAPI_UNICODE, properties);
if (ms != MAPI_E_SUCCESS) {
@@ -1083,28 +1411,6 @@ list_objects_internal_cb (EMapiConnection *conn,
}
static void
-maybe_add_named_id_tag (uint32_t proptag,
- EResolveNamedIDsData **named_ids_list,
- guint *named_ids_len)
-{
- g_return_if_fail (named_ids_list != NULL);
- g_return_if_fail (named_ids_len != NULL);
-
- if (((proptag >> 16) & 0xFFFF) >= 0x8000) {
- if (!*named_ids_list) {
- *named_ids_list = g_new0 (EResolveNamedIDsData, 1);
- *named_ids_len = 0;
- } else {
- *named_ids_list = g_renew (EResolveNamedIDsData, *named_ids_list, *named_ids_len + 1);
- }
-
- (*named_ids_list)[*named_ids_len].pidlid_propid = proptag;
- (*named_ids_list)[*named_ids_len].propid = MAPI_E_RESERVED;
- (*named_ids_len) += 1;
- }
-}
-
-static void
gather_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
EResolveNamedIDsData **named_ids_list,
guint *named_ids_len)
@@ -1155,49 +1461,6 @@ gather_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
}
}
-/* free returned pointer with g_hash_table_destroy */
-static GHashTable *
-prepare_maybe_replace_hash (const EResolveNamedIDsData *named_ids_list,
- guint named_ids_len)
-{
- GHashTable *res;
- gint ii;
-
- if (!named_ids_list || !named_ids_len)
- return NULL;
-
- res = g_hash_table_new (g_direct_hash, g_direct_equal);
-
- for (ii = 0; ii < named_ids_len; ii++) {
- uint32_t search_tag = named_ids_list[ii].pidlid_propid;
- uint32_t replace_with = named_ids_list[ii].propid;
-
- g_hash_table_insert (res, GUINT_TO_POINTER (search_tag), GUINT_TO_POINTER (replace_with));
-
- search_tag = (search_tag & ~0xFFFF) | PT_ERROR;
- replace_with = (replace_with & ~0xFFFF) | PT_ERROR;
-
- g_hash_table_insert (res, GUINT_TO_POINTER (search_tag), GUINT_TO_POINTER (replace_with));
- }
-
- return res;
-}
-
-static void
-maybe_replace_named_id_tag (uint32_t *pproptag,
- GHashTable *replace_hash)
-{
- gpointer key, value;
-
- g_return_if_fail (pproptag != NULL);
-
- if (!replace_hash)
- return;
-
- if (g_hash_table_lookup_extended (replace_hash, GUINT_TO_POINTER (*pproptag), &key, &value))
- *pproptag = GPOINTER_TO_UINT (value);
-}
-
static void
replace_mapi_SRestriction_named_ids (struct mapi_SRestriction *restriction,
GHashTable *replace_hash)
@@ -1279,7 +1542,7 @@ change_mapi_SRestriction_named_ids (EMapiConnection *conn,
res = e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror);
if (res) {
- GHashTable *replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len);
+ GHashTable *replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, TRUE);
if (replace_hash) {
replace_mapi_SRestriction_named_ids (restrictions, replace_hash);
@@ -2534,7 +2797,7 @@ convert_mapi_props_to_props (EMapiConnection *conn,
res = e_mapi_connection_resolve_named_props (conn, mapi_object_get_id (obj_folder), named_ids_list, named_ids_len, cancellable, perror);
if (res)
- replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len);
+ replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, TRUE);
if (replace_hash && *props) {
for (ii = 0; ii < *propslen; ii++) {
@@ -2871,7 +3134,7 @@ add_object_recipients (EMapiConnection *conn,
goto cleanup;
}
- replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len);
+ replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, TRUE);
for (ii = 0; ii < tags->cValues && replace_hash; ii++) {
uint32_t proptag = tags->aulPropTag[ii];
@@ -3699,7 +3962,7 @@ e_mapi_connection_list_gal_objects (EMapiConnection *conn,
res = e_mapi_connection_resolve_named_props (conn, 0, named_ids_list, named_ids_len, cancellable, perror);
if (res) {
- GHashTable *replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len);
+ GHashTable *replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, TRUE);
use_restriction = talloc_zero (mem_ctx, struct Restriction_r);
convert_mapi_SRestriction_to_Restriction_r (restrictions, use_restriction, mem_ctx, replace_hash);
@@ -3903,7 +4166,7 @@ e_mapi_connection_transfer_gal_objects (EMapiConnection *conn,
goto cleanup;
}
- replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len);
+ replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, TRUE);
if (replace_hash) {
for (ii = 0; ii < propTagArray->cValues; ii++) {
@@ -3964,36 +4227,29 @@ e_mapi_connection_transfer_gal_object (EMapiConnection *conn,
return res;
}
-mapi_id_t
+gboolean
e_mapi_connection_create_folder (EMapiConnection *conn,
- uint32_t olFolder,
- mapi_id_t pfid,
- guint32 fid_options,
+ mapi_object_t *obj_parent_folder, /* in */
const gchar *name,
+ const gchar *new_folder_type, /* usually IPF_NOTE and similar */
+ mapi_id_t *new_fid, /* out */
GCancellable *cancellable,
GError **perror)
{
enum MAPISTATUS ms;
mapi_object_t obj_folder;
- mapi_object_t obj_top;
struct SPropValue vals[1];
- const gchar *type;
mapi_id_t fid = 0;
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, 0);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, 0);
-
- e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_parent_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (name != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (new_folder_type != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (new_fid != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
LOCK ();
- mapi_object_init(&obj_top);
- mapi_object_init(&obj_folder);
-
- /* We now open the top/parent folder */
- ms = open_folder (conn, olFolder, &pfid, fid_options, &obj_top, perror);
- if (ms != MAPI_E_SUCCESS) {
- goto cleanup;
- }
+ mapi_object_init (&obj_folder);
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
ms = MAPI_E_USER_CANCEL;
@@ -4001,34 +4257,14 @@ e_mapi_connection_create_folder (EMapiConnection *conn,
}
/* Attempt to create the folder */
- ms = CreateFolder (&obj_top, FOLDER_GENERIC, name, "Created using Evolution/LibMAPI", OPEN_IF_EXISTS | MAPI_UNICODE, &obj_folder);
+ ms = CreateFolder (obj_parent_folder, FOLDER_GENERIC, name, "Created using Evolution/LibMAPI", OPEN_IF_EXISTS | MAPI_UNICODE, &obj_folder);
if (ms != MAPI_E_SUCCESS) {
make_mapi_error (perror, "CreateFolder", ms);
goto cleanup;
}
- switch (olFolder) {
- case olFolderInbox:
- type = IPF_NOTE;
- break;
- case olFolderCalendar:
- type = IPF_APPOINTMENT;
- break;
- case olFolderContacts:
- type = IPF_CONTACT;
- break;
- case olFolderTasks:
- type = IPF_TASK;
- break;
- case olFolderNotes:
- type = IPF_STICKYNOTE;
- break;
- default:
- type = IPF_NOTE;
- }
-
- vals[0].value.lpszA = type;
- vals[0].ulPropTag = PR_CONTAINER_CLASS;
+ vals[0].value.lpszW = new_folder_type;
+ vals[0].ulPropTag = PidTagContainerClass;
ms = SetProps (&obj_folder, MAPI_PROPS_SKIP_NAMEDID_CHECK, vals, 1);
if (ms != MAPI_E_SUCCESS) {
@@ -4037,131 +4273,184 @@ e_mapi_connection_create_folder (EMapiConnection *conn,
}
fid = mapi_object_get_id (&obj_folder);
- e_mapi_debug_print("Folder %s created with id %016" G_GINT64_MODIFIER "X ", name, fid);
+ if (fid == 0) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "mapi_object_get_id", ms);
+ } else {
+ *new_fid = fid;
+ }
- g_static_rec_mutex_lock (&priv->folders_lock);
+ cleanup:
+ mapi_object_release (&obj_folder);
- /* we should also update folder list locally */
- if (fid != 0 && priv->folders != NULL) {
- EMapiFolder *folder = NULL;
- folder = e_mapi_folder_new (name, type, MAPI_PERSONAL_FOLDER, fid, pfid, 0, 0, 0);
- if (folder)
- priv->folders = g_slist_append (priv->folders, folder);
+ UNLOCK ();
+
+ return ms == MAPI_E_SUCCESS;
+}
+
+gboolean
+e_mapi_connection_empty_folder (EMapiConnection *conn,
+ mapi_object_t *obj_folder,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ enum MAPISTATUS ms;
+
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_folder, MAPI_E_INVALID_PARAMETER, FALSE);
+
+ LOCK ();
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
}
- g_static_rec_mutex_unlock (&priv->folders_lock);
+ /* Empty the contents of the folder */
+ ms = EmptyFolder (obj_folder);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "EmptyFolder", ms);
+ goto cleanup;
+ }
+
+ cleanup:
+ UNLOCK ();
+
+ return ms == MAPI_E_SUCCESS;
+}
+
+static gboolean
+add_parent_fid_prop_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ struct SPropTagArray *props,
+ gpointer data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ g_return_val_if_fail (mem_ctx != NULL, FALSE);
+ g_return_val_if_fail (props != NULL, FALSE);
+
+ SPropTagArray_add (mem_ctx, props, PidTagParentFolderId);
+
+ return TRUE;
+}
+
+static gboolean
+read_parent_fid_prop_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ /* const */ struct mapi_SPropValue_array *properties,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ mapi_id_t *pmid = user_data;
+ const mapi_id_t *cmid;
- cleanup:
- mapi_object_release(&obj_folder);
- mapi_object_release(&obj_top);
+ g_return_val_if_fail (properties != NULL, FALSE);
+ g_return_val_if_fail (pmid != NULL, FALSE);
- UNLOCK ();
+ cmid = e_mapi_util_find_array_propval (properties, PidTagParentFolderId);
+ g_return_val_if_fail (cmid != NULL, FALSE);
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+ *pmid = *cmid;
- /* Shouldn't we return (EMapiFolder *) instead of a plain fid ? */
- return fid;
+ return TRUE;
}
-gboolean
-e_mapi_connection_empty_folder (EMapiConnection *conn,
- mapi_id_t fid,
- guint32 fid_options,
- GCancellable *cancellable,
- GError **perror)
+static gboolean
+emc_open_folders (EMapiConnection *conn,
+ mapi_object_t *obj_store, /* in */
+ mapi_id_t child_fid,
+ mapi_object_t *obj_child_folder, /* out */
+ mapi_object_t *obj_parent_folder, /* out */
+ GCancellable *cancellable,
+ GError **perror)
{
enum MAPISTATUS ms;
- mapi_object_t obj_folder;
- gboolean result = FALSE;
+ mapi_id_t parent_fid = 0;
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
+ e_return_val_mapi_error_if_fail (obj_store != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_child_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_parent_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
LOCK ();
- mapi_object_init (&obj_folder);
- /* Attempt to open the folder to be emptied */
- ms = open_folder (conn, 0, &fid, fid_options, &obj_folder, perror);
+ ms = OpenFolder (obj_store, child_fid, obj_child_folder);
if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "OpenFolder-1", ms);
goto cleanup;
}
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
ms = MAPI_E_USER_CANCEL;
+ mapi_object_release (obj_child_folder);
goto cleanup;
}
- /* Empty the contents of the folder */
- ms = EmptyFolder (&obj_folder);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "EmptyFolder", ms);
+ if (!e_mapi_connection_get_folder_properties (conn, obj_child_folder, add_parent_fid_prop_cb, NULL, read_parent_fid_prop_cb, &parent_fid, cancellable, perror) ||
+ parent_fid == 0) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "GetFolderProperties", ms);
+ mapi_object_release (obj_child_folder);
goto cleanup;
}
- e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was emptied ", fid);
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ mapi_object_release (obj_child_folder);
+ goto cleanup;
+ }
- result = TRUE;
+ ms = OpenFolder (obj_store, parent_fid, obj_parent_folder);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "OpenFolder-2", ms);
+ mapi_object_release (obj_child_folder);
+ goto cleanup;
+ }
cleanup:
- mapi_object_release(&obj_folder);
UNLOCK ();
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-
- return result;
+ return ms == MAPI_E_SUCCESS;
}
gboolean
e_mapi_connection_remove_folder (EMapiConnection *conn,
- mapi_id_t fid,
- guint32 fid_options,
+ mapi_object_t *obj_store, /* in, store, to which folder belongs */
+ mapi_id_t fid_to_remove,
GCancellable *cancellable,
GError **perror)
{
enum MAPISTATUS ms;
- mapi_object_t obj_top;
+ mapi_object_t obj_parent;
mapi_object_t obj_folder;
EMapiFolder *folder;
- gboolean result = FALSE;
GSList *l;
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- g_return_val_if_fail (fid != 0, FALSE);
+ e_return_val_mapi_error_if_fail (obj_store != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (fid_to_remove != 0, MAPI_E_INVALID_PARAMETER, FALSE);
e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
folder = NULL;
for (l = e_mapi_connection_peek_folders_list (conn); l; l = l->next) {
folder = l->data;
- if (folder && folder->folder_id == fid)
+ if (folder && folder->folder_id == fid_to_remove)
break;
else
folder = NULL;
}
- e_return_val_mapi_error_if_fail (folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
LOCK ();
- mapi_object_init(&obj_top);
- mapi_object_init(&obj_folder);
-
- /* FIXME: If the folder has sub-folders, open each of them in turn, empty them and delete them.
- * Note that this has to be done recursively, for the sub-folders as well.
- */
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
- /* Attempt to open the folder to be removed */
- ms = open_folder (conn, 0, &fid, fid_options, &obj_folder, perror);
- if (ms != MAPI_E_SUCCESS) {
- goto cleanup;
+ if (!emc_open_folders (conn, obj_store, fid_to_remove, &obj_folder, &obj_parent, cancellable, perror)) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "emc_open_folders", ms);
+
}
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
@@ -4176,45 +4465,32 @@ e_mapi_connection_remove_folder (EMapiConnection *conn,
goto cleanup;
}
- e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was emptied ", fid);
-
- /* Attempt to open the top/parent folder */
- ms = open_folder (conn, 0, &folder->parent_folder_id, fid_options, &obj_top, perror);
- if (ms != MAPI_E_SUCCESS) {
- goto cleanup;
- }
-
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
ms = MAPI_E_USER_CANCEL;
goto cleanup;
}
/* Call DeleteFolder on the folder to be removed */
- ms = DeleteFolder (&obj_top, fid, DEL_FOLDERS, NULL);
+ ms = DeleteFolder (&obj_parent, fid_to_remove, DEL_FOLDERS, NULL);
if (ms != MAPI_E_SUCCESS) {
make_mapi_error (perror, "DeleteFolder", ms);
goto cleanup;
}
- e_mapi_debug_print("Folder with id %016" G_GINT64_MODIFIER "X was deleted ", fid);
-
- result = TRUE;
-
cleanup:
- mapi_object_release(&obj_folder);
- mapi_object_release(&obj_top);
-
- g_static_rec_mutex_lock (&priv->folders_lock);
- priv->folders = g_slist_remove (priv->folders, folder);
- g_static_rec_mutex_unlock (&priv->folders_lock);
+ mapi_object_release (&obj_folder);
+ mapi_object_release (&obj_parent);
- e_mapi_folder_free (folder);
+ if (folder) {
+ g_static_rec_mutex_lock (&priv->folders_lock);
+ priv->folders = g_slist_remove (priv->folders, folder);
+ e_mapi_folder_free (folder);
+ g_static_rec_mutex_unlock (&priv->folders_lock);
+ }
UNLOCK ();
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-
- return result;
+ return ms == MAPI_E_SUCCESS;
}
gboolean
@@ -4755,9 +5031,7 @@ e_mapi_connection_get_default_folder_id (EMapiConnection *conn,
gboolean
e_mapi_connection_set_flags (EMapiConnection *conn,
- uint32_t olFolder,
- mapi_id_t fid,
- guint32 fid_options,
+ mapi_object_t *obj_folder,
GSList *mids,
uint32_t flag,
GCancellable *cancellable,
@@ -4765,7 +5039,6 @@ e_mapi_connection_set_flags (EMapiConnection *conn,
{
enum MAPISTATUS ms;
TALLOC_CTX *mem_ctx;
- mapi_object_t obj_folder;
uint32_t i;
mapi_id_t *id_messages;
GSList *tmp = mids;
@@ -4773,29 +5046,23 @@ e_mapi_connection_set_flags (EMapiConnection *conn,
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
LOCK ();
mem_ctx = talloc_new (priv->session);
- mapi_object_init(&obj_folder);
- id_messages = talloc_array(mem_ctx, mapi_id_t, g_slist_length (mids));
- for (i=0; tmp; tmp=tmp->next, i++)
+ id_messages = talloc_array (mem_ctx, mapi_id_t, g_slist_length (mids));
+ for (i = 0; tmp; tmp = tmp->next, i++)
id_messages[i] = *((mapi_id_t *)tmp->data);
- /* Attempt to open the folder */
- ms = open_folder (conn, olFolder, &fid, fid_options, &obj_folder, perror);
- if (ms != MAPI_E_SUCCESS) {
- goto cleanup;
- }
-
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
ms = MAPI_E_USER_CANCEL;
goto cleanup;
}
- ms = SetReadFlags (&obj_folder, flag, i, id_messages);
+ ms = SetReadFlags (obj_folder, flag, i, id_messages);
if (ms != MAPI_E_SUCCESS) {
make_mapi_error (perror, "SetReadFlags", ms);
goto cleanup;
@@ -4804,8 +5071,7 @@ e_mapi_connection_set_flags (EMapiConnection *conn,
result = TRUE;
cleanup:
- mapi_object_release(&obj_folder);
- talloc_free(mem_ctx);
+ talloc_free (mem_ctx);
UNLOCK ();
@@ -4814,41 +5080,22 @@ e_mapi_connection_set_flags (EMapiConnection *conn,
return result;
}
-static gboolean
-mapi_move_items (EMapiConnection *conn,
- mapi_id_t src_fid,
- guint32 src_fid_options,
- mapi_id_t dest_fid,
- guint32 dest_fid_options,
- GSList *mid_list,
- gboolean do_copy,
- GCancellable *cancellable,
- GError **perror)
+gboolean
+e_mapi_connection_copymove_items (EMapiConnection *conn,
+ mapi_object_t *src_obj_folder,
+ mapi_object_t *des_obj_folder,
+ gboolean do_copy,
+ GSList *mid_list,
+ GCancellable *cancellable,
+ GError **perror)
{
enum MAPISTATUS ms;
- mapi_object_t obj_folder_src;
- mapi_object_t obj_folder_dst;
GSList *l;
- e_return_val_mapi_error_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- mapi_object_init(&obj_folder_src);
- mapi_object_init(&obj_folder_dst);
-
- ms = open_folder (conn, 0, &src_fid, src_fid_options, &obj_folder_src, perror);
- if (ms != MAPI_E_SUCCESS) {
- goto cleanup;
- }
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, MAPI_E_INVALID_PARAMETER);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
- ms = open_folder (conn, 0, &dest_fid, dest_fid_options, &obj_folder_dst, perror);
- if (ms != MAPI_E_SUCCESS) {
- goto cleanup;
- }
+ LOCK ();
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
ms = MAPI_E_USER_CANCEL;
@@ -4866,7 +5113,7 @@ mapi_move_items (EMapiConnection *conn,
mid_list = l;
- ms = MoveCopyMessages (&obj_folder_src, &obj_folder_dst, &msg_id_array, do_copy);
+ ms = MoveCopyMessages (src_obj_folder, des_obj_folder, &msg_id_array, do_copy);
mapi_id_array_release (&msg_id_array);
if (ms != MAPI_E_SUCCESS) {
@@ -4881,76 +5128,20 @@ mapi_move_items (EMapiConnection *conn,
}
cleanup:
- mapi_object_release(&obj_folder_dst);
- mapi_object_release(&obj_folder_src);
-
- return ms;
-}
-
-gboolean
-e_mapi_connection_copy_items (EMapiConnection *conn,
- mapi_id_t src_fid,
- guint32 src_fid_options,
- mapi_id_t dest_fid,
- guint32 dest_fid_options,
- GSList *mids,
- GCancellable *cancellable,
- GError **perror)
-{
- enum MAPISTATUS ms;
-
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, MAPI_E_INVALID_PARAMETER);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
-
- e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
-
- LOCK ();
- ms = mapi_move_items (conn, src_fid, src_fid_options, dest_fid, dest_fid_options, mids, TRUE, cancellable, perror);
- UNLOCK ();
-
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-
- return ms == MAPI_E_SUCCESS;
-}
-
-gboolean
-e_mapi_connection_move_items (EMapiConnection *conn,
- mapi_id_t src_fid,
- guint32 src_fid_options,
- mapi_id_t dest_fid,
- guint32 dest_fid_options,
- GSList *mids,
- GCancellable *cancellable,
- GError **perror)
-{
- enum MAPISTATUS ms;
-
- CHECK_CORRECT_CONN_AND_GET_PRIV (conn, MAPI_E_INVALID_PARAMETER);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, MAPI_E_INVALID_PARAMETER);
-
- e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
-
- LOCK ();
- ms = mapi_move_items (conn, src_fid, src_fid_options, dest_fid, dest_fid_options, mids, FALSE, cancellable, perror);
UNLOCK ();
- e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
-
return ms == MAPI_E_SUCCESS;
}
gboolean
e_mapi_connection_remove_items (EMapiConnection *conn,
- uint32_t olFolder,
- mapi_id_t fid,
- guint32 fid_options,
+ mapi_object_t *obj_folder,
const GSList *mids,
GCancellable *cancellable,
GError **perror)
{
enum MAPISTATUS ms;
TALLOC_CTX *mem_ctx;
- mapi_object_t obj_folder;
uint32_t i;
mapi_id_t *id_messages;
const GSList *tmp = mids;
@@ -4958,33 +5149,27 @@ e_mapi_connection_remove_items (EMapiConnection *conn,
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (obj_folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
LOCK ();
mem_ctx = talloc_new (priv->session);
- mapi_object_init(&obj_folder);
- id_messages = talloc_array(mem_ctx, mapi_id_t, g_slist_length ((GSList *) mids));
+ id_messages = talloc_array (mem_ctx, mapi_id_t, g_slist_length ((GSList *) mids));
for (i = 0; tmp; tmp = tmp->next, i++) {
mapi_id_t *data = tmp->data;
id_messages[i] = *data;
}
- /* Attempt to open the folder */
- ms = open_folder (conn, olFolder, &fid, fid_options, &obj_folder, perror);
- if (ms != MAPI_E_SUCCESS) {
- goto cleanup;
- }
-
if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
ms = MAPI_E_USER_CANCEL;
goto cleanup;
}
/* Delete the messages from the folder */
- ms = DeleteMessage (&obj_folder, id_messages, i);
+ ms = DeleteMessage (obj_folder, id_messages, i);
if (ms != MAPI_E_SUCCESS) {
make_mapi_error (perror, "DeleteMessage", ms);
goto cleanup;
@@ -4993,7 +5178,6 @@ e_mapi_connection_remove_items (EMapiConnection *conn,
result = TRUE;
cleanup:
- mapi_object_release(&obj_folder);
talloc_free(mem_ctx);
UNLOCK ();
@@ -5397,7 +5581,7 @@ e_mapi_connection_get_folders_list (EMapiConnection *conn,
/* FIXME: May have to get the child folders count? Do we need/use it? */
folder = e_mapi_folder_new (mailbox_name, IPF_NOTE,
- MAPI_PERSONAL_FOLDER, mailbox_id, 0, 0, 0 ,0);
+ E_MAPI_FOLDER_CATEGORY_PERSONAL, mailbox_id, 0, 0, 0 ,0);
folder->is_default = true;
folder->default_type = olFolderTopInformationStore; /*Is this correct ?*/
folder->size = mailbox_size ? *mailbox_size : 0;
@@ -5405,7 +5589,7 @@ e_mapi_connection_get_folders_list (EMapiConnection *conn,
*mapi_folders = g_slist_prepend (*mapi_folders, folder);
/* FIXME: check status of get_child_folders */
- result = get_child_folders (conn, mem_ctx, MAPI_PERSONAL_FOLDER, &priv->msg_store, mailbox_id, mapi_folders, cb, cb_user_data, cancellable, perror);
+ result = get_child_folders (conn, mem_ctx, E_MAPI_FOLDER_CATEGORY_PERSONAL, &priv->msg_store, mailbox_id, mapi_folders, cb, cb_user_data, cancellable, perror);
*mapi_folders = g_slist_reverse (*mapi_folders);
@@ -5471,7 +5655,7 @@ e_mapi_connection_get_pf_folders_list (EMapiConnection *conn,
folder->is_default = true;
folder->default_type = olPublicFoldersAllPublicFolders;
*mapi_folders = g_slist_prepend (*mapi_folders, folder);
- result = get_child_folders (conn, mem_ctx, MAPI_FAVOURITE_FOLDER, &priv->public_store, mailbox_id, mapi_folders, cb, cb_user_data, cancellable, perror);
+ result = get_child_folders (conn, mem_ctx, E_MAPI_FOLDER_CATEGORY_PUBLIC, &priv->public_store, mailbox_id, mapi_folders, cb, cb_user_data, cancellable, perror);
*mapi_folders = g_slist_reverse (*mapi_folders);
cleanup:
@@ -5523,7 +5707,7 @@ e_mapi_connection_ex_to_smtp (EMapiConnection *conn,
gchar *smtp_addr = NULL;
CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
- e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, NULL);
e_return_val_mapi_error_if_fail (ex_address != NULL, MAPI_E_INVALID_PARAMETER, NULL);
@@ -5562,6 +5746,169 @@ e_mapi_connection_ex_to_smtp (EMapiConnection *conn,
return smtp_addr;
}
+gboolean
+e_mapi_connection_resolve_username (EMapiConnection *conn,
+ const gchar *to_resolve,
+ BuildReadPropsCB brp_cb,
+ gpointer brp_cb_user_data,
+ GetPropertiesCB cb,
+ gpointer cb_user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ enum MAPISTATUS ms;
+ TALLOC_CTX *mem_ctx;
+ struct SPropTagArray *tag_array;
+ struct SRowSet *rows = NULL;
+ struct PropertyTagArray_r *flaglist = NULL;
+ const gchar *str_array[2];
+ EResolveNamedIDsData *named_ids_list = NULL;
+ guint named_ids_len = 0, ii, jj, qq;
+
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (to_resolve != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (cb != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+ str_array[0] = to_resolve;
+ str_array[1] = NULL;
+
+ LOCK ();
+
+ mem_ctx = talloc_new (priv->session);
+
+ tag_array = set_SPropTagArray (mem_ctx, 3,
+ PidTagEntryId,
+ PidTagDisplayName,
+ PidTagSmtpAddress);
+
+ ms = MAPI_E_SUCCESS;
+ if (brp_cb != NULL && !brp_cb (conn, mem_ctx, tag_array, brp_cb_user_data, cancellable, perror)) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "build_read_props_callback", ms);
+ }
+
+ if (ms == MAPI_E_SUCCESS) {
+ for (ii = 0; ii < tag_array->cValues; ii++) {
+ uint32_t proptag = tag_array->aulPropTag[ii];
+
+ if (may_skip_property (proptag)) {
+ const gchar *name = get_proptag_name (proptag);
+ if (!name)
+ name = "";
+
+ g_debug ("%s: Cannot fetch property 0x%08x %s", G_STRFUNC, proptag, name);
+ } else {
+ maybe_add_named_id_tag (proptag, &named_ids_list, &named_ids_len);
+ }
+ }
+
+ if (named_ids_list) {
+ GHashTable *replace_hash;
+
+ if (!e_mapi_connection_resolve_named_props (conn, 0, named_ids_list, named_ids_len, cancellable, perror)) {
+ goto cleanup;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ goto cleanup;
+ }
+
+ replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, TRUE);
+ if (replace_hash) {
+ for (ii = 0; ii < tag_array->cValues; ii++) {
+ uint32_t proptag = tag_array->aulPropTag[ii];
+
+ maybe_replace_named_id_tag (&proptag, replace_hash);
+
+ tag_array->aulPropTag[ii] = proptag;
+ }
+
+ g_hash_table_destroy (replace_hash);
+ replace_hash = NULL;
+ }
+ }
+
+ ms = ResolveNames (priv->session, str_array, tag_array, &rows, &flaglist, MAPI_UNICODE);
+ if (ms != MAPI_E_SUCCESS && ms != MAPI_E_USER_CANCEL) {
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ } else {
+ ms = ResolveNames (priv->session, str_array, tag_array, &rows, &flaglist, 0);
+ }
+ }
+
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "ResolveNames", ms);
+ goto cleanup;
+ }
+ }
+
+ if (ms == MAPI_E_SUCCESS && rows) {
+ GHashTable *replace_hash = NULL;
+
+ if (named_ids_list)
+ replace_hash = prepare_maybe_replace_hash (named_ids_list, named_ids_len, FALSE);
+
+ for (qq = 0; qq < rows->cRows; qq++) {
+ struct mapi_SPropValue_array *properties;
+ struct SRow *row;
+
+ row = &rows->aRow[qq];
+ properties = talloc_zero (mem_ctx, struct mapi_SPropValue_array);
+ if (!properties) {
+ UNLOCK();
+ e_return_val_mapi_error_if_fail (properties != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ }
+
+ /* Conversion from SPropValue to mapi_SPropValue. (no padding here) */
+ properties->cValues = row->cValues;
+ properties->lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, properties->cValues + 1);
+ for (ii = 0, jj = 0; ii < row->cValues; ii++, jj++) {
+ if (may_skip_property (row->lpProps[ii].ulPropTag)) {
+ jj--;
+ properties->cValues--;
+ } else {
+ uint32_t proptag = row->lpProps[ii].ulPropTag;
+
+ maybe_replace_named_id_tag (&proptag, replace_hash);
+ row->lpProps[ii].ulPropTag = proptag;
+
+ cast_mapi_SPropValue (mem_ctx, &properties->lpProps[jj], &row->lpProps[ii]);
+ }
+ }
+
+ if (!cb (conn, mem_ctx, properties, cb_user_data, cancellable, perror)) {
+ ms = MAPI_E_CALL_FAILED;
+ make_mapi_error (perror, "callback", ms);
+ talloc_free (properties);
+ break;
+ }
+
+ talloc_free (properties);
+ }
+
+ if (replace_hash)
+ g_hash_table_destroy (replace_hash);
+ } else if (ms == MAPI_E_SUCCESS) {
+ if (flaglist && flaglist->aulPropTag[0] == MAPI_AMBIGUOUS) {
+ ms = MAPI_E_AMBIGUOUS_RECIP;
+ g_set_error (perror, E_MAPI_ERROR, ms, _("User name '%s' is ambiguous"), to_resolve);
+ } else {
+ ms = MAPI_E_NOT_FOUND;
+ g_set_error (perror, E_MAPI_ERROR, ms, _("User name '%s' not found"), to_resolve);
+ }
+ }
+
+ cleanup:
+ g_free (named_ids_list);
+ talloc_free (mem_ctx);
+
+ UNLOCK ();
+
+ return ms == MAPI_E_SUCCESS;
+}
+
static gint
emit_server_notification_signal (uint16_t event_type, gpointer event_data, gpointer user_data)
{
diff --git a/src/libexchangemapi/e-mapi-connection.h b/src/libexchangemapi/e-mapi-connection.h
index 348c0a3..dfd3d00 100644
--- a/src/libexchangemapi/e-mapi-connection.h
+++ b/src/libexchangemapi/e-mapi-connection.h
@@ -158,7 +158,7 @@ typedef gboolean (*WriteObjectCB) (EMapiConnection *conn,
gpointer user_data,
GCancellable *cancellable,
GError **perror);
-typedef gboolean (*GetFolderPropertiesCB) (EMapiConnection *conn,
+typedef gboolean (*GetPropertiesCB) (EMapiConnection *conn,
TALLOC_CTX *mem_ctx,
/* const */ struct mapi_SPropValue_array *properties,
gpointer user_data,
@@ -196,6 +196,20 @@ gboolean e_mapi_connection_reconnect (EMapiConnection *conn,
gboolean e_mapi_connection_close (EMapiConnection *conn);
gboolean e_mapi_connection_connected (EMapiConnection *conn);
+gboolean e_mapi_connection_test_foreign_folder (EMapiConnection *conn,
+ const gchar *username,
+ const gchar *folder_name,
+ mapi_id_t *fid, /* out */
+ GCancellable *cancellable,
+ GError **perror);
+
+gboolean e_mapi_connection_peek_store (EMapiConnection *conn,
+ gboolean public_store,
+ const gchar *foreign_username,
+ mapi_object_t **obj_store, /* out */
+ GCancellable *cancellable,
+ GError **perror);
+
gboolean e_mapi_connection_open_default_folder (EMapiConnection *conn,
uint32_t olFolderIdentifier,
mapi_object_t *obj_folder, /* out */
@@ -214,6 +228,13 @@ gboolean e_mapi_connection_open_public_folder (EMapiConnection *conn,
GCancellable *cancellable,
GError **perror);
+gboolean e_mapi_connection_open_foreign_folder (EMapiConnection *conn,
+ const gchar *username,
+ mapi_id_t fid,
+ mapi_object_t *obj_folder, /* out */
+ GCancellable *cancellable,
+ GError **perror);
+
gboolean e_mapi_connection_close_folder (EMapiConnection *conn,
mapi_object_t *obj_folder,
GCancellable *cancellable,
@@ -223,7 +244,7 @@ gboolean e_mapi_connection_get_folder_properties (EMapiConnection *conn,
mapi_object_t *obj_folder,
BuildReadPropsCB brp_cb,
gpointer brp_cb_user_data,
- GetFolderPropertiesCB cb,
+ GetPropertiesCB cb,
gpointer cb_user_data,
GCancellable *cancellable,
GError **perror);
@@ -306,25 +327,26 @@ gboolean e_mapi_connection_transfer_gal_object (EMapiConnection *conn,
GError **perror);
gboolean e_mapi_connection_get_public_folder (EMapiConnection *conn,
- mapi_object_t *obj_object,
+ mapi_object_t *obj_folder, /* out */
GCancellable *cancellable,
GError **perror);
-mapi_id_t e_mapi_connection_create_folder (EMapiConnection *conn,
- uint32_t olFolder,
- mapi_id_t pfid,
- guint32 fid_options,
+gboolean e_mapi_connection_create_folder (EMapiConnection *conn,
+ mapi_object_t *obj_parent_folder, /* in */
const gchar *name,
+ const gchar *new_folder_type, /* usually IPF_NOTE and similar */
+ mapi_id_t *new_fid, /* out */
GCancellable *cancellable,
GError **perror);
+
gboolean e_mapi_connection_remove_folder (EMapiConnection *conn,
- mapi_id_t fid,
- guint32 fid_options,
+ mapi_object_t *obj_store, /* in, store, to which folder belongs */
+ mapi_id_t fid_to_remove,
GCancellable *cancellable,
GError **perror);
+
gboolean e_mapi_connection_empty_folder (EMapiConnection *conn,
- mapi_id_t fid,
- guint32 fid_options,
+ mapi_object_t *obj_folder,
GCancellable *cancellable,
GError **perror);
gboolean e_mapi_connection_rename_folder (EMapiConnection *conn,
@@ -348,33 +370,20 @@ mapi_id_t e_mapi_connection_get_default_folder_id (EMapiConnection *conn,
GError **perror);
gboolean e_mapi_connection_set_flags (EMapiConnection *conn,
- uint32_t olFolder,
- mapi_id_t fid,
- guint32 fid_options,
+ mapi_object_t *obj_folder,
GSList *mid_list,
uint32_t flag,
GCancellable *cancellable,
GError **perror);
gboolean e_mapi_connection_remove_items (EMapiConnection *conn,
- uint32_t olFolder,
- mapi_id_t fid,
- guint32 fid_options,
+ mapi_object_t *obj_folder,
const GSList *mids, /* data is (mapi_id_t *) */
GCancellable *cancellable,
GError **perror);
-gboolean e_mapi_connection_copy_items (EMapiConnection *conn,
- mapi_id_t src_fid,
- guint32 src_fid_options,
- mapi_id_t dest_fid,
- guint32 dest_fid_options,
- GSList *mids,
- GCancellable *cancellable,
- GError **perror);
-gboolean e_mapi_connection_move_items (EMapiConnection *conn,
- mapi_id_t src_fid,
- guint32 src_fid_options,
- mapi_id_t dest_fid,
- guint32 dest_fid_options,
+gboolean e_mapi_connection_copymove_items (EMapiConnection *conn,
+ mapi_object_t *src_obj_folder,
+ mapi_object_t *des_obj_folder,
+ gboolean do_copy,
GSList *mids,
GCancellable *cancellable,
GError **perror);
@@ -414,6 +423,15 @@ gchar * e_mapi_connection_ex_to_smtp (EMapiConnection *conn,
GCancellable *cancellable,
GError **perror);
+gboolean e_mapi_connection_resolve_username (EMapiConnection *conn,
+ const gchar *to_resolve,
+ BuildReadPropsCB brp_cb,
+ gpointer brp_cb_user_data,
+ GetPropertiesCB cb,
+ gpointer cb_user_data,
+ GCancellable *cancellable,
+ GError **perror);
+
/* Push notifications APIs */
gboolean e_mapi_connection_enable_notifications (EMapiConnection *conn,
diff --git a/src/libexchangemapi/e-mapi-folder.c b/src/libexchangemapi/e-mapi-folder.c
index 369db67..d99e3dd 100644
--- a/src/libexchangemapi/e-mapi-folder.c
+++ b/src/libexchangemapi/e-mapi-folder.c
@@ -25,44 +25,75 @@
#include <config.h>
#endif
+#include <glib/gi18n-lib.h>
+
+#include <libedataserver/e-source.h>
+#include <libedataserver/e-source-group.h>
+#include <libedataserver/e-source-list.h>
+
#include "e-mapi-connection.h"
#include "e-mapi-folder.h"
#define d(x)
-static EMapiFolderType
-container_class_to_type (const gchar *type)
+static struct _folder_type_map {
+ const gchar *container_class;
+ EMapiFolderType folder_type;
+} folder_type_map[] = {
+ { IPF_APPOINTMENT, E_MAPI_FOLDER_TYPE_APPOINTMENT },
+ { IPF_CONTACT, E_MAPI_FOLDER_TYPE_CONTACT },
+ { IPF_STICKYNOTE, E_MAPI_FOLDER_TYPE_MEMO },
+ { IPF_TASK, E_MAPI_FOLDER_TYPE_TASK },
+ { IPF_NOTE, E_MAPI_FOLDER_TYPE_MAIL },
+ { "IPF.Note.HomePage", E_MAPI_FOLDER_TYPE_NOTE_HOMEPAGE },
+ { IPF_JOURNAL, E_MAPI_FOLDER_TYPE_JOURNAL}
+};
+
+EMapiFolderType
+e_mapi_folder_type_from_string (const gchar *container_class)
+{
+ gint ii;
+
+ if (!container_class)
+ return E_MAPI_FOLDER_TYPE_UNKNOWN;
+
+ for (ii = 0; ii < G_N_ELEMENTS (folder_type_map); ii++) {
+ if (g_str_equal (folder_type_map[ii].container_class, container_class))
+ return folder_type_map[ii].folder_type;
+ }
+
+ return E_MAPI_FOLDER_TYPE_UNKNOWN;
+}
+
+const gchar *
+e_mapi_folder_type_to_string (EMapiFolderType folder_type)
{
- EMapiFolderType folder_type = MAPI_FOLDER_TYPE_UNKNOWN;;
+ gint ii;
- if (!strcmp (type, IPF_APPOINTMENT))
- folder_type = MAPI_FOLDER_TYPE_APPOINTMENT;
- else if (!strcmp (type, IPF_CONTACT))
- folder_type = MAPI_FOLDER_TYPE_CONTACT;
- else if (!strcmp (type, IPF_STICKYNOTE))
- folder_type = MAPI_FOLDER_TYPE_MEMO;
- else if (!strcmp (type, IPF_TASK))
- folder_type = MAPI_FOLDER_TYPE_TASK;
- else if (!strcmp (type, IPF_NOTE))
- folder_type = MAPI_FOLDER_TYPE_MAIL;
- /* Fixme : no definition for this is available in mapidef.h */
- else if (!strcmp (type, "IPF.Note.HomePage"))
- folder_type = MAPI_FOLDER_TYPE_NOTE_HOMEPAGE;
- else if (!strcmp (type, IPF_JOURNAL))
- folder_type = MAPI_FOLDER_TYPE_JOURNAL;
+ for (ii = 0; ii < G_N_ELEMENTS (folder_type_map); ii++) {
+ if (folder_type_map[ii].folder_type == folder_type)
+ return folder_type_map[ii].container_class;
+ }
- return folder_type;
+ return NULL;
}
EMapiFolder *
-e_mapi_folder_new (const gchar *folder_name, const gchar *container_class, EMapiFolderCategory category, mapi_id_t folder_id, mapi_id_t parent_folder_id, uint32_t child_count, uint32_t unread_count, uint32_t total)
+e_mapi_folder_new (const gchar *folder_name,
+ const gchar *container_class,
+ EMapiFolderCategory category,
+ mapi_id_t folder_id,
+ mapi_id_t parent_folder_id,
+ uint32_t child_count,
+ uint32_t unread_count,
+ uint32_t total)
{
EMapiFolder *folder;
folder = g_new0 (EMapiFolder, 1);
folder->is_default = FALSE;
folder->folder_name = g_strdup (folder_name);
- folder->container_class = container_class_to_type (container_class);
+ folder->container_class = e_mapi_folder_type_from_string (container_class);
folder->folder_id = folder_id;
folder->parent_folder_id = parent_folder_id;
folder->child_count = child_count;
@@ -105,12 +136,6 @@ e_mapi_folder_free (EMapiFolder *folder)
}
}
-EMapiFolderType
-e_mapi_container_class (gchar *type)
-{
- return container_class_to_type (type);
-}
-
const gchar *
e_mapi_folder_get_name (EMapiFolder *folder)
{
@@ -172,3 +197,256 @@ e_mapi_folder_free_list (GSList *folder_list)
g_slist_foreach (folder_list, (GFunc) e_mapi_folder_free, NULL);
g_slist_free (folder_list);
}
+
+gchar *
+e_mapi_folder_pick_color_spec (gint move_by,
+ gboolean around_middle)
+{
+ static gint color_mover = 0;
+ static gint color_indexer = -1;
+ const guint32 colors[] = {
+ 0x1464ae, /* dark blue */
+ 0x14ae64, /* dark green */
+ 0xae1464, /* dark red */
+ 0
+ };
+ guint32 color;
+
+ if (move_by <= 0)
+ move_by = 1;
+
+ while (move_by > 0) {
+ move_by--;
+
+ color_indexer++;
+ if (colors[color_indexer] == 0) {
+ color_mover += 1;
+ color_indexer = 0;
+ }
+ }
+
+ color = colors[color_indexer];
+ color = (color & ~(0xFF << (color_indexer * 8))) |
+ (((((color >> (color_indexer * 8)) & 0xFF) + (0x33 * color_mover)) % 0xFF) << (color_indexer * 8));
+
+ if (around_middle) {
+ gint rr, gg, bb, diff;
+
+ rr = (0xFF0000 & color) >> 16;
+ gg = (0x00FF00 & color) >> 8;
+ bb = (0x0000FF & color);
+
+ diff = 0x80 - rr;
+ if (diff < 0x80 - gg)
+ diff = 0x80 - gg;
+ if (diff < 0x80 - bb)
+ diff = 0x80 - bb;
+
+ rr = rr + diff < 0 ? 0 : rr + diff > 0xCC ? 0xCC : rr + diff;
+ gg = gg + diff < 0 ? 0 : gg + diff > 0xCC ? 0xCC : gg + diff;
+ bb = bb + diff < 0 ? 0 : bb + diff > 0xCC ? 0xCC : bb + diff;
+
+ color = (rr << 16) + (gg << 8) + bb;
+ }
+
+ return g_strdup_printf ("#%06x", color);
+}
+
+#define MAPI_URI_PREFIX "mapi://"
+
+gboolean
+e_mapi_folder_add_as_esource (EMapiFolderType folder_type,
+ const gchar *login_profile,
+ const gchar *login_domain,
+ const gchar *login_realm,
+ const gchar *login_host,
+ const gchar *login_user,
+ gboolean login_kerberos,
+ gboolean offline_sync,
+ EMapiFolderCategory folder_category,
+ const gchar *foreign_username, /* NULL for public folder */
+ const gchar *folder_name,
+ const gchar *fid,
+ GError **perror)
+{
+ ESourceList *source_list = NULL;
+ ESourceGroup *group = NULL;
+ const gchar *conf_key = NULL;
+ GConfClient* client;
+ GSList *sources;
+ ESource *source = NULL;
+ gchar *relative_uri = NULL;
+ gchar *base_uri = NULL;
+
+ g_return_val_if_fail (login_profile != NULL, FALSE);
+ g_return_val_if_fail (login_host != NULL, FALSE);
+ g_return_val_if_fail (login_user != NULL, FALSE);
+ g_return_val_if_fail (folder_name != NULL, FALSE);
+ g_return_val_if_fail (fid != NULL, FALSE);
+ g_return_val_if_fail (folder_category == E_MAPI_FOLDER_CATEGORY_PUBLIC || folder_category == E_MAPI_FOLDER_CATEGORY_FOREIGN, FALSE);
+ if (folder_category == E_MAPI_FOLDER_CATEGORY_FOREIGN)
+ g_return_val_if_fail (foreign_username != NULL, FALSE);
+
+ if (folder_type == E_MAPI_FOLDER_TYPE_APPOINTMENT)
+ conf_key = CALENDAR_SOURCES;
+ else if (folder_type == E_MAPI_FOLDER_TYPE_TASK)
+ conf_key = TASK_SOURCES;
+ else if (folder_type == E_MAPI_FOLDER_TYPE_MEMO)
+ conf_key = JOURNAL_SOURCES;
+ else if (folder_type == E_MAPI_FOLDER_TYPE_JOURNAL)
+ conf_key = JOURNAL_SOURCES;
+ else if (folder_type == E_MAPI_FOLDER_TYPE_CONTACT)
+ conf_key = ADDRESSBOOK_SOURCES;
+ else {
+ g_propagate_error (perror, g_error_new_literal (E_MAPI_ERROR, MAPI_E_INVALID_PARAMETER, _("Cannot add folder, unsupported folder type")));
+ return FALSE;
+ }
+
+ client = gconf_client_get_default ();
+ source_list = e_source_list_new_for_gconf (client, conf_key);
+ base_uri = g_strdup_printf ("%s%s %s/", MAPI_URI_PREFIX, login_user, login_host);
+ group = e_source_list_peek_group_by_base_uri (source_list, base_uri);
+ if (!group) {
+ g_propagate_error (perror, g_error_new_literal (E_MAPI_ERROR, MAPI_E_INVALID_PARAMETER, _("Cannot add folder, group of sources not found")));
+ g_object_unref (source_list);
+ g_object_unref (client);
+ g_free (base_uri);
+
+ return FALSE;
+ }
+
+ sources = e_source_group_peek_sources (group);
+ for (; sources != NULL; sources = g_slist_next (sources)) {
+ ESource *source = E_SOURCE (sources->data);
+ gchar *folder_id = e_source_get_duped_property (source, "folder-id");
+ if (folder_id) {
+ if (g_str_equal (fid, folder_id)) {
+ g_object_unref (source_list);
+ g_object_unref (client);
+ g_free (folder_id);
+ g_free (base_uri);
+
+ g_propagate_error (perror,
+ g_error_new (E_MAPI_ERROR, MAPI_E_INVALID_PARAMETER,
+ _("Cannot add folder, folder already exists as '%s'"), e_source_peek_name (source)));
+ return FALSE;
+ }
+
+ g_free (folder_id);
+ }
+ }
+
+ relative_uri = g_strconcat (";", fid, NULL);
+ source = e_source_new (folder_name, relative_uri);
+ e_source_set_property (source, "username", login_user);
+ e_source_set_property (source, "host", login_host);
+ e_source_set_property (source, "profile", login_profile);
+ e_source_set_property (source, "domain", login_domain);
+ e_source_set_property (source, "realm", login_realm);
+ e_source_set_property (source, "folder-id", fid);
+ e_source_set_property (source, "offline_sync", offline_sync ? "1" : "0");
+ e_source_set_property (source, "delete", "yes");
+ if (folder_category == E_MAPI_FOLDER_CATEGORY_PUBLIC)
+ e_source_set_property (source, "public", "yes");
+ else
+ e_source_set_property (source, "foreign-username", foreign_username);
+ if (login_kerberos) {
+ e_source_set_property (source, "kerberos", "required");
+ } else {
+ e_source_set_property (source, "auth", "1");
+ e_source_set_property (source, "auth-type", "plain/password");
+ }
+
+ /* set also color for calendar-like sources */
+ if (folder_type != E_MAPI_FOLDER_TYPE_CONTACT) {
+ GSList *sources = e_source_group_peek_sources (group);
+ gchar *color_str;
+
+ color_str = e_mapi_folder_pick_color_spec (1 + g_slist_length (sources), folder_type != E_MAPI_FOLDER_TYPE_APPOINTMENT);
+ e_source_set_color_spec (source, color_str);
+ g_free (color_str);
+ }
+
+ e_source_group_add_source (group, source, -1);
+
+ g_object_unref (source);
+ g_object_unref (client);
+ g_free (relative_uri);
+ g_free (base_uri);
+
+ if (!e_source_list_sync (source_list, perror)) {
+ g_object_unref (source_list);
+ return FALSE;
+ }
+
+ g_object_unref (source_list);
+ return TRUE;
+}
+
+gboolean
+e_mapi_folder_remove_as_esource (EMapiFolderType folder_type,
+ const gchar *login_host,
+ const gchar *login_user,
+ const gchar *fid,
+ GError **perror)
+{
+ ESourceList *source_list = NULL;
+ ESourceGroup *group = NULL;
+ const gchar *conf_key = NULL;
+ GConfClient* client;
+ GSList *sources = NULL;
+ gchar *base_uri = NULL;
+
+ g_return_val_if_fail (login_host != NULL, FALSE);
+ g_return_val_if_fail (login_user != NULL, FALSE);
+ g_return_val_if_fail (fid != NULL, FALSE);
+
+ if (folder_type == E_MAPI_FOLDER_TYPE_APPOINTMENT)
+ conf_key = CALENDAR_SOURCES;
+ else if (folder_type == E_MAPI_FOLDER_TYPE_TASK)
+ conf_key = TASK_SOURCES;
+ else if (folder_type == E_MAPI_FOLDER_TYPE_MEMO)
+ conf_key = JOURNAL_SOURCES;
+ else if (folder_type == E_MAPI_FOLDER_TYPE_JOURNAL)
+ conf_key = JOURNAL_SOURCES;
+ else if (folder_type == E_MAPI_FOLDER_TYPE_CONTACT)
+ conf_key = ADDRESSBOOK_SOURCES;
+ else {
+ g_propagate_error (perror, g_error_new_literal (E_MAPI_ERROR, MAPI_E_INVALID_PARAMETER, _("Cannot remove folder, unsupported folder type")));
+ return FALSE;
+ }
+
+ client = gconf_client_get_default ();
+ source_list = e_source_list_new_for_gconf (client, conf_key);
+ base_uri = g_strdup_printf ("%s%s %s/", MAPI_URI_PREFIX, login_user, login_host);
+ group = e_source_list_peek_group_by_base_uri (source_list, base_uri);
+ if (!group) {
+ g_free (base_uri);
+ g_object_unref (source_list);
+ g_object_unref (client);
+
+ return TRUE;
+ }
+
+ sources = e_source_group_peek_sources (group);
+ for (; sources != NULL; sources = g_slist_next (sources)) {
+ ESource *source = E_SOURCE (sources->data);
+ gchar *folder_id = e_source_get_duped_property (source, "folder-id");
+ if (folder_id) {
+ if (g_str_equal (fid, folder_id)) {
+ g_free (folder_id);
+
+ e_source_group_remove_source (group, source);
+ break;
+ }
+
+ g_free (folder_id);
+ }
+ }
+
+ g_free (base_uri);
+ g_object_unref (source_list);
+ g_object_unref (client);
+
+ return TRUE;
+}
diff --git a/src/libexchangemapi/e-mapi-folder.h b/src/libexchangemapi/e-mapi-folder.h
index a0fa528..3212fb6 100644
--- a/src/libexchangemapi/e-mapi-folder.h
+++ b/src/libexchangemapi/e-mapi-folder.h
@@ -28,21 +28,30 @@
#include <libmapi/libmapi.h>
+#define CALENDAR_SOURCES "/apps/evolution/calendar/sources"
+#define TASK_SOURCES "/apps/evolution/tasks/sources"
+#define JOURNAL_SOURCES "/apps/evolution/memos/sources"
+#define SELECTED_CALENDARS "/apps/evolution/calendar/display/selected_calendars"
+#define SELECTED_TASKS "/apps/evolution/calendar/tasks/selected_tasks"
+#define SELECTED_JOURNALS "/apps/evolution/calendar/memos/selected_memos"
+#define ADDRESSBOOK_SOURCES "/apps/evolution/addressbook/sources"
+
typedef enum {
- MAPI_FOLDER_TYPE_MAIL=1,
- MAPI_FOLDER_TYPE_APPOINTMENT,
- MAPI_FOLDER_TYPE_CONTACT,
- MAPI_FOLDER_TYPE_MEMO,
- MAPI_FOLDER_TYPE_JOURNAL,
- MAPI_FOLDER_TYPE_TASK,
- MAPI_FOLDER_TYPE_NOTE_HOMEPAGE,
- MAPI_FOLDER_TYPE_UNKNOWN
+ E_MAPI_FOLDER_TYPE_UNKNOWN = 0,
+ E_MAPI_FOLDER_TYPE_MAIL,
+ E_MAPI_FOLDER_TYPE_APPOINTMENT,
+ E_MAPI_FOLDER_TYPE_CONTACT,
+ E_MAPI_FOLDER_TYPE_MEMO,
+ E_MAPI_FOLDER_TYPE_JOURNAL,
+ E_MAPI_FOLDER_TYPE_TASK,
+ E_MAPI_FOLDER_TYPE_NOTE_HOMEPAGE
} EMapiFolderType;
typedef enum {
- MAPI_PERSONAL_FOLDER,
- MAPI_FAVOURITE_FOLDER,
- MAPI_FOREIGN_FOLDER
+ E_MAPI_FOLDER_CATEGORY_UNKNOWN = 0,
+ E_MAPI_FOLDER_CATEGORY_PERSONAL,
+ E_MAPI_FOLDER_CATEGORY_PUBLIC,
+ E_MAPI_FOLDER_CATEGORY_FOREIGN
} EMapiFolderCategory;
typedef struct _EMapiFolder {
@@ -72,6 +81,9 @@ typedef struct _EMapiFolder {
gpointer reserved3;
} EMapiFolder;
+EMapiFolderType e_mapi_folder_type_from_string (const gchar *container_class);
+const gchar * e_mapi_folder_type_to_string (EMapiFolderType folder_type);
+
EMapiFolder * e_mapi_folder_new (const gchar *folder_name,
const gchar *container_class,
EMapiFolderCategory catgory,
@@ -82,7 +94,6 @@ EMapiFolder * e_mapi_folder_new (const gchar *folder_name,
uint32_t total);
EMapiFolder * e_mapi_folder_copy (EMapiFolder *src);
void e_mapi_folder_free (EMapiFolder *folder);
-EMapiFolderType e_mapi_container_class (gchar *type);
const gchar * e_mapi_folder_get_name (EMapiFolder *folder);
mapi_id_t e_mapi_folder_get_fid (EMapiFolder *folder);
@@ -95,4 +106,26 @@ gboolean e_mapi_folder_is_root (EMapiFolder *folder);
GSList * e_mapi_folder_copy_list (GSList *folder_list);
void e_mapi_folder_free_list (GSList *folder_list);
+gchar * e_mapi_folder_pick_color_spec (gint move_by,
+ gboolean around_middle);
+
+gboolean e_mapi_folder_add_as_esource (EMapiFolderType folder_type,
+ const gchar *login_profile,
+ const gchar *login_domain,
+ const gchar *login_realm,
+ const gchar *login_host,
+ const gchar *login_user,
+ gboolean login_kerberos,
+ gboolean offline_sync,
+ EMapiFolderCategory folder_category,
+ const gchar *foreign_username, /* NULL for public folder */
+ const gchar *folder_name,
+ const gchar *fid,
+ GError **perror);
+
+gboolean e_mapi_folder_remove_as_esource (EMapiFolderType folder_type,
+ const gchar *login_host,
+ const gchar *login_user,
+ const gchar *fid,
+ GError **perror);
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]