[evolution-exchange] Bug #456240 - Move exchange plugin to exchange package
- From: Milan Crha <mcrha src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [evolution-exchange] Bug #456240 - Move exchange plugin to exchange package
- Date: Fri, 2 Oct 2009 13:09:37 +0000 (UTC)
commit d0236a993c6ea6c7d9427143b48c591e21e4ab5b
Author: Milan Crha <mcrha redhat com>
Date: Fri Oct 2 15:08:53 2009 +0200
Bug #456240 - Move exchange plugin to exchange package
Makefile.am | 1 +
configure.ac | 20 +-
eplugin/ChangeLog | 1874 +++++++++++++++++++++++
eplugin/Makefile.am | 77 +
eplugin/exchange-account-setup.c | 1150 ++++++++++++++
eplugin/exchange-calendar.c | 539 +++++++
eplugin/exchange-change-password.c | 194 +++
eplugin/exchange-change-password.h | 33 +
eplugin/exchange-config-listener.c | 1520 ++++++++++++++++++
eplugin/exchange-config-listener.h | 84 +
eplugin/exchange-contacts.c | 548 +++++++
eplugin/exchange-delegates-user.c | 628 ++++++++
eplugin/exchange-delegates-user.h | 81 +
eplugin/exchange-delegates.c | 1027 +++++++++++++
eplugin/exchange-delegates.h | 34 +
eplugin/exchange-folder-permission.c | 527 +++++++
eplugin/exchange-folder-size-display.c | 170 ++
eplugin/exchange-folder-size-display.h | 33 +
eplugin/exchange-folder-subscription.c | 380 +++++
eplugin/exchange-folder-subscription.h | 34 +
eplugin/exchange-folder.c | 420 +++++
eplugin/exchange-mail-send-options.c | 196 +++
eplugin/exchange-operations.c | 305 ++++
eplugin/exchange-operations.h | 56 +
eplugin/exchange-permissions-dialog.c | 984 ++++++++++++
eplugin/exchange-permissions-dialog.h | 56 +
eplugin/exchange-send-options.c | 621 ++++++++
eplugin/exchange-send-options.h | 83 +
eplugin/exchange-user-dialog.c | 285 ++++
eplugin/exchange-user-dialog.h | 56 +
eplugin/org-gnome-exchange-operations.eplug | 114 ++
eplugin/org-gnome-exchange-operations.eplug.xml | 120 ++
eplugin/org-gnome-exchange-operations.error | 262 ++++
eplugin/org-gnome-exchange-operations.error.xml | 263 ++++
34 files changed, 12771 insertions(+), 4 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 31f991e..c584ad1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,5 @@
SUBDIRS = \
+ eplugin \
tools \
camel \
addressbook \
diff --git a/configure.ac b/configure.ac
index e7003c0..1fbe5f8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -11,6 +11,7 @@ AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
m4_define([glib_minimum_version], [2.16.0])
m4_define([gtk_minimum_version], [2.10.0])
m4_define([eds_minimum_version], [eex_version])
+m4_define([evo_minimum_version], [eex_version])
m4_define([gconf_minimum_version], [2.0.0]) # XXX Just a Guess
m4_define([libbonobo_minimum_version], [2.20.3])
m4_define([libxml_minimum_version], [2.0.0]) # XXX Just a Guess
@@ -192,6 +193,12 @@ if test "x$EXCHANGE_PACKAGE" != "x"; then
exit 1
fi
+plugindir=`$PKG_CONFIG --variable=plugindir evolution-plugin`
+AC_SUBST(plugindir)
+
+EVOLUTION_PLUGIN_errordir="`pkg-config --variable=errordir evolution-plugin`"
+AC_SUBST(EVOLUTION_PLUGIN_errordir)
+
extensiondir="`pkg-config --variable=extensiondir evolution-data-server-$EDS_API_VERSION`"
AC_SUBST(extensiondir)
@@ -207,9 +214,6 @@ AC_SUBST(EVOLUTION_privlibdir)
EVOLUTION_privlibexecdir="`pkg-config --variable=privlibexecdir evolution-shell`"
AC_SUBST(EVOLUTION_privlibexecdir)
-EVOLUTION_privdatadir="`pkg-config --variable=privdatadir evolution-shell`"
-AC_SUBST(EVOLUTION_privdatadir)
-
EVOLUTION_imagesdir="`pkg-config --variable=imagesdir evolution-shell`"
AC_SUBST(EVOLUTION_imagesdir)
@@ -230,7 +234,7 @@ AC_SUBST(CAMEL_CFLAGS)
PKG_CHECK_MODULES(MAIL, libecal-$EDS_API_VERSION)
AC_SUBST(MAIL_CFLAGS)
-PKG_CHECK_MODULES(EXCHANGE_STORAGE, evolution-shell evolution-plugin libedataserverui-$EDS_API_VERSION libedata-book-$EDS_API_VERSION libedata-cal-$EDS_API_VERSION libsoup-2.4 libxml-2.0 camel-provider-$EDS_API_VERSION)
+PKG_CHECK_MODULES(EXCHANGE_STORAGE, libedataserverui-$EDS_API_VERSION libedata-book-$EDS_API_VERSION libedata-cal-$EDS_API_VERSION libsoup-2.4 libxml-2.0 camel-provider-$EDS_API_VERSION)
AC_SUBST(EXCHANGE_STORAGE_CFLAGS)
AC_SUBST(EXCHANGE_STORAGE_LIBS)
@@ -238,6 +242,13 @@ PKG_CHECK_MODULES(LIBEXCHANGE, libsoup-2.4 evolution-shell libedataserverui-$EDS
AC_SUBST(LIBEXCHANGE_CFLAGS)
AC_SUBST(LIBEXCHANGE_LIBS)
+dnl ****************************
+dnl Check for evolution plugins
+dnl ****************************
+PKG_CHECK_MODULES(EVOLUTION_PLUGIN, evolution-plugin >= evo_minimum_version)
+AC_SUBST(EVOLUTION_PLUGIN_CFLAGS)
+AC_SUBST(EVOLUTION_PLUGIN_LIBS)
+
dnl *********************
dnl Pilot license support
dnl *********************
@@ -374,6 +385,7 @@ dnl ******************************
AC_OUTPUT([
Makefile
evolution-exchange-zip
+eplugin/Makefile
camel/Makefile
addressbook/Makefile
calendar/Makefile
diff --git a/eplugin/ChangeLog b/eplugin/ChangeLog
new file mode 100644
index 0000000..91a2e01
--- /dev/null
+++ b/eplugin/ChangeLog
@@ -0,0 +1,1874 @@
+2009-04-24 Milan Crha <mcrha redhat com>
+
+ ** Fix for bug #572348
+
+ * exchange-delegates.glade:
+ * e-foreign-folder-dialog.glade:
+ * exchange-folder-subscription.c:
+ * exchange-delegates-user.c:
+ Remove deprecated Gtk+ symbols.
+
+2009-02-26 Andre Klapper <a9016009 gmx de>
+
+ * exchange-permissions-dialog.c:
+ remove deprecated and commented code.
+
+2008-12-08 Bharath Acharya <abharath novell com>
+
+ ** Fix for bug #558498
+
+ * exchange-account-setup.c: (org_gnome_exchange_settings),
+ (destroy_oof_data), (org_gnome_exchange_commit):
+ * org-gnome-exchange-operations.error.xml:Check for the offline status
+ before setting up the Exchange settings.
+
+2008-12-02 Milan Crha <mcrha redhat com>
+
+ ** Part of fix for bug #562228
+
+ * exchange-account-setup.c: (want_mailbox_toggled),
+ (org_gnome_exchange_owa_url):
+ Make it clearer the mailbox entry is optional.
+
+2008-10-22 Bharath Acharya <abharath novell com>
+
+ ** Fix for bug #557246
+
+ * exchange-folder.c: (org_gnome_exchange_check_inbox_subscribed): Pop
+ up the "Unsubscribe Folder" option only for the subscribed folders and
+ not to the Other's folder hierarchy.
+
+2008-10-08 Milan Crha <mcrha redhat com>
+
+ ** Fix for bug #530606
+
+ * exchange-contacts.c: (e_exchange_contacts_get_contacts),
+ (e_exchange_contacts_pcontacts_on_change),
+ (e_exchange_contacts_pcontacts), (e_exchange_contacts_check),
+ (e_exchange_contacts_commit):
+ * exchange-account-setup.c: (btn_chpass_clicked), (btn_dass_clicked),
+ (btn_fsize_clicked), (org_gnome_exchange_show_folder_size_factory):
+ * exchange-calendar.c: (e_exchange_calendar_get_calendars),
+ (e_exchange_calendar_pcalendar_on_change),
+ (e_exchange_calendar_pcalendar), (e_exchange_calendar_check),
+ (e_exchange_calendar_commit):
+ Check validity of returned pointer before using it.
+
+2008-10-03 Sankar P <psankar novell com>
+
+License Changes
+
+ * exchange-account-setup.c:
+ * exchange-contacts.c:
+ * exchange-operations.c:
+ * exchange-operations.h:
+
+2008-09-24 Sankar P <psankar novell com>
+
+License Changes
+
+ * exchange-delegates-user.c:
+
+2008-09-23 Milan Crha <mcrha redhat com>
+
+ ** Part of fix for bug #553273
+
+ * exchange-config-listener.c: (exchange_config_listener_authenticate):
+ Always end e_error_run/e_error_new calls with NULL parameter.
+
+2008-09-16 Sankar P <psankar novell com>
+
+License Changes
+
+ * exchange-user-dialog.c:
+
+2008-09-04 Sankar P <psankar novell com>
+
+License Changes
+
+ * exchange-calendar.c:
+
+2008-09-02 Sankar P <psankar novell com>
+
+License Changes
+
+ * exchange-config-listener.c:
+ * exchange-delegates.c:
+ * exchange-folder-size-display.c:
+ * exchange-folder.c:
+ * exchange-mail-send-options.c:
+ * exchange-permissions-dialog.c:
+ * exchange-permissions-dialog.h:
+ * exchange-send-options.c:
+ * exchange-user-dialog.h:
+
+2008-08-28 Matthew Barnes <mbarnes redhat com>
+
+ ** Fixes bug #458512
+
+ * exchange-send-options.glade:
+ Delete the accessibility tag from the User button.
+
+2008-08-27 Sankar P <psankar novell com>
+
+License Changes
+
+ * exchange-change-password.c:
+ * exchange-change-password.h:
+ * exchange-config-listener.h:
+ * exchange-delegates-user.h:
+ * exchange-delegates.h:
+ * exchange-folder-permission.c:
+ * exchange-folder-size-display.h:
+ * exchange-folder-subscription.c:
+ * exchange-folder-subscription.h:
+ * exchange-send-options.h:
+
+2008-08-14 Matthew Barnes <mbarnes redhat com>
+
+ * exchange-send-options.c:
+ Use e_display_help() for displaying help.
+
+2008-08-06 Milan Crha <mcrha redhat com>
+
+ ** Fix for bug #435969
+
+ * org-gnome-exchange-operations.eplug.xml:
+ Show authentication section in an account druid too.
+
+2008-07-31 Matthew Barnes <mbarnes redhat com>
+
+ ** Fixes part of bug #545568
+
+ * org-gnome-exchange-operations.eplug.xml:
+ Add "system_plugin=true" so it's not shown in the Plugin Manager.
+ This plugin is not designed to be disabled by the user.
+
+2008-07-30 Milan Crha <mcrha redhat com>
+
+ ** Part of fix for bug #500389
+
+ * exchange-account-setup.c: (gal_auth_to_string),
+ (owa_authenticate_user): Use default authentication for GAL.
+
+2008-07-11 Bharath Acharya <abharath novell com>
+
+ ** Fix for bug #542149
+
+ * exchange-folder-subscription.c: (subscribe_to_folder): Display an
+ error message to restart if user tries to subscribe to other's mailbox.
+ * org-gnome-exchange-operations.error.xml: Added the corresponding
+ error message.
+
+2008-06-16 Milan Crha <mcrha redhat com>
+
+ ** Fix for bug #273627
+
+ * exchange-account-setup.c: (owa_authenticate_user),
+ (update_mailbox_param_in_url), (mailbox_editor_entry_changed),
+ (org_gnome_exchange_owa_url): New entry to enter mailbox name in case
+ it differs from the username. The entry is updated after a validation
+ and shows the mailbox name as was used for validation.
+
+2008-06-05 Matthew Barnes <mbarnes redhat com>
+
+ * exchange-permissions-dialog.c:
+ Here too.
+
+2008-06-04 Matthew Barnes <mbarnes redhat com>
+
+ * exchange-delegates-user.c:
+ Don't undef DISABLE_DEPRECATED macros in source code.
+ That's just evil.
+
+2008-06-02 Jacob Brown <jeblinux gmail com>
+
+ ** Fix for bug #529464
+
+ * org-gnome-exchange-operations.eplug.xml: Do not use "handle"
+
+2008-05-27 Bharath Acharya <abharath novell com>
+
+ * Fixes bnc #394441
+
+ * exchange-contacts.c: (e_exchange_contacts_commit): Fixes a double
+ free
+
+2008-05-22 Matthew Barnes <mbarnes redhat com>
+
+ ** Fixes part of bug #534360
+
+ * exchange-account-setup.c:
+ * exchange-send-options.h:
+ Migrate from deprecated GtkObject symbols to GObject equivalents.
+
+2008-04-21 Bharath Acharya <abharath novell com>
+
+ Fixes bnc #378203
+
+ * exchange-folder-permission.c:
+ (org_gnome_exchange_folder_permissions): Return sanely if the path
+ value is corrupted.
+
+2008-04-02 Matthew Barnes <mbarnes redhat com>
+
+ * Makefile.am:
+ Add EVOLUTION_MAIL_CFLAGS and EVOLUTION_MAIL_LIBS.
+
+ * exchange-mail-send-options.c (append_to_header),
+ (org_gnome_exchange_send_options):
+ Adapt to streamlined EMsgComposer API.
+
+2008-04-02 Ross Burton <ross openedhand com>
+
+ ** Fix for bug #522764
+
+ * exchange-account-setup.c:
+ * exchange-folder-subscription.c:
+ * exchange-folder-permission.c: Remove unused include.
+
+2008-03-18 Milan Crha <mcrha redhat com>
+
+ ** Part of fix for bug #511952
+
+ * exchange-folder-subscription.c: (setup_name_selector):
+ * exchange-send-options.c: (exchange_sendoptions_dialog_run):
+ Marking text for translation.
+
+2008-02-18 Srinivasa Ragavan <sragavan novell com>
+
+ * Fix for bug #339266
+
+ * exchange-account-setup.c:
+ (org_gnome_exchange_show_folder_size_factory): Upstreamed OpenSUSE
+ patch.
+
+2008-02-18 Srinivasa Ragavan <sragavan novell com>
+
+ ** Fix for bug #294999
+
+ * exchange-folder-subscription.c: (subscribe_to_folder): Upstreamed
+ OpenSUSE patch.
+
+2008-02-18 Srinivasa Ragavan <sragavan novell com>
+
+ ** Patch from OpenSUSE.
+
+ * exchange-delegates-user.c: Warnings.
+
+2008-02-18 Srinivasa Ragavan <sragavan novell com>
+
+ * exchange-folder-subscription.c: (subscribe_to_folder),
+ (create_folder_subscription_dialog): Pushing a downstream patch from
+ OpenSUSE.
+
+2008-02-02 Jeff Cai <jeff cai sun com>
+
+ ** Fixes bug #513395
+
+ * exchange-account-setup.c: (owa_authenticate_user),
+ (owa_editor_entry_changed), (org_gnome_exchange_owa_url),
+ (org_gnome_exchange_check_options), (org_gnome_exchange_commit):
+ Check parameters before calling camel_url_new
+
+2008-01-28 Srinivasa Ragavan <sragavan novell com>
+
+ * exchange-calendar.c: (e_exchange_calendar_commit): Fixes a double
+ free.
+
+2007-12-31 Sushma Rai <rsushma novell com>
+
+ ** Fixes bug #327965
+
+ * exchange-calendar.c (e_exchange_calendar_commit):
+ * exchange-contacts.c (e_exchange_contacts_commit): Setting the
+ e-source property username with domain if the domain is specified.
+
+2007-12-20 Matthew Barnes <mbarnes redhat com>
+
+ ** Fixes part of bug #362638
+
+ * exchange_folder.c:
+ Use the new MailMsg API for messages.
+
+2007-12-13 Tobias Mueller <tobiasmue svn gnome org>
+ Patch by evilninjasquirrel hotbrev com
+
+ ** Fixes bug 474043
+ * plugins/exchange-operations/exchange-operations.c:
+ * plugins/exchange-operations/exchange-operations.h
+ Prevent buffer overflows, by introducing a fourth parameter to
+ exchange_operations_tokenize_string - a max size to copy
+
+2007-12-04 David Turner <cillian64 googlemail com>
+
+ ** Fix for bug #466241
+
+ * exchange-account-setup.c: (org_gnome_exchange_auth_section):
+ Added a mnemonic to the Authentication Type label/dropdown
+
+2007-11-27 Matthew Barnes <mbarnes redhat com>
+
+ ** Fixes part of bug #495123
+
+ * exchange-mail-send-options.c (append_to_header):
+ Use e_msg_composer_hdrs_get_from_account() to obtain the EAccount.
+
+2007-11-23 Milan Crha <mcrha redhat com>
+
+ ** Fix for bug #479081
+
+ * exchange-account-setup.c: (org_gnome_exchange_owa_url):
+ Check for input validity immediately after creating setup widgets.
+
+2007-11-14 Matthew Barnes <mbarnes redhat com>
+
+ * exchange-folder.c (ex_create_folder_info):
+ Call camel_folder_info_new() instead of g_new0().
+
+2007-10-26 Kjartan Maraas <kmaraas gnome org>
+
+ * exchange-account-setup.c: (org_gnome_exchange_settings),
+ (print_error), (set_oof_info), (destroy_oof_data):
+ * exchange-delegates-user.c: (exchange_delegates_user_edit):
+ * exchange-mail-send-options.c: (append_to_header):
+ Warning fixes:
+ - mark some code static
+ - use non-deprecated GSignal apis
+ - rename shadowing variable
+
+2007-10-09 Matthew Barnes <mbarnes redhat com>
+
+ ** Fixes part of bug #437579
+
+ * exchange-user-dialog.c:
+ Fix various compiler warnings. Patch from Milan Crha.
+
+2007-10-02 Matthew Barnes <mbarnes redhat com>
+
+ ** Fixes part of bug #469657
+
+ * exchange-folder-size-display.c:
+ Use destroy functions in GHashTables to simplify memory management.
+
+2007-09-27 Matthew Barnes <mbarnes redhat com>
+
+ ** Fixes part of bug #477045
+
+ * exchange-folder-permission.c:
+ * exchange-folder.c:
+ Use standard icon names where applicable.
+
+2007-09-10 Srinivasa Ragavan <sragavan novell com>
+
+ ** Fix for bug #301044 (Novell Bugzilla)
+
+ * exchange-user-dialog.c: (e2k_user_dialog_get_user_list): Dont append
+ the comma from the Nameselector.
+
+2007-09-07 Milan Crha <mcrha redhat com>
+
+ ** Fix for bug #473903
+
+ * exchange-delegates.c: (email_look_up):
+ * exchange-mail-send-options.c: (append_to_header):
+ * exchange-delegates-user.c: (exchange_delegates_user_edit):
+ Fixes serious compiler warnings.
+
+2007-08-24 Srinivasa Ragavan <sragavan novell com>
+
+ * org-gnome-exchange-cal-subscription.xml: Fix for empty menu in the
+ UI.
+
+2007-08-20 Matthew Barnes <mbarnes redhat com>
+
+ * Makefile.am: Fix a distcheck error.
+
+2007-08-16 Milan Crha <mcrha redhat com>
+
+ ** Fix for bug #466548
+
+ * exchange-mail-send-options.c: (org_gnome_exchange_send_options):
+ e_msg_composer_get_preferred_account can return NULL, so test for it.
+
+2007-08-10 Milan Crha <mcrha redhat com>
+
+ ** Fix for bug #327977
+
+ * exchange-account-setup.c: (owa_authenticate_user):
+ Pass parent window to call of e2k_validate_user.
+
+2007-07-31 Veerapuram Varadhan <vvaradhan novell com>
+
+ * exchange-delegates-user.c: (exchange_delegates_user_edit):
+ Generate HTML content for permission-summary mail, instead of
+ ascii-text content. This is required to align strings in a table.
+
+ Committing on behalf of Bharath Acharya <abharath novell com>
+
+2007-07-30 Andre Klapper <a9016009 gmx de>
+
+ * exchange-permissions-dialog.glade:
+ remove "window1" string from translation
+
+2007-07-30 Chenthill Palanisamy <pchenthill novell com>
+
+ * exchange-delegates-user.c: (map_to_full_role_name),
+ (exchange_delegates_user_edit): Added the translation comments
+
+ Committing on behalf of Bharath Acharya <abharath novell com>
+
+2007-07-26 Hiroyuki Ikezoe <poincare ikezoe net>
+
+ ** Fix for bug #458511
+
+ * exchange-delegates-user.c: (exchange_delegates_user_edit): each
+ message is enclosed with double quotes line by line.
+
+2007-07-12 Matthew Barnes <mbarnes redhat com>
+
+ * exchange-delegates-user.c:
+ Fix a bunch of new implicit function declarations.
+
+2007-07-09 Chenthill Palanisamy <pchenthill novell com>
+
+ reviewed by: Veerapuram Varadhan <vvaradhan novell com>
+
+ * exchange-delegates-user.c: (map_to_full_role_name),
+ (em_utils_delegates_done), (exchange_delegates_user_edit):
+ * exchange-delegates-user.h:
+ * exchange-delegates.c: (add_button_clicked_cb),
+ (edit_button_clicked_cb), (email_look_up), (table_click_cb):
+ * exchange-delegates.glade:
+ * exchange-delegates.h:
+ * exchange-mail-send-options.c: (append_to_header):
+ * exchange-send-options.c:
+ (exchange_send_options_get_widgets_data), (get_widgets),
+ (exchange_send_options_fill_widgets_with_data),
+ (exchange_send_options_cb), (delegate_option_toggled),
+ (addressbook_dialog_response), (addressbook_entry_changed),
+ (address_button_clicked), (exchange_sendoptions_dialog_run),
+ (exchange_sendoptions_dialog_init):
+ * exchange-send-options.glade:
+ * exchange-send-options.h:
+ * org-gnome-exchange-operations.error.xml: Added the exchange
+ delegation support.
+
+ Committing on behalf of Bharath Acharya <abharath novell com>
+
+2007-07-03 Srinivasa Ragavan <sragavan novell com>
+
+ * exchange-account-setup.c: (owa_authenticate_user): Form the password
+ url same as what is used every where else, so that the query can be
+ avoided.
+
+2007-06-07 Gilles Dartiguelongue <dartigug esiee fr>
+
+ * exchange-mail-send-options.c: (org_gnome_exchange_send_options):
+ more compilation warnings cleanup, completes bug #437584 fixes
+
+2007-06-11 Milan Crha <mcrha redhat com>
+
+ ** Fix for bug #325882
+
+ * exchange-folder-tree.glade:
+ * exchange-oof.glade:
+ * e-foreign-folder-dialog.glade:
+ * exchange-passwd-expiry.glade:
+ Changed GTK_WIN_POS_NONE to GTK_WIN_POS_CENTER_ON_PARENT.
+
+2007-06-03 Srinivasa Ragavan <sragavan novell com>
+
+ ** Fix for bug #386503 from Matthew Barnes
+
+ * exchange-send-options.c: (exchange_send_options_cb):
+
+2007-05-25 Matthew Barnes <mbarnes redhat com>
+
+ * exchange-config-listener.c (exchange_add_autocompletion_folders):
+ Don't assume the absolute URI is non-NULL (#427232).
+
+2007-05-11 Gilles Dartiguelongue <dartigug esiee fr>
+
+ * exchange-folder.c: (org_gnome_exchange_folder_inbox_unsubscribe):
+ Fixes unhandled cases in switch, fixes part of bug #437584.
+
+2007-05-25 Veerapuram Varadhan <vvaradhan novell com>
+
+ * Makefile.am: Distcheck fixes.
+
+2007-04-10 Elizabeth Greene <nerdygirl_ellie yahoo com>
+
+ ** Fixes #426481
+ * exchange-account-setup.c: Fix Typo Assitant
+
+2007-04-05 Matthew Barnes <mbarnes redhat com>
+
+ * exchange-config-listener.c (class_init):
+ * exchange-delegates-user.c (class_init):
+ Use GLib marshallers wherever possible.
+
+2007-03-27 Matthew Barnes <mbarnes redhat com>
+
+ * exchange-account-setup.c:
+ * exchange-calendar.c:
+ * exchange-config-listener.c:
+ * exchange-contacts.c:
+ Don't mix declarations and code (#405495).
+
+2007-03-20 Matthew Barnes <mbarnes redhat com>
+
+ ** Fixes part of bug #419524
+
+ * Include <glib/gi18n.h> instead of <libgnome/gnome-i18n.h>.
+
+2007-01-27 Nickolay V. Shmyrev <nshmyrev yandex ru>
+
+ * exchange-account-setup.c:
+ (org_gnome_exchange_show_folder_size_factory):
+ * exchange-contacts.c: (e_exchange_contacts_pcontacts):
+ mark strings as translatable. See bug #399381 for details.
+
+2006-01-18 Raghavendran R <raghavguru7 gmail com>
+
+ * exchange-send-options.glade :Glade file for
+ exchange send options .
+ * org-gnome-exchange-operations.eplug.xml :Added a
+ hook for implementing send options .
+ * exchange-mail-send-options.c :Contains code for invoking
+ the dialog and processing the data received and destroying
+ the dialog .
+ * exchange-send-options.[c,h] :Contains the GType for exchange
+ send options dialog .
+
+2006-12-18 Veerapuram Varadhan <vvaradhan novell com>
+
+ Fixes bnc #208395
+
+ * exchange-folder-permission.c:
+ (org_gnome_exchange_folder_permissions): Decode the derived path
+ using camel_url_decode_path(), as path may contain encoded
+ characters.
+
+2006-12-04 Matthew Barnes <mbarnes redhat com>
+
+ Fixes bug #357970
+
+ * exchange-config-listener.c: Don't call deprecated GLib / GDK
+ functions.
+
+2006-10-23 Priit Laes <amd store20 com>
+
+ * org-gnome-default-source.eplug.xml: Fixed typo in plugin
+ description. Fixes bug 363999.
+
+2006-08-07 Sushma Rai <rsushma novell com>
+
+ * org-gnome-exchange-operations.error.xml: Corrected a spelling
+ mistake in the error message. Fixes #350231.
+
+2006-07-24 Sushma Rai <rsushma novell com>
+
+ * exchange-folder-subscription.c (subscribe_to_folder): Handling the
+ errors EXCHANGE_ACCOUNT_FOLDER_GC_NOTREACHABLE and
+ EXCHANGE_ACCOUNT_FOLDER_NO_SUCH_USER.
+
+ * org-gnome-exchange-operations.error.xml: Added an error code
+ folder-no-gc-error and corresponding error string. Fixes #234359.
+
+2006-07-22 Sushma Rai <rsushma novell com>
+
+ * exchange-folder-subscription.c (subscribe_to_folder): Checking if a
+ user is subscribing to his own folder. Fixes #311322.
+ Patch submitted by "Vandana Shenoy .B <shvandana novell com>"
+
+2006-07-18 Andre Klapper <a9016009 gmx de>
+
+ * exchange-change-password.glade:
+ remove "*" from translation. Fixes bug #331147.
+
+2006-07-13 Andre Klapper <a9016009 gmx de>
+
+ * exchange-permissions-dialog.glade: remove empty strings from
+ translation
+
+2006-07-07 Hiroyuki Ikezoe <poincare ikezoe net>
+
+ ** Fixes bug #341369
+ * exchange-calendar.c:
+ * exchange-contacts.c: fixing a memory leak.
+
+2006-06-15 Sushma Rai <rsushma novell com>
+
+ * Makefile.am: Added exchange-oof.glade to the list of glade files.
+
+ * exchange-config-listener.c (exchange_config_listener_authenticate):
+ On successful connection, checking if the OOF state is set in the
+ server, and if it is set, asking the user if he wants to change it
+ to in-office during login. Fixes #344650.
+
+2006-06-13 Sushma Rai <rsushma novell com>
+
+ * org-gnome-exchange-operations.error.xml: defined a new error code and
+ error string, for displaying in offline state.
+
+ * exchange-folder.c (org_gnome_exchange_folder_ab_unsubscribe): Display
+ proper error in offline mode.
+ (org_gnome_exchange_folder_unsubscribe): Similar.
+ (org_gnome_exchange_folder_subscription): Similar.
+ Fixes #344270.
+
+2006-06-07 Sushma Rai <rsushma novell com>
+
+ * exchange-folder-subscription.c (create_folder_subscription_dialog):
+ Disabling the OK button and added a callback to change the sensitivity.
+ (user_name_entry_changed_callback): Call-back to enable OK button, on
+ entering username. Fixes #317025.
+
+2006-05-11 Sankar P <psankar novell com>
+
+ * exchange-account-setup.c: (btn_chpass_clicked):
+ Do not print the password in the terminal.
+
+2006-05-10 Sushma Rai <rsushma novell com>
+
+ * exchange-config-listener.c (account_changed): Using the HIGified
+ notification message.
+
+ * org-gnome-exchange-operations.error.xml: Similar,
+ Fixes #302825.
+
+2006-05-10 Sushma Rai <rsushma novell com>
+
+ * exchange-account-setup.c (owa_authenticate_user): Display error
+ message only in case of authentication failure and not on cancelling
+ authentication operation. Fixes #332131
+
+2006-04-19 Sushma Rai <rsushma novell com>
+
+ * exchange-contacts.c (e_exchange_contacts_commit): Setting the
+ e-source properties on both successful creation and rename of a folder.
+
+ * exchange-calendar.c (e_exchange_calendar_commit): Similar.
+ Fixes #338876 and #328578.
+
+2006-04-19 Sushma Rai <rsushma novell com>
+
+ * exchange-account-setup.c (owa_authenticate_user): Changed the
+ function signature. Fixes #329371.
+
+2006-04-17 Sushma Rai <rsushma novell com>
+
+ * exchange-contacts.c (e_exchange_contacts_check): Return TRUE in case
+ of non-exchange accounts.
+
+ * exchange-calendar.c (e_exchange_calendar_check): Similar.
+ Fixes #338198.
+
+2006-04-10 Sushma Rai <rsushma novell com>
+
+ * exchange-operations.[ch] (is_exchange_personal_folder): Added new to
+ check if a folder is a personal folder or not.
+
+ * exchange-contacts.c (e_exchange_contacts_pcontacts): Printing the
+ folder size only for the personal folders, in properties window.
+ (e_exchange_contacts_check): Returning FALSE in case of rename of
+ non-personal folders.
+ (e_exchange_contacts_commit): Renaming only the personal folders.
+
+ * exchange-calendar.c (e_exchange_calendar_pcalendar)
+ (e_exchange_calendar_check)(e_exchange_calendar_commit): Similar.
+ Fixes #328813 and #315522.
+
+2006-04-06 Sushma Rai <rsushma novell com>
+
+ * exchange-operations.c (exchange_operations_update_child_esources):
+ Checking for ruri NULL.
+
+ * exchange-folder.c (org_gnome_exchange_check_address_book_subscribed):
+ Freeing uri.
+
+ * exchange-contacts.c (e_exchange_contacts_get_contacts): Defined as
+ static.
+ (e_exchange_contacts_pcontacts): Setting contacts_src_exists for GAL
+ folder.
+ (e_exchange_contacts_check): Checking for new folder creation and also
+ not allowing rename of GAL and Contacts folders.
+ (e_exchange_contacts_commit): Corrected the way relative URI was being
+ constructed during rename operation. Handling the return value of the
+ rename operation.
+
+ * exchange-calendar.c (e_exchange_calendar_get_calendars): Defined as a
+ static function.
+ (e_exchange_calendar_check): Not allowing the rename of standard
+ calendar and tasks folders.
+ (e_exchange_calendar_commit): Corrected the way relative URI was being
+ formed during rename operation. Also, handling the return value of the
+ rename folder operation.
+ Fixes #310433.
+
+2006-03-06 Sushma Rai <rsushma novell com>
+
+ * exchange-config-listener.c
+ (exchange_config_listener_get_offline_status): Freeing GConfValue.
+ See #329251.
+
+2006-03-06 Sushma Rai <rsushma novell com>
+
+ * exchange-config-listener.c (account_removed): Not unrefing the
+ account passed to the signal handler. Fixes #332129.
+
+2006-02-27 Sushma Rai <rsushma novell com>
+
+ * exchange-calendar.c (e_exchange_calendar_pcalendar): fixed a typo.
+
+2006-02-27 Sushma Rai <rsushma novell com>
+
+ * exchange-contacts.c (e_exchange_contacts_pcontacts): Check for NULL
+ account.
+
+ * exchange-calendar.c (e_exchange_calendar_pcalendar): Similar.
+ Fixes #332185.
+
+2006-02-27 Sushma Rai <rsushma novell com>
+
+ * exchange-folder-permission.c
+ (org_gnome_exchange_calendar_permissions): Trying to get the exchange
+ account only if one tries to see the folder permissions for the
+ exchange account. Also, not showing the folder permissions dialog if
+ the account is in offline mode.
+ (org_gnome_exchange_addressbook_permissions): Similar.
+ (org_gnome_exchange_folder_permissions): similar.
+ (org_gnome_exchange_menu_folder_permissions): Similar.
+ (org_gnome_exchange_menu_cal_permissions): Similar.
+ (org_gnome_exchange_menu_tasks_permissions): Similar.
+ (org_gnome_exchange_menu_ab_permissions): Similar.
+ See #332514.
+
+2006-02-27 Sushma Rai <rsushma novell com>
+
+ * exchange-config-listener.c (add_defaults_for_account): Not trying to
+ set autocompletion folders here, which is done somewhere else.
+ (account_added): Invoking add_defaults_for_account() always on
+ "connected" signal, not only if the account is marked as default
+ folder, as we need to set them even if the account is not an default
+ account.
+ (set_special_mail_folder): Fomring the URIs for sent items and drafts
+ folders, by removing the ";" from the physical URIs.
+ Fixes #324693, #324694.
+
+2006-02-25 Sushma Rai <rsushma novell com>
+
+ * exchange-contacts.c (e_exchange_contacts_get_contacts): Freeing
+ folder array.
+
+ * exchange-calendar.c (e_exchange_calendar_get_calendars): Similar.
+ See #329251.
+
+2006-02-18 Irene Huang <Irene Huang sun com>
+
+ Fixes bug #331635
+
+ * exchange-account-setup.c: (org_gnome_exchange_settings):
+ Add NULL as the last parameter in g_object_new to mark the
+ the end of parameter list.
+
+2006-02-10 Sushma Rai <rsushma novell com>
+
+ * exchange-contacts.c (e_exchange_contacts_pcontacts): Checking if the
+ folder selected is GAL folder and in case of GAL folder, returning
+ after checking for offline status.
+ (e_exchange_contacts_check): Handling GAL folder also.
+ Fixes #329623 #328571 and #329624
+
+2006-02-10 Sushma Rai <rsushma novell com>
+
+ * exchange-contacts.c (e_exchange_contacts_commit): Freeing uri_text.
+ See #329251.
+
+2006-02-06 Sushma Rai <rsushma novell com>
+
+ * exchange-permissions-dialog.c (exchange_permissions_dialog_new):
+ Initializing nresults to zero and freeing E2kResult.
+
+ * exchange-calendar.c (e_exchange_calendar_commit): Freeing authtype.
+
+ * exchange-contacts.c (e_exchange_contacts_commit): Similar.
+ See #329251.
+
+2006-02-05 Karsten Bräckelmann <guenther rudersport de>
+
+ * exchange-user-dialog.c (e2k_user_dialog_construct):
+ Correcting "Addressbook" to properly read "Address Book".
+ Fixes bug #326256.
+
+2006-02-03 Sushma Rai <rsushma novell com>
+
+ * exchange-permissions-dialog.c (exchange_permissions_dialog_new):
+ Freeing E2kResult.
+
+ * exchange-calendar.c (e_exchange_calendar_commit): Freeing authtype.
+
+ * exchange-contacts.c (e_exchange_contacts_commit): similar.
+ See #329251.
+
+2006-02-03 Sushma Rai <rsushma novell com>
+
+ * exchange-folder.c (org_gnome_exchange_folder_subscription): Moved
+ discovering the shared folder, opening that folder and error handling
+ out to create_folder_subscription_dialog().
+
+ * exchange-folder-subscription.c (create_folder_subscription_dialog):
+ Pass all the data to subscirbe_to_folder() callback.
+ (subscribe_to_folder): On pressing OK, extracting the dtails like user's
+ email id, folder name, finding the shared folder and opening that
+ folder.
+ (destroy_subscription_info): Cleanup function.
+ Fixes #328554.
+
+2006-01-27 Sushma Rai <rsushma novell com>
+
+ * exchange-calendar.c (e_exchange_calendar_commit): Freeing uri_text
+ in case of OFFLINE mode.
+ Instead of terminating memory allocated string tmpruri and using it,
+ forming the URI string from the EUri and appending the path.
+
+ * exchange-contacts.c (e_exchange_contacts_commit): Similar.
+ Fixes #328304.
+
+2006-01-24 Sushma Rai <rsushma novell com>
+
+ * exchange-config-listener.c (exchange_config_listener_authenticate):
+ Not using e_error_run(), to avoid modal error dialogs. Fixes #328385.
+
+ * exchange-operations.c (exchange_operations_report_error): Similar.
+ Also displaying the current quota usage instead of the quota limit.
+
+2006-01-23 Sushma Rai <rsushma novell com>
+
+ * exchange-operations.c
+ (exchange_operations_cta_select_node_from_tree): Checking for the NULL
+ URI, Fixes #328282.
+
+2006-01-23 Sushma Rai <rsushma novell com>
+
+ * exchange-account-setup.c (camel_exchange_ntlm): Setting the authproto
+ value to NTLM, which is used later.
+ (org_gnome_exchange_auth_section): Reading the auth type from
+ ExchangeAccount and setting it in URL if the url doesn't contain the
+ auth mechanism value. Since the auth mechanism is not set using the
+ authentication type tab in druid during account setup, when the editor
+ is invoked, it doesn't get set in the account URI. Fixes #327284.
+
+2006-01-19 Andre Klapper <a9016009 gmx de>
+
+ * org-gnome-exchange-operations.error.xml:
+ changed "mails" to "mail" or "messages", removed duplicated
+ whitespaces. Fixes bug 325569.
+
+2006-01-18 Sushma Rai <rsushma novell com>
+
+ * exchange-contacts.c (e_exchange_contacts_pcontacts): Displaying the
+ offline message for both Exchange personal and GAL folders.
+ Fixes #327483.
+
+2006-01-16 Harish Krishnaswamy <kharish novell com>
+
+ * org-gnome-exchange-operations.error.xml:
+ Fixed a minor typo in error string. (#327053).
+
+2006-01-16 Harish Krishnaswamy <kharish novell com>
+
+ * exchange-config-listener.c: (display_passwd_expiry_message):
+ Fix a grammar error in translatable string. (#327155)
+
+2006-01-13 Sushma Rai <rsushma novell com>
+
+ * exchange-config-listener.c (exchange_config_listener_authenticate):
+ Set the "save-passwd" parameter value EAccount. Fixes #326842.
+
+2006-01-13 Sushma Rai <rsushma novell com>
+
+ * exchange-config-listener.c: Added krb5 checks while invoking
+ change_passwd_cb() and exchange_config_listener_authenticate().
+
+2006-01-11 Chenthill Palanisamy <pchenthill novell com>
+
+ Fixes #271546
+ * exchange-folder.c: (org_gnome_exchange_calendar_subscription),
+ (org_gnome_exchange_addressbook_subscription),
+ (org_gnome_exchange_tasks_subscription),
+ (org_gnome_exchange_inbox_subscription): Mark the string for completion.
+
+2006-01-12 Sushma Rai <rsushma novell com>
+
+ * exchange-config-listener.c (exchange_config_listener_authenticate):
+ Checking for the password expired error code during connect and if the
+ password is expired, showing the error message, prompting for resetting
+ the password and trying to connect again with the new password.
+ Checking if the password will expire in next a few days, which is
+ specified by the user during account creation, and if yes, showing
+ the corresponding error message to the user, which allows him to change
+ his password.
+ Fixes #326060.
+ Also, Checking for the quota related error codes and displaying the
+ corresponding error/warning messages to the user. Fixes #326087.
+
+ * org-gnome-exchange-operations.error.xml: Added a space.
+
+ * exchange-passwd-expiry.glade: Added new.
+
+ * Makefile.am: Added exchange-passwd-expiry.glade.
+
+2006-01-11 Srinivasa Ragavan <sragavan novell com>
+
+ ** Fixes bug #316100
+
+ * org-gnome-exchange-ab-subscription.xml:
+ * org-gnome-exchange-tasks-subscription.xml:
+ * org-gnome-folder-permissions.xml:
+ * org-gnome-folder-subscription.xml:
+ Removed empty menu entry which was pointing to Tools menu.
+
+2006-01-09 Sushma Rai <rsushma novell com>
+
+ * exchange-folder-subscription.c (create_folder_subscription_dialog):
+ Instead of gtk_dialog_run(), calling gtk_widget_show().
+ (dialog_destroy): Added callback to do the cleanup on closing the
+ window. Fixes #314748.
+
+2006-01-06 Simon Zheng <simon zheng sun com>
+
+ * exchange-account-setup.c:
+ * exchange-calendar.c:
+ * exchange-config-listener.h:
+ * exchange-contacts.c:
+ use libedataserver/e-account-list.h instead of e-util/e-account-list.h.
+ use libedataserver/e-account.h instead of e-util/e-account.h.
+
+2006-01-05 Sushma Rai <rsushma novell com>
+
+ * exchange-calendar.c (e_exchange_calendar_commit): Setting the
+ username, authtype, auth-domain and auth properties on the esource
+ created, so that corresponding folder will be authenticated and loaded
+ after the folder creation. Also fixed memory leak in case of no any
+ changes condition.
+
+ * exchange-config-listener.c (remove_selected_non_offline_esources):
+ Not freeing the non allocated string offline_mode.
+
+2006-01-02 Sushma Rai <rsushma novell com>
+
+ * exchange-folder-permission.c (org_gnome_exchange_folder_permissions):
+ Proceed only with the exchange account folders.
+
+ * exchange-folder.c (org_gnome_exchange_check_inbox_subscribe):
+ Similar. Fixes #325491.
+
+2005-12-30 Andre Klapper <a9016009 gmx de>
+
+ * evolution/plugins/exchange-operations/org-gnome-exchange-operations.error.xml:
+ Fixing several typos and harmonizing
+ capital/small letters. Partially fixes bug 306117.
+
+2005-12-30 Andre Klapper <a9016009 gmx de>
+
+ * evolution/plugins/exchange-operations/exchange-account-setup.c:
+ harmonized "URL", "Url" and "url". Fixes bug 325125.
+
+2005-12-25 Funda Wang <fundawang linux net cn>
+
+ * Makefile.am: Mark this plugin as translatable (bug#301149).
+
+2005-12-21 Sushma Rai <rsushma novell com>
+
+ * exchange-contacts.c (e_exchange_contacts_commit): Setting the
+ username, authtype, auth-domain and auth properties on the esource
+ created, so that corresponding folder will be authenticated and loaded
+ after the folder creation. Fixes #324678.
+ Also fixed memory leak in case of no any changes condition.
+
+2005-12-20 Sushma Rai <rsushma novell com>
+
+ * exchange-folder-subscription.c (create_folder_subscription_dialog):
+ Setting the correct title. Fixes #324580.
+
+2005-12-19 Sushma Rai <rsushma novell com>
+
+ * exchange-delegates-user.c (exchange_delegates_user_edit): Using the
+ window title as "Delegates Permissions". Label "Permissions for <user>"
+ was repeated twice.
+
+ * exchange-delegates.glade: Added translator comments. Fixes #313545.
+
+2005-12-19 Sushma Rai <rsushma novell com>
+
+ * exchange-account-setup.c (owa_authenticate_user): Adding the
+ parameter "save-passwd" to CamelURL, during account creation, which can
+ be used to see if the user has remembered password or password is
+ temporarily remembered so that password is not prompted second time at
+ the end of account creation.
+
+ * exchange-config-listener.c (exchange_config_listener_authenticate):
+ Using the flag E_PASSWORDS_REMEMBER_FOREVER instead of
+ E_PASSWORDS_REMEMBER_SESSION. Reading the save-passwd URL parameter to
+ see if the password was remembered by the user or remembered
+ temporarily by the plugin and foget it in case of remembered by the
+ plugin. Also free CamelURL.
+ (account_added): Calling exchange_config_listener_authenticate().
+
+ Fixes #324485
+
+2005-12-19 Sushma Rai <rsushma novell com>
+
+ * exchange-account-setup.c (org_gnome_exchange_settings)
+ (owa_editor_entry_changed)(org_gnome_exchange_owa_url)
+ (org_gnome_exchange_commit): free CamelURL.
+ (owa_authenticate_user): free CamelURL and exchange_params.
+ Fixes #324483.
+
+2005-12-19 Sushma Rai <rsushma novell com>
+
+ * exchange-folder-permission.c: Corrected include path of header files
+ which was breaking the build.
+
+ * exchange-change-password.[ch]: Similar.
+
+ * exchange-folder-subscription.c: Similar.
+
+2005-12-12 Sushma Rai <rsushma novell com>
+
+ * exchange-account-setup.c (print_error): Passing the support URL to
+ e_error_run(), so that hardcoded URL won't be marked for translation.
+ See #272514.
+ * org-gnome-exchange-operations.error.xml: Uisng the correct error code
+ "connect-exchange-error". Changed the primary message to more
+ appropriate one. Also removed hard coded URL.
+
+2005-12-12 Harish Krishnaswamy <kharish novell com>
+
+ * Makefile.am: Add primary CLEANFILES,
+ fix BUILT_SOURCES, make-clean issues.
+
+2005-12-07 Funda Wang <fundawang linux net cn>
+
+ * org-gnome-exchange-operations.eplug.in: i18nlized.
+
+2005-11-24 Sushma Rai <rsushma novell com>
+
+ * exchange-account-setup.c (org_gnome_exchange_settings): Initialize
+ OOF state and check for the OOF state and message only of the account
+ is valid. Fixes the problem of printing OOF error message in case
+ of authentication failure.
+ (set_oof_info): Similar.
+ Fixes #314583, #315331.
+
+2005-10-03 Shakti Sen <shprasad novell com>
+
+ * exchange-folder-permission.c (org_gnome_exchange_folder_permissions),
+ (org_gnome_exchange_menu_folder_permission): Constructing the path
+ properly to get the efolder.
+ * exchange-folder.c (org_gnome_exchange_folder_inbox_unsubscribe),
+ (exchange_get_folder), (org_gnome_exchange_check_inbox_subscribed),
+ (unsubscribe_dialog_ab_response), (unsubscribe_dialog_response):
+ Creating proper path.
+
+ The above modifications will now allow the user to do the operations
+ like unsubscribed to Inbox and giving permission to a folder.
+ -
+
+2005-09-30 Shakti Sen <shprasad novell com>
+
+ * exchange-folder-subscription.c (setup_folder_name_combo): Sets the
+ corresponding 'Folder name'.
+ (create_folder_subscription_dialog): Sets the cursor to User's entry
+ text field.
+ * exchange-folder-subscription.h: Added one more argument to function
+ create_folder_subscription_dialog() to set the window title.
+ * exchange-folder.c (org_gnome_exchange_inbox_subscription),
+ (org_gnome_exchange_addressbook_subscription),
+ (org_gnome_exchange_calendar_subscription),
+ (org_gnome_exchange_tasks_subscription): Added newly.
+ * org-gnome-exchange-operations.eplug.in: Changed the activate callback
+ function names so that it can show appropriate window title.
+
+ Fixes bug #317019, #317023.
+
+2005-09-28 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * exchange-account-setup.c (owa_authenticate_user) : Propogate the
+ authentication mechanism to the backend.
+ * exchange-calendar.c
+ * exchange-contacts.c
+ * exchange-folder.c : Parse the new account uri.
+
+2005-09-28 Tor Lillqvist <tml novell com>
+
+ * Makefile.am (INCLUDES, LIBADD): Use just CAMEL_EXCHANGE_CFLAGS
+ and _LIBS, they now includes all necessary (see top-level
+ ChangeLog).
+ (LDFLAGS): Use NO_UNDEFINED.
+
+ * org-gnome-exchange-operations.eplug.in: Use SOEXT.
+
+2005-09-22 Praveen Kumar <kpraveen novell com>
+
+ ** Fixes bug 312849
+
+ * exchange-calendar.c
+ (e_exchange_calendar_pcalendar): Populate the folder hierarchy only
+ if Evolution is online.
+ (e_exchange_calendar_check): Disable the "OK" button if Evolution
+ is offline.
+ (e_exchange_calendar_commit): Don't do anything if Evolution is
+ offline.
+
+ * exchange-contacts.c
+ (e_exchange_contacts_pcontacts): Populate the folder hierarchy only
+ if Evolution is online.
+ (e_exchange_contacts_check): Disable the "OK" button if Evolution
+ is offline.
+ (e_exchange_contacts_commit): Don't do anything if Evolution is
+ offline.
+
+2005-09-15 Arunprakash <arunp novell com>
+
+ * exchange-account-setup.c
+ (org_gnome_exchange_show_folder_size_factory) : Now checks for the
+ camel provider type, and does nothing for non exchange providers.
+ ** Fixes #312886.
+
+2005-09-14 Irene Huang <Irene Huang sun com>
+
+ Fix for #316274
+
+ * exchange-account-setup.c: (btn_chpass_clicked),
+ (org_gnome_exchange_settings): Enable change password function only
+ when built with kerberos5.
+
+2005-08-29 Praveen Kumar <kpraveen novell com>
+
+ ** Fixes bug 314762
+
+ * exchange-config-listener.c (remove_selected_non_offline_esources) :
+ Fixing a nasty infinite loop by swapping an if and while block.
+
+2005-08-26 Shakti Sen <shprasad novell com>
+
+ * exchange-folder.c (org_gnome_exchange_folder_unsubscribe): Fixes the
+ 'Label disappears' problem in Tasks, Calendar and Contacts.
+
+ Fixes bug #311959.
+
+2005-08-25 Arunprakash <arunp novell com>
+
+ * exchange-config-listener.c (account_added) : Need to set the
+ account's linestatus to online as there is no way to get the
+ linestatus in plugin. Also moved the authentication code to
+ exchange_operations_get_exchange_account as it is not needed here.
+ * exchange-operations.c (exchange_operations_get_exchange_account) :
+ Updated to return the account in offline mode.
+
+2005-08-25 Shakti Sen <shprasad novell com>
+
+ * exchange-folder.c (exchange_refresh_folder_tree, exchange_get_folder,
+ org_gnome_exchange_folder_inbox_unsubscribe): Added support for
+ Unsubscribe to other user's Inbox.
+
+ Fixes bug #313310.
+
+2005-08-24 Shakti Sen <shprasad novell com>
+
+ * exchange-permissions-dialog.c (add_clicked): Getting list of mail-ids
+ instead of a single mail-id.
+ * exchange-user-dialog.[c/h] (e2k_user_dialog_get_user_list): Added
+ support for adding multiple IDs.
+
+ Fixes bug #313919.
+
+2005-08-24 Praveen Kumar <kpraveen novell com>
+
+ * plugins/exchange-operations/exchange-account-setup.c:
+ * plugins/exchange-operations/exchange-calendar.c:
+ * plugins/exchange-operations/exchange-config-listener.c:
+ * plugins/exchange-operations/exchange-contacts.c:
+ * plugins/exchange-operations/exchange-delegates-user.c:
+ * plugins/exchange-operations/exchange-folder-size-display.c:
+ * plugins/exchange-operations/exchange-folder.c:
+ * plugins/exchange-operations/exchange-operations.c:
+ Removed the warning that are generated when compiled with GCC 4.
+
+ * plugins/exchange-operations/exchange-calendar.c:
+ Fixed a build break due to the modification of the 'source_type'
+ field in the ECalConfigTargetSource class.
+
+2005-08-22 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * exchange-account-setup.c (btn_fsize_clicked)
+ (set_oof_info) : Use exchange_operations_get_exchange_account.
+ * exchange-config-listener.c (exchange_config_listener_authenticate) :
+ Fetch the password and connect. Added new
+ * exchange-config-listener.h : Similar.
+ * exchange-operations.c (exchange_operations_get_exchange_account) :
+ Try authenticating if account is not found.
+
+2005-09-12 Praveen Kumar <kpraveen novell com>
+
+ * exchange-config-listener.c
+ (remove_selected_non_offline_esources): Added new
+ (add_account_esources): Don't add the calendars and tasks in the
+ selected list
+ (account_added): If starting in offline mode remove the non-offline
+ calendars and tasks from the selected list so that it doesn't
+ throws an error
+
+ Fixes the bug 273272.
+
+2005-08-11 Praveen Kumar <kpraveen novell com>
+
+ * exchange-config-listener.c
+ (exchange_camel_urls_is_equal): Added new
+ (exchange_config_listener_modify_esource_group_name): Added new
+ (account_changed): Handle most of the account parameter changes
+ without restart. This fixes bug 272784 and partially bug 220168
+ (account_removed): Removed the message dialog that says that the
+ changes will be reflected after restart. This partially fixes the
+ bug 220168
+
+2005-08-08 Arunprakash <arunp novell com>
+
+ * exchange-folder-size-display.c: Included glib/gi18n.h file for
+ translation.
+ * exchange-operations.c: Same.
+
+2005-08-05 Arunprakash <arunp novell com>
+
+ * exchange-folder-size-display.c (exchange_folder_size_display) :
+ Marked strings for translation that were left out.
+ * exchange-operations.c (exchange_operations_cta_add_node_to_tree)
+ (exchange_operations_cta_select_node_from) : Same.
+
+2005-08-03 Shakti Sen <shprasad blr novell com>
+
+ * exchange-folder.c (org_gnome_exchange_folder_ab_unsubscribe)
+ (org_gnome_exchange_folder_unsubscribe)
+ (org_gnome_exchange_folder_subscription): Added offline/online support
+ and removed some warning messages.
+ * exchange-operations.c: Added a new function exchange_is_offline().
+ * exchange-operations.h: Included a prototype.
+ * exchange-config-listener.c
+ (exchange_config_listener_get_offline_status): Added newly to get the
+ online/offline status.
+ * exchange-config-listener.h: Added the prototype for
+ exchange_config_listener_get_offline_status().
+
+ Fixes bug #311324.
+
+2005-08-03 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * exchange-folder.c : Fixed a build break. A typo.
+
+2005-08-02 Shakti Sen <shprasad blr novell com>
+
+ * Makefile.am: Included 'calendar' in INCLUDES and some .la in
+ 'liborg_gnome_exchange_operations_la_LIBADD'
+ * exchange-folder-permission.c: Added the functionality for
+ 'File->Permissions' menu-item for Calendar, Tasks and Contacts.
+ * exchange-permissions-dialog.c (exchange_permissions_dialog_new):
+ Takes care of 'folder' is not-null.
+
+ Fixes bug #231968.
+
+2005-08-02 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * exchange-calendar.c : Check for NULL target
+ * exchange-contacts.c : Similar
+ * exchange-folder-permission.c : Similar
+ * exchange-folder.c : Similar
+
+2005-08-01 Praveen Kumar <kpraveen novell com>
+
+ * exchnage-config-listener.c
+ (exchange_add_autocompletion_folders) : Added new
+ (add_defaults_for_account) : Added a call to the newly added function
+ to select GAL for autocompletion by default. Fixes bug 303998
+
+2005-07-27 Praveen Kumar <kpraveen novell com>
+
+ * exchange-folder.c (org_gnome_exchange_folder_subscription) : Handle
+ error conditions if folder subscription fails. Fixes bug 311712
+
+2005-07-27 Harry Lu <harry lu sun com>
+
+ Only show the unsubscribe menu if it is an exchange folder.
+ * exchange-folder.c:
+ (org_gnome_exchange_check_address_book_subscribed),
+ (org_gnome_exchange_check_subscribed):
+
+2005-07-25 Shakti Sen <shprasad novell com>
+
+ * org-gnome-exchange-operations.eplug.in: Fixed a small typo.
+ The file name is org-gnome-exchange-tasks-subscription.xml, not
+ org-gnome-exchange-task-subscription.xml.
+
+2005-07-25 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * exchange-calendar.c (e_exchange_calendar_pcalendar) : Add the size
+ label only if the calendar exists.
+ * exchange-contacts.c (e_exchange_contacts_pcontacts) : Add the size
+ label only if the addressbook exists.
+
+2005-07-25 Shakti Sen <shprasad novell com>
+
+ * Makefile.am: Added EVOLUTION_CALENDAR_CFLAGS and widgets in 'INCLUDES'.
+ * org-gnome-exchange-operations.eplug.in: Added the hooks for Calendar,
+ Tasks and Contacts.
+ * exchange-folder-permission.c: Added new functions to support
+ 'File->Permissions' for all the components.
+ * org-gnome-folder-permissions.xml: Changed the placeholder from 'Folder'
+ to 'File' menu for 'Permissions' menu-item.
+
+ Fixes bug #231968 (Partly).
+
+2005-07-25 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * exchange-account-setup.c
+ (org_gnome_exchange_show_folder_size_factory): Takes care of displaying
+ the folder size for mail folders.
+ * exchange-calendar.c (e_exchange_calendar_pcalendar): Now also adds
+ the calendar size in the properties page
+ * exchange-contacts.c (e_exchange_contacts_pcontacts): Now also adds
+ the addressbook size in the properties page.
+ * exchange-folder-size-display.c (exchange_folder_size_get_val) : Fetch
+ the folder size of a particular exchange folder.
+ * exchange-folder-size-display.h : Similar
+ * org-gnome-exchange-operations.eplug.in : Added the hook for the mail
+ properties page.
+
+2005-07-25 Arunprakash <arunp novell com>
+
+ * exchange-delegates.c (get_folder_security) (add_button_clicked_cb)
+ (delegates_apply) : Changed the e_notice calls to e_error_run calls.
+ * exchange-folder-permission.c (create_folder_subscription_dialog) :
+ Same.
+ * exchange-calendar.c (e_exchange_calendar_commit) : Same.
+ * exchange-contacts.c (e_exchange_contacts_commit) : Same.
+ * exchange-folder-subscription.c (create_folder_subscription_dialog) :
+ Same
+ * exchange-permissions-dialog.c (exchange_permissions_dialog_new)
+ (dialog_response) (add_clicked): Same.
+ * exchange-operations.c (exchange_operations_report_error) : Modified
+ to report the quota value to the user.
+ * org-gnome-exchange-operations.error.xml : Added few more
+ error descriptions needed for the above changes.
+
+2005-07-25 Shakti Sen <shprasad novell com>
+
+ * exchange-permissions-dialog.c (add_clicked): Creating the dialog
+ and getting the user.
+
+ Fixes bug #311096.
+
+2005-07-20 Shakti Sen <shprasad novell com>
+
+ * Makefile.am: Included files org-gnome-exchange-ab-subscription.xml,
+ org-gnome-exchange-tasks-subscription.xml and
+ org-gnome-exchange-cal-subscription.xml.
+ * org-gnome-exchange-ab-subscription.xml: Added newly to add
+ "Subscribe to Other User's Contacts' menu-item in 'File' menu for
+ address book.
+ * org-gnome-exchange-tasks-subscription.xml: Same for 'Tasks'.
+ * org-gnome-exchange-cal-subscription.xml: Same for 'Calendar'.
+
+ Fixes bug #310985.
+
+2005-07-22 Praveen Kumar <kpraveen novell com>
+
+ * exchange-calendar.c : Handling the rename of calendars. This
+ addresses the bug 310433
+ * exchange-config-listener.c : Removed the functions
+ add_folder_esource and remove_folder_esource
+ * exchange-contacts.c : Handling the rename of addressbooks. Also
+ modified the way of Exchange addressbook ESource URI handling to be
+ the same way as calendar ESource URI handling
+ * exchange-operations.c (exchange_operations_update_child_esources) :
+ Added new to handle the rename of the ESources of all child folders
+ in the case of parent folder being renamed.
+ * exchange-operations.h : Added prototype for the new function
+
+2005-07-21 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * exchange-calendar.c (e_exchange_calendar_get_calendars): Rescan the
+ tree before fetching the folder list.
+ * exchange-contacts.c (e_exchange_contacts_get_contacts): Similar
+ * exchange-config-listener.c (account_added): Dont add the sources here
+ now. Its now taken care while the folders are being created in e-d-s.
+ * exchange-folder.c (org_gnome_exchange_folder_subscription): Dont add
+ the esources here.
+
+2005-07-19 Shakti Sen <shprasad novell com>
+
+ * exchange-permissions-dialog.c (display_role, get_widgets):
+ Added a label named 'Custom' to show appropriate role in the 'Role:'
+ combo box.
+
+ Fixes bug#310837
+
+2005-07-18 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * exchange-folder-size-display.c (parent_destroyed) : This is no longer
+ needed. gtk_widget_destroy will take care of destroying it.
+ Fixes #310699
+ * exchange-account-setup.c (org_gnome_exchange_settings) : Fixed a
+ warning. Alignment cannot be set for a radio button
+
+2005-07-15 Shakti Sen <shprasad novell com>
+
+ * exchange-folder-permission.c: Added the functions
+ org_gnome_exchange_calendar_permissions() and
+ org_gnome_exchange_addressbook_permissions() to support
+ 'Folder Permissions' for 'Calendar', 'Tasks' and 'Contacts' components.
+ Also taken care of a bug #310493.
+ * org-gnome-exchange-operations.eplug.in: Added the class hooks.
+
+ Fixes bug#310479.
+ Fixes bug#310493 as well.
+
+2005-07-18 Praveen Kumar <kpraveen novell com>
+
+ * exchange-account-setup.c (btn_chpass_clicked) : Handle the case
+ of user clicking "Cancel" button in "Change Password" dialog. Fixes
+ bug 310356.
+ (org_gnome_exchange_setting) : Removed the duplicate signal handler
+ registered for "Change Password" button.
+
+2005-07-16 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * exchange-ask-password.c : Removed. Is no longer being used
+
+2005-07-15 Shakti Sen <shprasad novell com>
+
+ * Makefile.am: Included the e-foreign-folder-dialog.glade file.
+ * e-foreign-folder-dialog.glade: Added newly.
+
+ Fixes bug #310369.
+
+2005-07-14 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * exchange-account-setup.c :
+ * exchange-calendar.c :
+ * exchange-folder-size-display.c :
+ * exchange-permissions-dialog.c : Fixed some compile time warnings
+
+2005-07-13 Shakti Sen <shprasad novell com>
+
+ * exchange-operations.c: Checked for if the exchange account
+ exist/configured.
+ * exchange-folder-permission.c: Replaced all the occurences of function
+ exchange_config_listener_get_accounts() with
+ exchange_operations_get_exchange_account() and returns if it doesn't
+ exist. Also took care to avoid some compile time warnings.
+ * exchange-folder.c: Same. Also took care to avoid some compile time
+ warnings.
+ * exchange-folder-subscription.c: Included
+ exchange-folder-subscription.h file to avoid compilation warning.
+
+ Fixes bug #310233.
+
+2005-07-13 Praveen Kumar <kpraveen novell com>
+
+ * org-gnome-exchange-operations.eplug.in : Modified the eplug file to
+ add the "commit" code for folder hierarchy plugins for calendar and
+ contacts
+
+2005-07-11 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * exchange-operations.c (exchange_operations_report_error) : Check that
+ the result is not a success and only then print the error
+ * exchange-account-setup.c (btn_chpass_clicked) : Call the error
+ reporting routine only if there is a failure.
+ * exchange-config-listener.c (account_added) : Similar
+
+2005-07-11 Sarfraaz Ahmed <asarfraaz novell com>
+
+ Patch submitted by ArunPrakash <arunp novell com>
+ * exchange-operations.c (exchange_operations_report_error) : Newly
+ added, to report errors using e_error_run. Also a list of error-ids is
+ added.
+ * exchange-config-listener.c (account_added) (account_removed) :
+ Modified the usage of e_notice to e_error_run. Also the error from
+ exchange_account_connect is reported using
+ exchange_operations_report_error.
+ * exchange-account-setup.c (btn_chpass_clicked)
+ (org_gnome_exchange_settings) (print_error) (set_oof_info): Changed to
+ use exchange_operations_report_error and e_error_run functions.
+ * org-gnome-exchange-operations.error.xml : Newly added, defines
+ the list of error messages used in the plugin.
+ * Makefile.am : Modified for org-gnome-exchange-operations.error.xml
+
+2005-07-11 Shakti Sen <shprasad novell com>
+
+ * Makefile.am: Included files exchange-folder-subscription.c,
+ exchange-folder-subscription.h, exchange-folder.c and
+ org-gnome-folder-subscription.xml
+ * exchange-folder.c: Renamed all the function names starting with
+ org_gnome_* to org_gnome_exchnage* to resolve name space collision.
+ * org-gnome-exchange-operations.eplug.in: Added the hook class for
+ 'Subscribe/Unsubscribe Folder'.
+
+2005-07-08 Praveen Kumar <kpraveen novell com>
+
+ * Makefile.am : Added entries for the files providing the delegation
+ assistant feature
+ * exchange-user-dialog.c : Added new
+ * exchange-user-dialog.h : Added new
+ * exchange-account-setup.c (btn_dass_clicked) : Enabled the code for
+ for invoking the delegation assistant window
+ * exchange-delegates-user.c : Modified to include the header files
+ from include path instead of the local directory
+ * exchange-permissions-dialog.c : Modified an occurence to include
+ the file exchange-user-dialog.c instead of e2k-folder-dialog.c
+
+2005-07-08 Shakti Sen <shprasad novell com>
+
+ * Makefile.am: Included files exchange-permissions-dialog.c,
+ exchange-permissions-dialog.h, exchange-folder-permission.c,
+ org-gnome-folder-permissions.xml & exchange-permissions-dialog.glade
+ * exchange-folder-permission.c: Renamed the function name
+ org_gnome_menu_folder_permissions to
+ org_gnome_exchnage_menu_folder_permissions
+ * org-gnome-exchange-operations.eplug.in: Added the hook class for
+ Folder Permissions.
+
+2005-07-08 Shakti Sen <shprasad novell com>
+
+ * exchange-folder-permission.c: Added new file for Folder Permissions.
+ * exchange-permissions-dialog.c: Added new file for Folder Permissions.
+ * exchange-permissions-dialog.h: Added new file for Folder Permissions.
+ * exchange-permissions-dialog.glade: Added newly for Folder Permissions
+ support.
+ * org-gnome-folder-permissions.xml: Added new file for Folder
+ Permissions support.
+ * exchange-folder-subscription.c: Added new file for Folder
+ Subscribe/Unsubcribe support.
+ * exchange-folder-subscription.h: Added new file for Folder
+ Subscribe/Unsubcribe support.
+ * exchange-folder.c: Added new file for Folder Subscribe/Unsubcribe
+ support.
+ * org-gnome-folder-subscription.xml: Added new file for Folder
+ Subscribe/Unsubcribe support.
+
+2005-07-07 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * exchange-account-setup.c : Include exchange-folder-size-display.h
+ * exchange-folder-size-display.c : Similar
+
+2005-07-07 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * exchange-account-setup.c (btn_fsize_clicked) : Implemented new to
+ invoke the folder size table.
+ (org_gnome_exchange_settings) : Minor re-ordering
+ * exchange-folder-size-display.c : Newly added to handle the UI code
+ for folder size display
+ * exchange-folder-size-display.h : Similar
+ * exchange-folder-size.[ch] : Removed
+ * Makefile.am : Include exchange-folder-size-display.[ch]
+
+2005-07-05 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * exchange-config-listener.c (add_new_sources) : Newly added. This adds
+ the esources for all the folders only if the esource doesnt already
+ exist.
+ (account_added) : Invoke add_new_sources after connect.
+
+2005-07-01 Praveen Kumar <kpraveen novell com>
+
+ * Makefile.am : Added new file entries for calendar , contacts
+ and change-password
+ * exchange-account-setup.c (btn_chpass_clicked) : enabled the code
+ * exchange-operations.c (exchange_operations_cta_add_node_to_tree) :
+ This now stores the relative uri of the node to the model
+ (exchange_operations_cta_select_node_from_tree) : Added new. This
+ selects the node for a given relative uri.
+ * exchange-operations.h : Similar
+ * org-gnome-exchange-operations.eplug.in : Added commit hook action
+ for calendar and contacts
+ * exchange-change-password.c : Added new
+ * exchange-calendar.c : Added new
+ * exchange-contacts.c : Added new
+
+2005-07-01 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * exchange-account-setup.c(print_error) : Added new. This prints the
+ validation error string.
+ (owa_authenticate_user) : Fetch the error code from validate and handle
+ the printing of error strings in the plugin.
+ * exchange-config-listener.c (account_added) : For now add the sources
+ before connect to avoid multiple esources. Should be fixed more
+ elegantly.
+
+2005-06-27 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * Makefile.am : Added the header files as part of SOURCES so that they
+ get disted as well.
+
+2005-06-22 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * exchange-account-setup.c : We no longer should be declaring the
+ global_config_listener as a static variable here. Also, added some
+ NULL checks to avoid crashes.
+
+2005-06-15 Sushma Rai <rsushma novell com>
+
+ * exchange-account-setup.c (org_gnome_exchange_settings): Trying to
+ get the exchange account, after checking the account selected in
+ an exchange account or not. It fixes a crash, when trying to edit an
+ non-exchange account, where e-d-s and evolution are built with exchange
+ support, but exchange account is not configured.
+
+2005-06-14 Sarfaaz Ahmed <asarfraaz novell com>
+
+ * exchange-account-setup.c : Fixed some warnings
+ * exchange-config-listener.c : Similar
+
+2005-06-12 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * Initial commit to rename Exchange-account-setup as Exchange
+ Operations.
+
+2005-06-10 Sarfraaz Ahmed <asarfraaz novell com>
+
+ * exchange-account-setup.c (e_plugin_lib_enable)
+ (free_exchange_listener)(e_plugin_lib_enable) : Added new to
+ initialise the config listener.
+ (update_state) : Now updates the state directly from the server and not
+ from the file as earlier.
+ (owa_authenticate_user) : Authenticates and validates directly from
+ the server instead of using the camel APIs as earlier.
+ (set_oof_info) : Sets the state directly on the server
+ * Makefile.am : Use CAMEL_EXCHANGE CFLAGS and LIBS
+
+2005-05-21 Sarfraaz Ahmed <asarfraaz novell com>
+
+ Added a bunch of files to create exchange plugins for UI changes
+ * exchange-change-password.[ch]/.glade
+ * exchange-delegates.[ch]/.glade
+ * exchange-delegate-user.[ch]
+ * exchange-folder-size.[ch]
+ * exchange-folder-tree.glade
+
+2005-05-16 Not Zed <NotZed Ximian com>
+
+ * exchange-account-setup.c: moved e-error to e-util
+
+2005-03-18 Sushma Rai <rsushma novell com>
+
+ * exchange-account-setup.c (org_gnome_exchange_owa_url): When the
+ Exchange account doesn't contain OWA url parameter, setting the OWA
+ url value in the receive page and saving it.
+ (construct_owa_url): Forming OWA url, from the existing parameters for
+ hostname, ssl, OWA path and mailbox name.
+ see #73627
+
+2005-03-17 Sushma Rai <rsushma novell com>
+
+ * exchange-account-setup.c (exchange_authtype_changed): Setting the
+ authentication mechanism to both transport and source urls.
+
+2005-03-05 Sushma Rai <rsushma novell com>
+
+ * org-gnome-exchange-account-setup.eplug.in: Added the commit function
+ to save OOF data. This got missed in the previous commit. Also removed
+ duplicate accountWizard definition.
+
+2005-02-28 JP Rosevear <jpr novell com>
+
+ * org-gnome-exchange-account-setup.eplug.in: add account wizard item
+
+2005-02-27 Sushma Rai <rsushma novell com>
+
+ * exchange-account-setup.c (org_gnome_exchange_settings): Storing the
+ oof data enterted by user to a file, displaying the existing data on
+ this page.
+ (toggled_state): Signal hander for radiobutton, that sets the oof state.
+ (update_state): Signal handler that reads the oof message entered.
+ (org_gnome_exchange_commit): Stores the oof data and does cleanup.
+ (store_oof_info): Checks for the oof information file, writes the
+ oof state and message to the file.
+ (destroy_oof_data): Frees OOFData.
+
+2005-02-26 Sushma Rai <rsushma novell com>
+
+ * exchange-account-setup.c (org_gnome_exchange_check_options):
+ Returning FALSE on NULL host name or set to "" for receive page,
+ so that one can proceed with the account creation only after
+ hostname is retrived and set by validate().
+
+2005-02-24 Björn Torkelsson <torkel acc umu se>
+
+ * org-gnome-exchange-account-setup.eplug.in: Added author and
+ fixed description.
+
+2005-02-21 Not Zed <NotZed Ximian com>
+
+ * exchange-account-setup.c (org_gnome_exchange_owa_url): if the
+ host is null in the url, set it to "", so it has a non-null value.
+
+2005-02-07 Sushma Rai <rsushma novell com>
+
+ * org-gnome-exchange-account-setup.eplug.in: Added plugin for adding
+ auth type section to editor.
+
+ * exchange-account-setup.c (org_gnome_exchange_auth_section): Adding
+ and handling authentication type for exchange account.
+
+2005-01-28 Not Zed <NotZed Ximian com>
+
+ ** related to bug #71520.
+
+ * exchange-account-setup.c: All but re-written.
+ Fixed the license of the file.
+ Fixed a translation string.
+ Modified return condition check.
+ Fixed problem over writing current account with the old data.
+ Removed duplicated code.
+ Removed the hack for handling NULL hostname, now using
+ CAMEL_URL_HIDDEN_HOST url flag in the provider.
+ Using E_ACCOUNT_SOURCE_SAVE_PASSWD for remember password.
+ Removed the way owa url entry was added to table in config section,
+ Now econfig supports tables.
+
+ * exchange-ask-password.c: removed, functionality moved to
+ exchange-account-setup.c.
+
+2005-01-25 Sushma Rai <rsushma novell com>
+
+ * exchange-account-setup.c (create_page): Fixed empty
+ string being marked for translation problem. #71644
+
+2005-01-23 Sushma Rai <rsushma novell com>
+
+ * org-gnome-exchange-account-setup.eplug.in: Added plugins
+ for handling hiding auth type section in druid.
+
+ * exchange-account-setup.c (add_owa_entry_to_editor): Changed the
+ button label to "Authenticate" from OK
+
+ * exchange-ask-password.c (add_owa_entry): Changed the button label
+ to Authenticate.
+ (org_gnome_exchange_handle_auth): Hiding Auth section in receive page.
+ (org_gnome_exchange_handle_send_auth_option): Hiding the Auth section
+ in send page
+
+2005-01-22 Sushma Rai <rsushma novell com>
+
+ * org-gnome-exchange-account-setup.eplug.in: Added
+ org_gnome_exchange_check_options plugin.
+
+ * exchange-ask-password.c (org_gnome_exchange_check_options):
+ Reads OWA URL value and sets use_ssl and owa_url values for source
+ account url.
+
+ * exchange-account-setup.c (org_gnome_exchange_set_url)
+ (add_owa_entry_to_editor): Reading owa url value from gconf and setting
+ owa url value in the account editor. Fixes #71378
+
+2005-01-19 Sushma Rai <rsushma novell com>
+
+ * exchange-ask-password.c (validate_exchange_user): Fix for remembering
+ password if user has selected that option, while creating the account.
+
+2005-01-18 Sushma Rai <rsushma novell com>
+
+ * exchange-ask-password.c (validate_exchange_user): Reading the return
+ value of user validation function. Fixes #71385
+
+2005-01-18 Sushma Rai <rsushma novell com>
+
+ * exchange-ask-password.c (validate_exchange_user): Filling up
+ user name so that page check doesn't fail. Fixes #71384
+
+2005-01-18 Sushma Rai <rsushma novell com>
+
+ * exchange-ask-password.c (org_gnome_exchange_read_url):
+ Setting dummy host name, which will be reset to proper
+ hostname once the user is authenticated.
+
+2005-01-18 Sushma Rai <rsushma novell com>
+
+ * org-gnome-exchange-account-setup.eplug.in: Moved two account
+ editor plugins unser same hook class.
+
+ * exchange-ask-password.c: Reorganized the code.
+ Used accessor functions to read and set EAccount values.
+ Removed editor specific factory function add_owa_entry_to_editor()
+ from here.
+
+ * exchange-account-setup.c: Reorganized the code.
+ Moved add_owa_entry_to_editor() and it's sub functions into this file.
+ (org_gnome_exchange_account_setup): Reading source url and transport
+ url values stored in gconf and filling up the EAccount structure.
+ This fixes the problem of page check failure, as improper source url
+ and transport url values, as we don't read host name in the editor.
+ (org_gnome_exchange_set_url): Similar.
+
+2005-01-17 Sushma Rai <rsushma novell com>
+
+ * Makefile.am: Linking to camel libs. Fixes plugin loading problem
+ due to undefined camel symbol, during evolution startup.
+
+2005-01-13 Sushma Rai <rsushma novell com>
+
+ * org-gnome-exchange-account-setup.eplug.in: Combined
+ all the plugins into one.
+
+2005-01-12 Sushma Rai <rsushma novell com>
+
+ * exchange-ask-password.c: (validate_exchange_user):
+ Added one more error condition check.
+
+2005-01-12 Sushma Rai <rsushma novell com>
+
+ * org-gnome-exchange-account-setup.eplug.in: Factory
+ method to add owa url entry to account editor.
+
+ * exchange-ask-password.c: (org_gnome_exchange_set_url)
+ (add_owa_entry_to_editor): Adds owa url entry to the
+ account editor for Exchange account.
+ (validate_exchange_user): Using the CamelProvider private
+ function defined by Exchange camel provider.
+
+2005-01-11 Sushma Rai <rsushma novell com>
+
+ * org-gnome-exchange-account-setup.eplug.in: Removed page check plugin
+
+ * exchange-ask-password.c: Added a button to prompt for password
+ instead of listening on page next signal
+
+2005-01-11 Not Zed <NotZed Ximian com>
+
+ * Makefile.am: fix LDFLAGS variable name.
+
+2005-01-10 Sushma Rai <rsushma novell com>
+
+ * exchange-ask-password.c: (validate_exchange_user):
+ Corrected argument order.
+
+2005-01-10 Sushma Rai <rsushma novell com>
+
+ * org-gnome-exchange-account-setup.eplug.in: Added plugin to read
+ OWA url entry to the account set up druid.
+
+ * exchange-ask-password.c: Create a entry for OWA URL and reads the
+ URL value.
+
+2005-01-09 Sushma Rai <rsushma novell com>
+
+ * exchange-ask-password.c: Pops up password dialog and validates
+ user credentials once owa url and user name are entered.
+
+ * org-gnome-exchange-account-setup.eplug.in: Added page check plugin.
+
+2005-01-09 Sushma Rai <rsushma novell com>
+
+ * Intial ckeckin, Plugin for Exchange account specific settings
diff --git a/eplugin/Makefile.am b/eplugin/Makefile.am
new file mode 100644
index 0000000..116b449
--- /dev/null
+++ b/eplugin/Makefile.am
@@ -0,0 +1,77 @@
+### EVO_PLUGIN_RULE ### begin ###
+
+%.eplug: %.eplug.in
+ sed -e 's|\ PLUGINDIR\@|$(plugindir)|' \
+ -e 's|\ SOEXT\@|$(SOEXT)|' \
+ -e 's|\ GETTEXT_PACKAGE\@|$(GETTEXT_PACKAGE)|' \
+ -e 's|\ LOCALEDIR\@|$(localedir)|' $< > $@
+
+%.eplug.in: %.eplug.xml
+ LC_ALL=C $(INTLTOOL_MERGE) -x -u /tmp $< $@
+
+%.error: %.error.xml
+ LC_ALL=C $(INTLTOOL_MERGE) -x -u /tmp $< $@
+
+### EVO_PLUGIN_RULE ### end ###
+
+
+plugin_DATA = org-gnome-exchange-operations.eplug
+
+plugin_LTLIBRARIES = liborg-gnome-exchange-operations.la
+
+liborg_gnome_exchange_operations_la_SOURCES = \
+ exchange-operations.c \
+ exchange-operations.h \
+ exchange-config-listener.c \
+ exchange-config-listener.h \
+ exchange-calendar.c \
+ exchange-contacts.c \
+ exchange-change-password.c \
+ exchange-change-password.h \
+ exchange-delegates-user.c \
+ exchange-delegates-user.h \
+ exchange-delegates.c \
+ exchange-delegates.h \
+ exchange-user-dialog.c \
+ exchange-user-dialog.h \
+ exchange-folder-size-display.c \
+ exchange-folder-size-display.h \
+ exchange-account-setup.c \
+ exchange-permissions-dialog.c \
+ exchange-permissions-dialog.h \
+ exchange-folder-permission.c \
+ exchange-folder-subscription.c \
+ exchange-folder-subscription.h \
+ exchange-folder.c \
+ exchange-mail-send-options.c \
+ exchange-send-options.c \
+ exchange-send-options.h
+
+liborg_gnome_exchange_operations_la_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -I . \
+ $(EVOLUTION_DATA_SERVER_CFLAGS) \
+ $(EVOLUTION_PLUGIN_CFLAGS) \
+ $(CAMEL_EXCHANGE_CFLAGS) \
+ $(EVOLUTION_MAIL_CFLAGS)
+
+liborg_gnome_exchange_operations_la_LIBADD = \
+ $(EVOLUTION_DATA_SERVER_LIBS) \
+ $(EVOLUTION_PLUGIN_LIBS) \
+ $(CAMEL_EXCHANGE_LIBS) \
+ $(EVOLUTION_MAIL_LIBS)
+
+liborg_gnome_exchange_operations_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED)
+
+error_DATA = org-gnome-exchange-operations.error
+errordir = $(EVOLUTION_PLUGIN_errordir)
+
+EXTRA_DIST = \
+ org-gnome-exchange-operations.eplug.xml \
+ org-gnome-exchange-operations.error.xml
+
+BUILT_SOURCES = $(error_DATA) org-gnome-exchange-operations.eplug
+
+CLEANFILES = $(BUILT_SOURCES)
+
+-include $(top_srcdir)/git.mk
diff --git a/eplugin/exchange-account-setup.c b/eplugin/exchange-account-setup.c
new file mode 100644
index 0000000..f1b64d3
--- /dev/null
+++ b/eplugin/exchange-account-setup.c
@@ -0,0 +1,1150 @@
+/*
+ * 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:
+ * Sushma Rai <rsushma novell com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "libedataserver/e-account.h"
+#include "e-util/e-error.h"
+
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <gconf/gconf-client.h>
+#include <camel/camel-provider.h>
+#include <camel/camel-url.h>
+#include <camel/camel-service.h>
+#include <camel/camel-folder.h>
+#include <e-util/e-dialog-utils.h>
+#include <e2k-validate.h>
+#include <exchange-oof.h>
+#include <exchange-account.h>
+#include "exchange-config-listener.h"
+#include "exchange-operations.h"
+#include "exchange-folder-size-display.h"
+#include "mail/em-account-editor.h"
+#include "mail/em-config.h"
+#include "exchange-delegates.h"
+#include "exchange-change-password.h"
+#include "exchange-folder-size-display.h"
+
+GtkWidget* org_gnome_exchange_settings(EPlugin *epl, EConfigHookItemFactoryData *data);
+GtkWidget *org_gnome_exchange_owa_url(EPlugin *epl, EConfigHookItemFactoryData *data);
+gboolean org_gnome_exchange_check_options(EPlugin *epl, EConfigHookPageCheckData *data);
+GtkWidget *org_gnome_exchange_auth_section (EPlugin *epl, EConfigHookItemFactoryData *data);
+void org_gnome_exchange_commit (EPlugin *epl, EConfigHookItemFactoryData *data);
+GtkWidget* org_gnome_exchange_show_folder_size_factory (EPlugin *epl, EConfigHookItemFactoryData *data);
+
+CamelServiceAuthType camel_exchange_ntlm_authtype = {
+ /* i18n: "Secure Password Authentication" is an Outlookism */
+ (gchar *) N_("Secure Password"),
+
+ /* i18n: "NTLM" probably doesn't translate */
+ (gchar *) N_("This option will connect to the Exchange server "
+ "using secure password (NTLM) authentication."),
+
+ (gchar *) "NTLM",
+ TRUE
+};
+
+CamelServiceAuthType camel_exchange_password_authtype = {
+ (gchar *) N_("Plaintext Password"),
+
+ (gchar *) N_("This option will connect to the Exchange server "
+ "using standard plaintext password authentication."),
+
+ (gchar *) "Basic",
+ TRUE
+};
+
+typedef struct {
+ gboolean state;
+ gchar *message;
+ GtkWidget *text_view;
+}OOFData;
+
+static OOFData *oof_data;
+
+static void
+update_state (GtkTextBuffer *buffer, gpointer data)
+{
+ if (gtk_text_buffer_get_modified (buffer)) {
+ GtkTextIter start, end;
+ if (oof_data->message)
+ g_free (oof_data->message);
+ gtk_text_buffer_get_bounds (buffer, &start, &end);
+ oof_data->message = gtk_text_buffer_get_text (buffer, &start,
+ &end, FALSE);
+ gtk_text_buffer_set_modified (buffer, FALSE);
+ }
+}
+
+static void
+toggled_state (GtkToggleButton *button, gpointer data)
+{
+ gboolean current_oof_state = gtk_toggle_button_get_active (button);
+
+ if (current_oof_state == oof_data->state)
+ return;
+ oof_data->state = current_oof_state;
+ gtk_widget_set_sensitive (oof_data->text_view, current_oof_state);
+}
+
+#ifdef HAVE_KRB5
+static void
+btn_chpass_clicked (GtkButton *button, gpointer data)
+{
+ ExchangeAccount *account;
+ gchar *old_password, *new_password;
+ ExchangeAccountResult result;
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account)
+ return;
+
+ old_password = exchange_account_get_password (account);
+ if (!old_password) {
+ g_print ("Could not fetch old password\n");
+ return;
+ }
+ new_password = exchange_get_new_password (old_password, TRUE);
+ if (!new_password) {
+ /* "Cacel" button was hit */
+ return;
+ }
+ /* g_print ("Current password is \"%s\"\n", old_password); */
+ result = exchange_account_set_password (account, old_password, new_password);
+ if (result != EXCHANGE_ACCOUNT_CONNECT_SUCCESS)
+ exchange_operations_report_error (account, result);
+
+ g_free (old_password);
+ g_free (new_password);
+}
+#endif
+
+static void
+btn_dass_clicked (GtkButton *button, gpointer data)
+{
+ ExchangeAccount *account;
+ account = exchange_operations_get_exchange_account ();
+ if (!account)
+ return;
+ exchange_delegates (account, gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_WINDOW));
+}
+
+static void
+btn_fsize_clicked (GtkButton *button, gpointer data)
+{
+ ExchangeAccount *account;
+ GtkListStore *model;
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account)
+ return;
+
+ model = exchange_account_folder_size_get_model (account);
+ if (model)
+ exchange_folder_size_display (model, GTK_WIDGET (button));
+}
+
+/* only used in editor */
+GtkWidget *
+org_gnome_exchange_settings(EPlugin *epl, EConfigHookItemFactoryData *data)
+{
+ EMConfigTargetAccount *target_account;
+ ExchangeAccount *account = NULL;
+ CamelURL *url;
+ const gchar *source_url;
+ gchar *message = NULL, *txt = NULL, *oof_message;
+ gboolean oof_state = FALSE;
+ gint offline_status;
+
+ GtkVBox *vbox_settings;
+
+ /* OOF fields */
+ GtkFrame *frm_oof;
+ GtkVBox *vbox_oof;
+ GtkLabel *lbl_oof_desc;
+ GtkTable *tbl_oof_status;
+ GtkLabel *lbl_status;
+ GtkRadioButton *radio_iof, *radio_oof;
+ GtkScrolledWindow *scrwnd_oof;
+ GtkTextView *txtview_oof;
+
+ /* Authentication settings */
+ GtkFrame *frm_auth;
+ GtkVBox *vbox_auth;
+ GtkTable *tbl_auth;
+#ifdef HAVE_KRB5
+ GtkLabel *lbl_chpass;
+ GtkButton *btn_chpass;
+#endif
+ GtkLabel *lbl_dass;
+ GtkButton *btn_dass;
+
+ /* Miscelleneous setting */
+ GtkFrame *frm_misc;
+ GtkVBox *vbox_misc;
+ GtkTable *tbl_misc;
+ GtkLabel *lbl_fsize;
+ GtkButton *btn_fsize;
+
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+
+ target_account = (EMConfigTargetAccount *)data->config->target;
+ source_url = e_account_get_string (target_account->account, E_ACCOUNT_SOURCE_URL);
+ url = camel_url_new(source_url, NULL);
+ if (url == NULL
+ || strcmp(url->protocol, "exchange") != 0) {
+ if (url)
+ camel_url_free(url);
+ return NULL;
+ }
+
+ if (data->old) {
+ camel_url_free(url);
+ return data->old;
+ }
+ if (url)
+ camel_url_free (url);
+
+ account = exchange_operations_get_exchange_account ();
+
+ exchange_config_listener_get_offline_status (exchange_global_config_listener,
+ &offline_status);
+ if (offline_status == OFFLINE_MODE) {
+ e_error_run (NULL, ERROR_DOMAIN ":exchange-settings-offline", NULL);
+
+ return NULL;
+ }
+
+ oof_data = g_new0 (OOFData, 1);
+
+ oof_data->state = FALSE;
+ oof_data->message = NULL;
+ oof_data->text_view = NULL;
+
+ /* See if oof info found already */
+
+ if (account && !exchange_oof_get (account, &oof_state, &message)) {
+
+ e_error_run (NULL, ERROR_DOMAIN ":state-read-error", NULL);
+
+ return NULL;
+ }
+
+ if (message && *message)
+ oof_data->message = g_strdup (message);
+ else
+ oof_data->message = NULL;
+ oof_data->state = oof_state;
+
+ /* construct page */
+
+ vbox_settings = (GtkVBox*) g_object_new (GTK_TYPE_VBOX, "homogeneous", FALSE, "spacing", 6, NULL);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox_settings), 12);
+
+ frm_oof = (GtkFrame*) g_object_new (GTK_TYPE_FRAME, "label", _("Out Of Office"), NULL);
+ gtk_box_pack_start (GTK_BOX (vbox_settings), GTK_WIDGET (frm_oof), FALSE, FALSE, 0);
+
+ vbox_oof = (GtkVBox*) g_object_new (GTK_TYPE_VBOX, NULL, "homogeneous", FALSE, "spacing", 12, NULL);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox_oof), 6);
+ gtk_container_add (GTK_CONTAINER (frm_oof), GTK_WIDGET (vbox_oof));
+
+ lbl_oof_desc = (GtkLabel*) g_object_new (GTK_TYPE_LABEL, "label", _("The message specified below will be automatically sent to \neach person who sends mail to you while you are out of the office."), "justify", GTK_JUSTIFY_LEFT, NULL);
+ gtk_misc_set_alignment (GTK_MISC (lbl_oof_desc), 0, 0.5);
+ gtk_box_pack_start (GTK_BOX (vbox_oof), GTK_WIDGET (lbl_oof_desc), FALSE, FALSE, 0);
+
+ tbl_oof_status = (GtkTable*) g_object_new (GTK_TYPE_TABLE, "n-rows", 2, "n-columns", 2, "homogeneous", FALSE, "row-spacing", 6, "column-spacing", 6, NULL);
+ txt = g_strdup_printf ("<b>%s</b>", _("Status:"));
+ lbl_status = (GtkLabel*) g_object_new (GTK_TYPE_LABEL, "label", txt, "use-markup", TRUE, NULL);
+ g_free (txt);
+ gtk_misc_set_alignment (GTK_MISC (lbl_status), 0, 0.5);
+ gtk_misc_set_padding (GTK_MISC (lbl_status), 0, 0);
+
+ if (oof_data->state) {
+ radio_oof = (GtkRadioButton*) g_object_new (GTK_TYPE_RADIO_BUTTON, "label", _("I am out of the office"), NULL);
+ radio_iof = (GtkRadioButton*) g_object_new (GTK_TYPE_RADIO_BUTTON, "label", _("I am in the office"), "group", radio_oof, NULL);
+ }
+ else {
+ radio_iof = (GtkRadioButton*) g_object_new (GTK_TYPE_RADIO_BUTTON, "label", _("I am in the office"), NULL);
+ radio_oof = (GtkRadioButton*) g_object_new (GTK_TYPE_RADIO_BUTTON, "label", _("I am out of the office"), "group", radio_iof, NULL);
+ }
+ g_signal_connect (radio_oof, "toggled", G_CALLBACK (toggled_state), NULL);
+
+ gtk_table_attach (tbl_oof_status, GTK_WIDGET (lbl_status), 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+ gtk_table_attach (tbl_oof_status, GTK_WIDGET (radio_iof), 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+ gtk_table_attach (tbl_oof_status, GTK_WIDGET (radio_oof), 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+
+ gtk_box_pack_start (GTK_BOX (vbox_oof), GTK_WIDGET (tbl_oof_status), FALSE, FALSE, 0);
+
+ scrwnd_oof = (GtkScrolledWindow*) g_object_new (GTK_TYPE_SCROLLED_WINDOW, "hscrollbar-policy", GTK_POLICY_AUTOMATIC, "vscrollbar-policy", GTK_POLICY_AUTOMATIC, "shadow-type", GTK_SHADOW_IN, NULL);
+ gtk_box_pack_start (GTK_BOX (vbox_oof), GTK_WIDGET (scrwnd_oof), FALSE, FALSE, 0);
+ txtview_oof = (GtkTextView*) g_object_new (GTK_TYPE_TEXT_VIEW, "justification", GTK_JUSTIFY_LEFT, "wrap-mode", GTK_WRAP_WORD, "editable", TRUE, NULL);
+ buffer = gtk_text_view_get_buffer (txtview_oof);
+ gtk_text_buffer_get_bounds (buffer, &start, &end);
+ oof_message = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+ if (oof_message && *oof_message) {
+ /* Will this ever happen? */
+ oof_data->message = oof_message;
+ }
+ if (oof_data->message) {
+ /* previuosly set message */
+ gtk_text_buffer_set_text (buffer, oof_data->message, -1);
+ gtk_text_view_set_buffer (txtview_oof, buffer);
+
+ }
+ gtk_text_buffer_set_modified (buffer, FALSE);
+ if (!oof_data->state)
+ gtk_widget_set_sensitive (GTK_WIDGET (txtview_oof), FALSE);
+ oof_data->text_view = GTK_WIDGET (txtview_oof);
+ g_signal_connect (buffer, "changed", G_CALLBACK (update_state), NULL);
+ gtk_container_add (GTK_CONTAINER (scrwnd_oof), GTK_WIDGET (txtview_oof));
+
+ /* Security settings */
+ frm_auth = (GtkFrame*) g_object_new (GTK_TYPE_FRAME, "label", _("Security"), NULL);
+ gtk_box_pack_start (GTK_BOX (vbox_settings), GTK_WIDGET (frm_auth), FALSE, FALSE, 0);
+
+ vbox_auth = (GtkVBox*) g_object_new (GTK_TYPE_VBOX, "homogeneous", FALSE, "spacing", 6, NULL);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox_auth), 6);
+ gtk_container_add (GTK_CONTAINER (frm_auth), GTK_WIDGET (vbox_auth));
+
+ tbl_auth = (GtkTable*) g_object_new (GTK_TYPE_TABLE, "n-rows", 2, "n-columns", 2, "homogeneous", FALSE, "row-spacing", 6, "column-spacing", 6, NULL);
+
+#ifdef HAVE_KRB5
+ /* Change Password */
+ lbl_chpass = (GtkLabel*) g_object_new (GTK_TYPE_LABEL, "label", _("Change the password for Exchange account"), NULL);
+ gtk_misc_set_alignment (GTK_MISC (lbl_chpass), 0, 0.5);
+ btn_chpass = (GtkButton*) g_object_new (GTK_TYPE_BUTTON, "label", _("Change Password"), NULL);
+ g_signal_connect (GTK_OBJECT (btn_chpass), "clicked", G_CALLBACK (btn_chpass_clicked), NULL);
+#endif
+
+ /* Delegation Assistant */
+ lbl_dass = (GtkLabel*) g_object_new (GTK_TYPE_LABEL, "label", _("Manage the delegate settings for Exchange account"), NULL);
+ gtk_misc_set_alignment (GTK_MISC (lbl_dass), 0, 0.5);
+ btn_dass = (GtkButton*) g_object_new (GTK_TYPE_BUTTON, "label", _("Delegation Assistant"), NULL);
+ g_signal_connect (btn_dass, "clicked", G_CALLBACK (btn_dass_clicked), NULL);
+ /* Add items to the table */
+#ifdef HAVE_KRB5
+ gtk_table_attach_defaults (tbl_auth, GTK_WIDGET (lbl_chpass), 0, 1, 0, 1);
+ gtk_table_attach (tbl_auth, GTK_WIDGET (btn_chpass), 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+#endif
+ gtk_table_attach_defaults (tbl_auth, GTK_WIDGET (lbl_dass), 0, 1, 1, 2);
+ gtk_table_attach (tbl_auth, GTK_WIDGET (btn_dass), 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+ gtk_box_pack_start (GTK_BOX (vbox_auth), GTK_WIDGET (tbl_auth), FALSE, FALSE, 0);
+
+ /* Miscelleneous settings */
+ frm_misc = (GtkFrame*) g_object_new (GTK_TYPE_FRAME, "label", _("Miscelleneous"), NULL);
+ gtk_box_pack_start (GTK_BOX (vbox_settings), GTK_WIDGET (frm_misc), FALSE, FALSE, 0);
+
+ vbox_misc = (GtkVBox*) g_object_new (GTK_TYPE_VBOX, "homogeneous", FALSE, "spacing", 6, NULL);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox_misc), 6);
+ gtk_container_add (GTK_CONTAINER (frm_misc), GTK_WIDGET (vbox_misc));
+
+ tbl_misc = (GtkTable*) g_object_new (GTK_TYPE_TABLE, "n-rows", 1, "n-columns", 1, "homogeneous", FALSE, "row-spacing", 6, "column-spacing", 6, NULL);
+
+ /* Folder Size */
+ lbl_fsize = (GtkLabel*) g_object_new (GTK_TYPE_LABEL, "label", _("View the size of all Exchange folders"), NULL);
+ gtk_misc_set_alignment (GTK_MISC (lbl_fsize), 0, 0.5);
+ btn_fsize = (GtkButton*) g_object_new (GTK_TYPE_BUTTON, "label", _("Folders Size"), NULL);
+ g_signal_connect (btn_fsize, "clicked", G_CALLBACK (btn_fsize_clicked), NULL);
+ gtk_table_attach_defaults (tbl_misc, GTK_WIDGET (lbl_fsize), 0, 1, 0, 1);
+ gtk_table_attach (tbl_misc, GTK_WIDGET (btn_fsize), 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+ gtk_box_pack_start (GTK_BOX (vbox_misc), GTK_WIDGET (tbl_misc), FALSE, FALSE, 0);
+
+ gtk_widget_show_all (GTK_WIDGET (vbox_settings));
+ gtk_notebook_insert_page (GTK_NOTEBOOK (data->parent), GTK_WIDGET (vbox_settings), gtk_label_new(_("Exchange Settings")), 4);
+ return GTK_WIDGET (vbox_settings);
+
+}
+
+static void
+print_error (const gchar *owa_url, E2kAutoconfigResult result)
+{
+ switch (result) {
+
+ case E2K_AUTOCONFIG_CANT_CONNECT:
+ e_error_run (NULL, ERROR_DOMAIN ":account-connect-error", "", NULL);
+ break;
+
+ case E2K_AUTOCONFIG_CANT_RESOLVE:
+ e_error_run (NULL, ERROR_DOMAIN ":account-resolve-error", "", NULL);
+ break;
+
+ case E2K_AUTOCONFIG_AUTH_ERROR:
+ case E2K_AUTOCONFIG_AUTH_ERROR_TRY_NTLM:
+ case E2K_AUTOCONFIG_AUTH_ERROR_TRY_BASIC:
+ e_error_run (NULL, ERROR_DOMAIN ":password-incorrect", NULL);
+ break;
+
+ case E2K_AUTOCONFIG_AUTH_ERROR_TRY_DOMAIN:
+ e_error_run (NULL, ERROR_DOMAIN ":account-domain-error", NULL);
+ break;
+
+ case E2K_AUTOCONFIG_NO_OWA:
+ case E2K_AUTOCONFIG_NOT_EXCHANGE:
+ e_error_run (NULL, ERROR_DOMAIN ":account-wss-error", NULL);
+ break;
+
+ case E2K_AUTOCONFIG_CANT_BPROPFIND:
+ e_error_run (NULL, ERROR_DOMAIN ":connect-exchange-error",
+ "http://support.novell.com/cgi-bin/search/searchtid.cgi?/ximian/ximian328.html",
+ NULL);
+ break;
+
+ case E2K_AUTOCONFIG_EXCHANGE_5_5:
+ e_error_run (NULL, ERROR_DOMAIN ":account-version-error", NULL);
+ break;
+
+ default:
+ e_error_run (NULL, ERROR_DOMAIN ":configure-error", NULL);
+ break;
+
+ }
+}
+
+static const gchar *
+gal_auth_to_string (E2kAutoconfigGalAuthPref ad_auth)
+{
+ switch (ad_auth) {
+ case E2K_AUTOCONFIG_USE_GAL_DEFAULT: return "default";
+ case E2K_AUTOCONFIG_USE_GAL_BASIC: return "basic";
+ case E2K_AUTOCONFIG_USE_GAL_NTLM: return "ntlm";
+ }
+
+ return "default";
+}
+
+static void
+owa_authenticate_user(GtkWidget *button, EConfig *config)
+{
+ EMConfigTargetAccount *target_account = (EMConfigTargetAccount *)config->target;
+ E2kAutoconfigResult result;
+ CamelURL *url=NULL;
+ gboolean remember_password;
+ gchar *url_string, *key;
+ const gchar *source_url, *id_name, *owa_url;
+ gchar *at, *user;
+ gboolean valid = FALSE;
+ ExchangeParams *exchange_params;
+ GtkWidget *mailbox_entry = g_object_get_data (G_OBJECT (button), "mailbox-entry");
+
+ exchange_params = g_new0 (ExchangeParams, 1);
+ exchange_params->host = NULL;
+ exchange_params->ad_server = NULL;
+ exchange_params->ad_auth = E2K_AUTOCONFIG_USE_GAL_DEFAULT;
+ exchange_params->mailbox = NULL;
+ exchange_params->owa_path = NULL;
+ exchange_params->is_ntlm = TRUE;
+
+ source_url = e_account_get_string (target_account->account, E_ACCOUNT_SOURCE_URL);
+
+ if (source_url && source_url[0] != '\0')
+ url = camel_url_new(source_url, NULL);
+ if (url && url->user == NULL) {
+ id_name = e_account_get_string (target_account->account, E_ACCOUNT_ID_ADDRESS);
+ if (id_name) {
+ at = strchr(id_name, '@');
+ user = g_alloca(at-id_name+1);
+ memcpy(user, id_name, at-id_name);
+ user[at-id_name] = 0;
+ camel_url_set_user (url, user);
+ }
+ }
+
+ /* validate_user() CALLS GTK!!!
+
+ THIS IS TOTALLY UNNACCEPTABLE!!!!!!!!
+
+ It must use camel_session_ask_password, and it should return an exception for any problem,
+ which should then be shown using e-error */
+
+ owa_url = camel_url_get_param (url, "owa_url");
+ if (camel_url_get_param (url, "authmech"))
+ exchange_params->is_ntlm = TRUE;
+ else
+ exchange_params->is_ntlm = FALSE;
+ camel_url_set_authmech (url, exchange_params->is_ntlm ? "NTLM" : "Basic");
+
+ key = camel_url_to_string (url, CAMEL_URL_HIDE_PASSWORD | CAMEL_URL_HIDE_PARAMS);
+ /* Supress the trailing slash */
+ key [strlen(key) -1] = 0;
+
+ /* set the mailbox before function call to let it use our, not create one */
+ exchange_params->mailbox = g_strdup (camel_url_get_param (url, "mailbox"));
+
+ valid = e2k_validate_user (owa_url, key, &url->user, exchange_params,
+ &remember_password, &result,
+ GTK_WINDOW (gtk_widget_get_toplevel (button)));
+ g_free (key);
+
+ if (!valid && result != E2K_AUTOCONFIG_CANCELLED)
+ print_error (owa_url, result);
+
+ camel_url_set_host (url, valid ? exchange_params->host : "");
+
+ if (valid)
+ camel_url_set_param (url, "save-passwd", remember_password? "true" : "false");
+
+ camel_url_set_param (url, "ad_server", valid ? exchange_params->ad_server: NULL);
+ camel_url_set_param (url, "mailbox", valid ? exchange_params->mailbox : NULL);
+ camel_url_set_param (url, "owa_path", valid ? exchange_params->owa_path : NULL);
+ camel_url_set_param (url, "ad_auth", valid ? gal_auth_to_string (exchange_params->ad_auth) : NULL);
+
+ if (mailbox_entry) {
+ const gchar *par = camel_url_get_param (url, "mailbox");
+
+ gtk_entry_set_text (GTK_ENTRY (mailbox_entry), par ? par : "");
+ }
+
+ g_free (exchange_params->owa_path);
+ g_free (exchange_params->mailbox);
+ g_free (exchange_params->host);
+ g_free (exchange_params->ad_server);
+ g_free (exchange_params);
+
+ if (valid) {
+ url_string = camel_url_to_string (url, 0);
+ e_account_set_string (target_account->account, E_ACCOUNT_SOURCE_URL, url_string);
+ e_account_set_string (target_account->account, E_ACCOUNT_TRANSPORT_URL, url_string);
+ e_account_set_bool (target_account->account, E_ACCOUNT_SOURCE_SAVE_PASSWD, remember_password);
+ g_free (url_string);
+ }
+ camel_url_free (url);
+}
+
+static void
+owa_editor_entry_changed(GtkWidget *entry, EConfig *config)
+{
+ const gchar *uri, *ssl = NULL;
+ CamelURL *url, *owaurl = NULL;
+ gchar *url_string;
+ EMConfigTargetAccount *target = (EMConfigTargetAccount *)config->target;
+ GtkWidget *button = g_object_get_data((GObject *)entry, "authenticate-button");
+ gint active = FALSE;
+
+ /* NB: we set the button active only if we have a parsable uri entered */
+
+ const gchar * target_url = e_account_get_string(target->account, E_ACCOUNT_SOURCE_URL);
+ if (target_url && target_url[0] != '\0')
+ url = camel_url_new(target_url, NULL);
+ else url = NULL;
+ uri = gtk_entry_get_text((GtkEntry *)entry);
+ if (uri && uri[0]) {
+ camel_url_set_param(url, "owa_url", uri);
+ owaurl = camel_url_new(uri, NULL);
+ if (owaurl) {
+ active = TRUE;
+
+ /* Reading the owa url and setting use_ssl paramemter */
+ if (!strcmp(owaurl->protocol, "https"))
+ ssl = "always";
+ camel_url_free(owaurl);
+ }
+ } else {
+ camel_url_set_param(url, "owa_url", NULL);
+ }
+
+ camel_url_set_param(url, "use_ssl", ssl);
+ gtk_widget_set_sensitive(button, active);
+
+ url_string = camel_url_to_string(url, 0);
+ e_account_set_string(target->account, E_ACCOUNT_SOURCE_URL, url_string);
+ g_free(url_string);
+ camel_url_free (url);
+}
+
+static void
+update_mailbox_param_in_url (EAccount *account, e_account_item_t item, const gchar *mailbox)
+{
+ CamelURL *url;
+ gchar *url_string;
+ const gchar *target_url;
+
+ if (!account)
+ return;
+
+ target_url = e_account_get_string (account, item);
+ if (target_url && target_url[0] != '\0')
+ url = camel_url_new (target_url, NULL);
+ else
+ return;
+
+ if (mailbox && *mailbox)
+ camel_url_set_param (url, "mailbox", mailbox);
+ else
+ camel_url_set_param (url, "mailbox", NULL);
+
+ url_string = camel_url_to_string (url, 0);
+ e_account_set_string (account, item, url_string);
+ g_free (url_string);
+ camel_url_free (url);
+}
+
+static void
+mailbox_editor_entry_changed (GtkWidget *entry, EConfig *config)
+{
+ EMConfigTargetAccount *target;
+ const gchar *mailbox;
+
+ target = (EMConfigTargetAccount *)config->target;
+ mailbox = gtk_entry_get_text (GTK_ENTRY (entry));
+
+ update_mailbox_param_in_url (target->account, E_ACCOUNT_SOURCE_URL, mailbox);
+ update_mailbox_param_in_url (target->account, E_ACCOUNT_TRANSPORT_URL, mailbox);
+}
+
+static void
+want_mailbox_toggled (GtkWidget *toggle, EConfig *config)
+{
+ GtkWidget *entry;
+
+ g_return_if_fail (toggle != NULL);
+ g_return_if_fail (config != NULL);
+
+ entry = g_object_get_data (G_OBJECT (toggle), "mailbox-entry");
+ if (entry) {
+ gboolean is_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle));
+ EMConfigTargetAccount *target;
+ const gchar *mailbox;
+
+ gtk_widget_set_sensitive (entry, is_active);
+
+ target = (EMConfigTargetAccount *)config->target;
+ mailbox = gtk_entry_get_text (GTK_ENTRY (entry));
+
+ update_mailbox_param_in_url (target->account, E_ACCOUNT_SOURCE_URL, is_active ? mailbox : NULL);
+ update_mailbox_param_in_url (target->account, E_ACCOUNT_TRANSPORT_URL, is_active ? mailbox : NULL);
+ }
+}
+
+static gchar *
+construct_owa_url (CamelURL *url)
+{
+ const gchar *owa_path, *use_ssl = NULL;
+ const gchar *protocol = "http", *mailbox_name;
+ gchar *owa_url;
+
+ use_ssl = camel_url_get_param (url, "use_ssl");
+ if (use_ssl) {
+ if (!strcmp (use_ssl, "always"))
+ protocol = "https";
+ }
+
+ owa_path = camel_url_get_param (url, "owa_path");
+ if (!owa_path)
+ owa_path = "/exchange";
+ mailbox_name = camel_url_get_param (url, "mailbox");
+
+ if (mailbox_name)
+ owa_url = g_strdup_printf("%s://%s%s/%s", protocol, url->host, owa_path, mailbox_name);
+ else
+ owa_url = g_strdup_printf("%s://%s%s", protocol, url->host, owa_path );
+
+ return owa_url;
+}
+
+/* used by editor and assistant - same code */
+GtkWidget *
+org_gnome_exchange_owa_url(EPlugin *epl, EConfigHookItemFactoryData *data)
+{
+ EMConfigTargetAccount *target_account;
+ const gchar *source_url;
+ gchar *owa_url = NULL, *mailbox_name, *username;
+ GtkWidget *owa_entry, *mailbox_entry, *want_mailbox_check;
+ CamelURL *url;
+ gint row;
+ GtkWidget *hbox, *label, *button;
+
+ target_account = (EMConfigTargetAccount *)data->config->target;
+ source_url = e_account_get_string (target_account->account, E_ACCOUNT_SOURCE_URL);
+ if (source_url && source_url[0] != '\0')
+ url = camel_url_new(source_url, NULL);
+ else
+ url = NULL;
+ if (url == NULL
+ || strcmp(url->protocol, "exchange") != 0) {
+ if (url)
+ camel_url_free(url);
+
+ if (data->old
+ && (label = g_object_get_data((GObject *)data->old, "authenticate-label")))
+ gtk_widget_destroy(label);
+
+ /* TODO: we could remove 'owa-url' from the url,
+ but that will lose it if we come back. Maybe a commit callback could do it */
+
+ return NULL;
+ }
+
+ if (data->old) {
+ camel_url_free(url);
+ return data->old;
+ }
+
+ owa_url = g_strdup (camel_url_get_param(url, "owa_url"));
+ mailbox_name = g_strdup (camel_url_get_param (url, "mailbox"));
+ username = g_strdup (url->user);
+
+ /* if the host is null, then user+other info is dropped silently, force it to be kept */
+ if (url->host == NULL) {
+ gchar *uri;
+
+ camel_url_set_host(url, "");
+ uri = camel_url_to_string(url, 0);
+ e_account_set_string(target_account->account, E_ACCOUNT_SOURCE_URL, uri);
+ g_free(uri);
+ }
+
+ row = ((GtkTable *)data->parent)->nrows;
+
+ hbox = gtk_hbox_new (FALSE, 6);
+ label = gtk_label_new_with_mnemonic(_("_OWA URL:"));
+ gtk_widget_show(label);
+
+ owa_entry = gtk_entry_new();
+
+ if (!owa_url) {
+ if (url->host[0] != 0) {
+ gchar *uri;
+
+ /* url has hostname but not owa_url.
+ * Account has been created using x-c-s or evo is upgraded to 2.2
+ * When invoked from assistant, hostname will get set after validation,
+ * so this condition will never be true during account creation.
+ */
+ owa_url = construct_owa_url (url);
+ camel_url_set_param (url, "owa_url", owa_url);
+ uri = camel_url_to_string(url, 0);
+ e_account_set_string(target_account->account, E_ACCOUNT_SOURCE_URL, uri);
+ g_free(uri);
+ }
+ }
+ camel_url_free (url);
+ if (owa_url)
+ gtk_entry_set_text(GTK_ENTRY (owa_entry), owa_url);
+ gtk_label_set_mnemonic_widget((GtkLabel *)label, owa_entry);
+
+ button = gtk_button_new_with_mnemonic (_("A_uthenticate"));
+ gtk_widget_set_sensitive (button, owa_url && owa_url[0]);
+
+ gtk_box_pack_start (GTK_BOX (hbox), owa_entry, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+ gtk_widget_show_all(hbox);
+
+ gtk_table_attach (GTK_TABLE (data->parent), label, 0, 1, row, row+1, 0, 0, 0, 0);
+ gtk_table_attach (GTK_TABLE (data->parent), hbox, 1, 2, row, row+1, GTK_FILL|GTK_EXPAND, GTK_FILL, 0, 0);
+
+ g_signal_connect (owa_entry, "changed", G_CALLBACK(owa_editor_entry_changed), data->config);
+ g_object_set_data((GObject *)owa_entry, "authenticate-button", button);
+ g_signal_connect (button, "clicked", G_CALLBACK(owa_authenticate_user), data->config);
+
+ /* Track the authenticate label, so we can destroy it if e-config is to destroy the hbox */
+ g_object_set_data((GObject *)hbox, "authenticate-label", label);
+
+ /* check for correctness of the input in the owa_entry */
+ owa_editor_entry_changed (owa_entry, data->config);
+
+ row++;
+ want_mailbox_check = gtk_check_button_new_with_mnemonic (
+ _("Mailbox name is _different than user name"));
+ gtk_widget_show (want_mailbox_check);
+ gtk_table_attach (GTK_TABLE (data->parent), want_mailbox_check, 1, 2, row, row+1, GTK_FILL, GTK_FILL, 0, 0);
+ if (!username || !*username || !mailbox_name || !*mailbox_name ||
+ g_ascii_strcasecmp (username, mailbox_name) == 0 ||
+ (strchr (username, '/') && g_ascii_strcasecmp (strchr (username, '/') + 1, mailbox_name) == 0)) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (want_mailbox_check), FALSE);
+ } else {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (want_mailbox_check), TRUE);
+ }
+ g_signal_connect (want_mailbox_check, "toggled", G_CALLBACK (want_mailbox_toggled), data->config);
+
+ row++;
+ label = gtk_label_new_with_mnemonic (_("_Mailbox:"));
+ gtk_widget_show (label);
+
+ mailbox_entry = gtk_entry_new ();
+ gtk_widget_show (mailbox_entry);
+ if (mailbox_name)
+ gtk_entry_set_text (GTK_ENTRY (mailbox_entry), mailbox_name);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), mailbox_entry);
+
+ gtk_widget_set_sensitive (mailbox_entry, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (want_mailbox_check)));
+
+ g_signal_connect (mailbox_entry, "changed", G_CALLBACK (mailbox_editor_entry_changed), data->config);
+ g_object_set_data (G_OBJECT (button), "mailbox-entry", mailbox_entry);
+ g_object_set_data (G_OBJECT (want_mailbox_check), "mailbox-entry", mailbox_entry);
+
+ gtk_table_attach (GTK_TABLE (data->parent), label, 0, 1, row, row+1, 0, 0, 0, 0);
+ gtk_table_attach (GTK_TABLE (data->parent), mailbox_entry, 1, 2, row, row+1, GTK_FILL|GTK_EXPAND, GTK_FILL, 0, 0);
+
+ g_free (owa_url);
+ g_free (mailbox_name);
+ g_free (username);
+
+ return hbox;
+}
+
+gboolean
+org_gnome_exchange_check_options(EPlugin *epl, EConfigHookPageCheckData *data)
+{
+ EMConfigTargetAccount *target = (EMConfigTargetAccount *)data->config->target;
+ gint status = TRUE;
+
+ /* We assume that if the host is set, then the setting is valid.
+ The host gets set when the provider validate() call is made */
+ /* We do this check for receive page also, so that user can
+ * proceed with the account set up only after user is validated,
+ * and host name is reset by validate() call
+ */
+ if (data->pageid == NULL ||
+ strcmp (data->pageid, "10.receive") == 0 ||
+ strcmp (data->pageid, "20.receive_options") == 0) {
+ CamelURL *url;
+
+ const gchar * target_url = e_account_get_string(target->account, E_ACCOUNT_SOURCE_URL);
+ if (target_url && target_url[0] != '\0')
+ url = camel_url_new(target_url, NULL);
+ else
+ url = NULL;
+ /* Note: we only care about exchange url's, we WILL get called on all other url's too. */
+ if (url != NULL
+ && strcmp(url->protocol, "exchange") == 0
+ && (url->host == NULL || url->host[0] == 0))
+ status = FALSE;
+
+ if (url)
+ camel_url_free(url);
+ }
+
+ return status;
+}
+
+static void
+set_oof_info (void)
+{
+ ExchangeAccount *account;
+
+ account = exchange_operations_get_exchange_account ();
+
+ if (account && !exchange_oof_set (account, oof_data->state, oof_data->message)) {
+
+ e_error_run (NULL, ERROR_DOMAIN ":state-update-error", NULL);
+ }
+}
+
+static void
+destroy_oof_data (void)
+{
+ if (oof_data->message)
+ g_free (oof_data->message);
+ if (oof_data)
+ g_free (oof_data);
+}
+
+void
+org_gnome_exchange_commit (EPlugin *epl, EConfigHookItemFactoryData *data)
+{
+ EMConfigTargetAccount *target_account;
+ const gchar *source_url;
+ CamelURL *url;
+ gint offline_status;
+
+ target_account = (EMConfigTargetAccount *)data->config->target;
+ source_url = e_account_get_string (target_account->account, E_ACCOUNT_SOURCE_URL);
+ if (source_url && source_url[0] != '\0')
+ url = camel_url_new (source_url, NULL);
+ else
+ url = NULL;
+ if (url == NULL
+ || strcmp (url->protocol, "exchange") != 0) {
+ if (url)
+ camel_url_free (url);
+
+ return;
+ }
+ if (data->old) {
+ camel_url_free(url);
+ return;
+ }
+
+ camel_url_free (url);
+
+ exchange_config_listener_get_offline_status (exchange_global_config_listener,
+ &offline_status);
+
+ if (offline_status == OFFLINE_MODE) {
+ return;
+ }
+
+ /* Set oof data in exchange account */
+ set_oof_info ();
+ destroy_oof_data ();
+ return;
+}
+
+static void
+exchange_check_authtype (GtkWidget *w, EConfig *config)
+{
+ return;
+}
+
+static void
+exchange_authtype_changed (GtkComboBox *dropdown, EConfig *config)
+{
+ EMConfigTargetAccount *target = (EMConfigTargetAccount *)config->target;
+ gint id = gtk_combo_box_get_active(dropdown);
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ CamelServiceAuthType *authtype;
+ CamelURL *url_source, *url_transport;
+ const gchar *source_url, *transport_url;
+ gchar *source_url_string, *transport_url_string;
+
+ source_url = e_account_get_string (target->account,
+ E_ACCOUNT_SOURCE_URL);
+ if (id == -1)
+ return;
+
+ url_source = camel_url_new (source_url, NULL);
+
+ transport_url = e_account_get_string (target->account,
+ E_ACCOUNT_TRANSPORT_URL);
+ url_transport = camel_url_new (transport_url, NULL);
+
+ model = gtk_combo_box_get_model(dropdown);
+ if (gtk_tree_model_iter_nth_child(model, &iter, NULL, id)) {
+ gtk_tree_model_get(model, &iter, 1, &authtype, -1);
+ if (authtype) {
+ camel_url_set_authmech(url_source, authtype->authproto);
+ camel_url_set_authmech(url_transport, authtype->authproto);
+ }
+ else {
+ camel_url_set_authmech(url_source, NULL);
+ camel_url_set_authmech(url_transport, NULL);
+ }
+
+ source_url_string = camel_url_to_string(url_source, 0);
+ transport_url_string = camel_url_to_string(url_transport, 0);
+ e_account_set_string(target->account, E_ACCOUNT_SOURCE_URL, source_url_string);
+ e_account_set_string(target->account, E_ACCOUNT_TRANSPORT_URL, transport_url_string);
+ g_free(source_url_string);
+ g_free(transport_url_string);
+ }
+ camel_url_free(url_source);
+ camel_url_free(url_transport);
+}
+
+GtkWidget *
+org_gnome_exchange_auth_section (EPlugin *epl, EConfigHookItemFactoryData *data)
+{
+ EMConfigTargetAccount *target_account;
+ const gchar *source_url;
+ gchar *label_text, *exchange_account_authtype = NULL;
+ CamelURL *url;
+ GtkWidget *hbox, *button, *auth_label, *vbox, *label_hide;
+ GtkComboBox *dropdown;
+ GtkTreeIter iter;
+ GtkListStore *store;
+ gint i, active=0, auth_changed_id = 0;
+ GList *authtypes, *l, *ll;
+ ExchangeAccount *account;
+
+ target_account = (EMConfigTargetAccount *)data->config->target;
+ source_url = e_account_get_string (target_account->account,
+ E_ACCOUNT_SOURCE_URL);
+ url = camel_url_new (source_url, NULL);
+ if (url == NULL
+ || strcmp (url->protocol, "exchange") != 0) {
+ if (url)
+ camel_url_free (url);
+
+ return NULL;
+ }
+
+ if (data->old) {
+ camel_url_free(url);
+ return data->old;
+ }
+
+ account = exchange_operations_get_exchange_account ();
+ if (account)
+ exchange_account_authtype = exchange_account_get_authtype (account);
+
+ vbox = gtk_vbox_new (FALSE, 6);
+
+ label_text = g_strdup_printf("<b>%s</b>", _("_Authentication Type"));
+ auth_label = gtk_label_new_with_mnemonic (label_text);
+ g_free (label_text);
+ gtk_label_set_justify (GTK_LABEL (auth_label), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment (GTK_MISC (auth_label), 0, 0.5);
+ gtk_misc_set_padding (GTK_MISC (auth_label), 0, 0);
+ gtk_label_set_use_markup (GTK_LABEL (auth_label), TRUE);
+
+ label_hide = gtk_label_new("\n");
+
+ hbox = gtk_hbox_new (FALSE, 6);
+ dropdown = (GtkComboBox * )gtk_combo_box_new ();
+ gtk_label_set_mnemonic_widget (GTK_LABEL (auth_label), GTK_WIDGET (dropdown));
+
+ button = gtk_button_new_with_mnemonic (_("Ch_eck for Supported Types"));
+
+ authtypes = g_list_prepend (g_list_prepend (NULL, &camel_exchange_password_authtype),
+ &camel_exchange_ntlm_authtype);
+ store = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN);
+
+ for (i=0, l=authtypes; l; l=l->next, i++) {
+ CamelServiceAuthType *authtype = l->data;
+ gint avail = TRUE;
+
+ if (authtypes) {
+ for (ll = authtypes; ll; ll = g_list_next(ll))
+ if (!strcmp(authtype->authproto,
+ ((CamelServiceAuthType *)ll->data)->authproto))
+ break;
+ avail = ll != NULL;
+ }
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0, authtype->name, 1,
+ authtype, 2, !avail, -1);
+
+ if (url && url->authmech && !strcmp(url->authmech, authtype->authproto)) {
+ active = i;
+ }
+ else if (url && exchange_account_authtype &&
+ !strcmp (exchange_account_authtype, authtype->authproto)) {
+ /* if the url doesn't contain authmech, read the value from
+ * exchange account and set the tab selection and
+ * also set the authmech back to url
+ */
+ camel_url_set_authmech (url, exchange_account_authtype);
+ active = i;
+ }
+ }
+
+ gtk_combo_box_set_model (dropdown, (GtkTreeModel *)store);
+ gtk_combo_box_set_active (dropdown, -1);
+
+ if (auth_changed_id == 0) {
+ GtkCellRenderer *cell = gtk_cell_renderer_text_new();
+
+ gtk_cell_layout_pack_start ((GtkCellLayout *)dropdown, cell, TRUE);
+ gtk_cell_layout_set_attributes ((GtkCellLayout *)dropdown, cell,
+ "text", 0, "strikethrough", 2, NULL);
+
+ auth_changed_id = g_signal_connect (dropdown,
+ "changed",
+ G_CALLBACK (exchange_authtype_changed),
+ data->config);
+ g_signal_connect (button,
+ "clicked",
+ G_CALLBACK(exchange_check_authtype),
+ data->config);
+ }
+
+ gtk_combo_box_set_active(dropdown, active);
+
+ gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (dropdown), FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+
+ gtk_box_pack_start (GTK_BOX (vbox), auth_label, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), label_hide, TRUE, TRUE, 0);
+ gtk_widget_show_all (vbox);
+
+ gtk_box_pack_start (GTK_BOX (data->parent), vbox, TRUE, TRUE, 0);
+
+ if (url)
+ camel_url_free(url);
+ g_list_free (authtypes);
+ g_free (exchange_account_authtype);
+
+ return vbox;
+}
+
+GtkWidget *
+org_gnome_exchange_show_folder_size_factory (EPlugin *epl, EConfigHookItemFactoryData *data)
+{
+ EMConfigTargetFolder *target= (EMConfigTargetFolder *)data->config->target;
+ CamelFolder *cml_folder = target->folder;
+ CamelService *service;
+ CamelProvider *provider;
+ ExchangeAccount *account;
+ GtkWidget *lbl_size, *lbl_size_val;
+ GtkListStore *model;
+ GtkVBox *vbx;
+ GtkHBox *hbx_size;
+ gchar *folder_name, *folder_size;
+ gint mode;
+
+ service = CAMEL_SERVICE (camel_folder_get_parent_store (cml_folder));
+ if (!service)
+ return NULL;
+
+ provider = camel_service_get_provider (service);
+ if (!provider)
+ return NULL;
+
+ if (g_ascii_strcasecmp (provider->protocol, "exchange"))
+ return NULL;
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account)
+ return NULL;
+
+ exchange_account_is_offline (account, &mode);
+ if (mode == OFFLINE_MODE)
+ return NULL;
+
+ folder_name = (gchar *) camel_folder_get_name (cml_folder);
+ if (!folder_name)
+ folder_name = g_strdup ("name");
+
+ model = exchange_account_folder_size_get_model (account);
+ if (model)
+ folder_size = g_strdup_printf (_("%s KB"), exchange_folder_size_get_val (model, folder_name));
+ else
+ folder_size = g_strdup (_("0 KB"));
+
+ hbx_size = (GtkHBox*) gtk_hbox_new (FALSE, 0);
+ vbx = (GtkVBox *)gtk_notebook_get_nth_page (GTK_NOTEBOOK (data->parent), 0);
+
+ lbl_size = gtk_label_new_with_mnemonic (_("Size:"));
+ lbl_size_val = gtk_label_new_with_mnemonic (_(folder_size));
+ gtk_widget_show (lbl_size);
+ gtk_widget_show (lbl_size_val);
+ gtk_misc_set_alignment (GTK_MISC (lbl_size), 0.0, 0.5);
+ gtk_misc_set_alignment (GTK_MISC (lbl_size_val), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (hbx_size), lbl_size, FALSE, TRUE, 12);
+ gtk_box_pack_start (GTK_BOX (hbx_size), lbl_size_val, FALSE, TRUE, 10);
+ gtk_widget_show_all (GTK_WIDGET (hbx_size));
+
+ gtk_box_pack_start (GTK_BOX (vbx), GTK_WIDGET (hbx_size), FALSE, FALSE, 0);
+ g_free (folder_size);
+
+ return GTK_WIDGET (hbx_size);
+}
diff --git a/eplugin/exchange-calendar.c b/eplugin/exchange-calendar.c
new file mode 100644
index 0000000..f9f7bd7
--- /dev/null
+++ b/eplugin/exchange-calendar.c
@@ -0,0 +1,539 @@
+/*
+ * 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:
+ * Praveen Kumar <kpraveen novell com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <string.h>
+#include <gtk/gtk.h>
+#include <e-util/e-config.h>
+#include <calendar/gui/e-cal-config.h>
+#include <libedataserver/e-source.h>
+#include <libedataserver/e-url.h>
+#include <e-folder.h>
+#include <exchange-account.h>
+#include <libecal/e-cal.h>
+
+#include "calendar/gui/dialogs/calendar-setup.h"
+#include "mail/em-account-editor.h"
+#include "mail/em-config.h"
+#include "libedataserver/e-account.h"
+#include "e-util/e-error.h"
+
+#include "exchange-operations.h"
+#include "exchange-folder-size-display.h"
+
+enum {
+ CALENDARNAME_COL,
+ CALENDARRURI_COL,
+ NUM_COLS
+};
+
+gboolean calendar_src_exists = FALSE;
+gchar *calendar_old_source_uri = NULL;
+
+static GPtrArray *e_exchange_calendar_get_calendars (ECalSourceType ftype);
+void e_exchange_calendar_pcalendar_on_change (GtkTreeView *treeview, ESource *source);
+GtkWidget *e_exchange_calendar_pcalendar (EPlugin *epl, EConfigHookItemFactoryData *data);
+gboolean e_exchange_calendar_check (EPlugin *epl, EConfigHookPageCheckData *data);
+void e_exchange_calendar_commit (EPlugin *epl, EConfigTarget *target);
+
+/* FIXME: Reconsider the prototype of this function */
+static GPtrArray *
+e_exchange_calendar_get_calendars (ECalSourceType ftype)
+{
+ ExchangeAccount *account;
+ GPtrArray *folder_array;
+ GPtrArray *calendar_list;
+ EFolder *folder;
+ gint i, prefix_len;
+ gchar *type;
+ gchar *uri_prefix;
+ gchar *tmp, *ruri;
+ gchar *tstring;
+
+ /* FIXME: Compiler warns here; review needed */
+ if (ftype == E_CAL_SOURCE_TYPE_EVENT) { /* Calendars */
+ tstring = g_strdup ("calendar");
+ }
+ else if (ftype == E_CAL_SOURCE_TYPE_TODO) { /* Tasks */
+ tstring = g_strdup ("tasks");
+ }
+ else {
+ /* FIXME: Would this ever happen? If so, handle it wisely */
+ tstring = NULL;
+ }
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account)
+ return NULL;
+
+ /* FIXME: Reconsider this hardcoding */
+ uri_prefix = g_strconcat ("exchange://", account->account_filename, "/;", NULL);
+ prefix_len = strlen (uri_prefix);
+
+ calendar_list = g_ptr_array_new ();
+
+ exchange_account_rescan_tree (account);
+ folder_array = exchange_account_get_folders (account);
+
+ for (i=0; i<folder_array->len; ++i) {
+ folder = g_ptr_array_index (folder_array, i);
+ type = (gchar *)e_folder_get_type_string (folder);
+
+ if (!strcmp (type, tstring)) {
+ tmp = (gchar *)e_folder_get_physical_uri (folder);
+ if (g_str_has_prefix (tmp, uri_prefix)) {
+ ruri = g_strdup (tmp+prefix_len);
+ g_ptr_array_add (calendar_list, ruri);
+ }
+ }
+ }
+
+ if (folder_array)
+ g_ptr_array_free (folder_array, TRUE);
+ g_free (uri_prefix);
+ g_free (tstring);
+ return calendar_list;
+}
+
+void
+e_exchange_calendar_pcalendar_on_change (GtkTreeView *treeview, ESource *source)
+{
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ ExchangeAccount *account;
+ gchar *es_ruri, *ruri;
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account)
+ return;
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
+ gtk_tree_selection_get_selected(selection, &model, &iter);
+
+ gtk_tree_model_get (model, &iter, CALENDARRURI_COL, &ruri, -1);
+ es_ruri = g_strconcat (account->account_filename, "/;", ruri, NULL);
+ e_source_set_relative_uri (source, es_ruri);
+ g_free (ruri);
+ g_free (es_ruri);
+}
+
+GtkWidget *
+e_exchange_calendar_pcalendar (EPlugin *epl, EConfigHookItemFactoryData *data)
+{
+ static GtkWidget *lbl_pcalendar, *scrw_pcalendar, *tv_pcalendar, *lbl_size, *lbl_size_val;
+ static GtkWidget *hidden = NULL;
+ GtkWidget *parent;
+ GtkTreeStore *ts_pcalendar;
+ GtkCellRenderer *cr_calendar;
+ GtkTreeViewColumn *tvc_calendar;
+ GtkListStore *model;
+ GPtrArray *callist;
+ ECalConfigTargetSource *t = (ECalConfigTargetSource *) data->target;
+ ESource *source = t->source;
+ EUri *uri;
+ ExchangeAccount *account;
+ gchar *ruri;
+ gchar *account_name;
+ gchar *uri_text;
+ gchar *cal_name;
+ gchar *folder_size;
+ const gchar *rel_uri;
+ gint row, i;
+ gint offline_status;
+ gchar *offline_msg;
+ GtkWidget *lbl_offline_msg;
+ gboolean is_personal;
+
+ if (!hidden)
+ hidden = gtk_label_new ("");
+
+ if (data->old) {
+ /* FIXME: Review this */
+ gtk_widget_destroy (lbl_pcalendar);
+ gtk_widget_destroy (scrw_pcalendar);
+ gtk_widget_destroy (tv_pcalendar);
+ }
+
+ uri_text = e_source_get_uri (t->source);
+ uri = e_uri_new (uri_text);
+
+ if (uri && strcmp (uri->protocol, "exchange")) {
+ e_uri_free (uri);
+ g_free (uri_text);
+ return hidden;
+ }
+
+ e_uri_free (uri);
+
+ parent = data->parent;
+ row = ((GtkTable*)parent)->nrows;
+
+ exchange_config_listener_get_offline_status (exchange_global_config_listener,
+ &offline_status);
+ if (offline_status == OFFLINE_MODE) {
+ /* Evolution is in offline mode; we will not be able to create
+ new folders or modify existing folders. */
+ offline_msg = g_markup_printf_escaped ("<b>%s</b>",
+ _("Evolution is in offline mode. You cannot create or modify folders now.\nPlease switch to online mode for such operations."));
+ lbl_offline_msg = gtk_label_new ("");
+ gtk_label_set_markup (GTK_LABEL (lbl_offline_msg), offline_msg);
+ g_free (offline_msg);
+ gtk_widget_show (lbl_offline_msg);
+ gtk_table_attach (GTK_TABLE (parent), lbl_offline_msg, 0, 2, row, row+1, GTK_FILL|GTK_EXPAND, 0, 0, 0);
+ g_free (uri_text);
+ return lbl_offline_msg;
+ }
+
+ rel_uri = e_source_peek_relative_uri (t->source);
+ if (rel_uri && strlen (rel_uri)) {
+ calendar_src_exists = TRUE;
+ g_free (calendar_old_source_uri);
+ calendar_old_source_uri = g_strdup (rel_uri);
+ }
+ else {
+ calendar_src_exists = FALSE;
+ }
+
+ /* REVIEW: Should this handle be freed? - Attn: surf */
+ account = exchange_operations_get_exchange_account ();
+ if (!account) {
+ g_free (calendar_old_source_uri);
+ g_free (uri_text);
+ return NULL;
+ }
+ account_name = account->account_name;
+ is_personal = is_exchange_personal_folder (account, uri_text);
+ g_free (uri_text);
+
+ if (calendar_src_exists && is_personal) {
+ cal_name = (gchar *) e_source_peek_name (source);
+ model = exchange_account_folder_size_get_model (account);
+ if (model)
+ folder_size = g_strdup_printf ("%s KB", exchange_folder_size_get_val (model, cal_name));
+ else
+ folder_size = g_strdup ("0 KB");
+
+ /* FIXME: Take care of i18n */
+ lbl_size = gtk_label_new_with_mnemonic (_("Size:"));
+ lbl_size_val = gtk_label_new_with_mnemonic (_(folder_size));
+ gtk_widget_show (lbl_size);
+ gtk_widget_show (lbl_size_val);
+ gtk_misc_set_alignment (GTK_MISC (lbl_size), 0.0, 0.5);
+ gtk_misc_set_alignment (GTK_MISC (lbl_size_val), 0.0, 0.5);
+ gtk_table_attach (GTK_TABLE (parent), lbl_size, 0, 2, row, row+1, GTK_FILL|GTK_EXPAND, 0, 0, 0);
+ gtk_table_attach (GTK_TABLE (parent), lbl_size_val, 1, 3, row, row+1, GTK_FILL|GTK_EXPAND, 0, 0, 0);
+ g_free (folder_size);
+ }
+
+ lbl_pcalendar = gtk_label_new_with_mnemonic (_("_Location:"));
+ gtk_widget_show (lbl_pcalendar);
+ gtk_misc_set_alignment (GTK_MISC (lbl_pcalendar), 0.0, 0.5);
+ gtk_table_attach (GTK_TABLE (parent), lbl_pcalendar, 0, 2, row+1, row+2, GTK_FILL|GTK_EXPAND, 0, 0, 0);
+
+ ts_pcalendar = gtk_tree_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_STRING);
+
+ callist = e_exchange_calendar_get_calendars (t->source_type);
+
+ if (callist) {
+ for (i = 0; i < callist->len; i++) {
+ ruri = g_ptr_array_index (callist, i);
+ exchange_operations_cta_add_node_to_tree (ts_pcalendar, NULL, ruri);
+ }
+ g_ptr_array_free (callist, TRUE);
+ }
+
+ cr_calendar = gtk_cell_renderer_text_new ();
+ tvc_calendar = gtk_tree_view_column_new_with_attributes (account_name, cr_calendar, "text", CALENDARNAME_COL, NULL);
+ tv_pcalendar = gtk_tree_view_new_with_model (GTK_TREE_MODEL (ts_pcalendar));
+ gtk_tree_view_append_column (GTK_TREE_VIEW (tv_pcalendar), tvc_calendar);
+ g_object_set (tv_pcalendar, "expander-column", tvc_calendar, "headers-visible", TRUE, NULL);
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (tv_pcalendar));
+
+ scrw_pcalendar = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrw_pcalendar), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrw_pcalendar), GTK_SHADOW_IN);
+ g_object_set (scrw_pcalendar, "height-request", 150, NULL);
+ gtk_container_add (GTK_CONTAINER (scrw_pcalendar), tv_pcalendar);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (lbl_pcalendar), tv_pcalendar);
+ g_signal_connect (G_OBJECT (tv_pcalendar), "cursor-changed", G_CALLBACK (e_exchange_calendar_pcalendar_on_change), t->source);
+
+ gtk_table_attach (GTK_TABLE (parent), scrw_pcalendar, 0, 2, row+2, row+3, GTK_EXPAND|GTK_FILL, 0, 0, 0);
+ gtk_widget_show_all (scrw_pcalendar);
+
+ if (calendar_src_exists) {
+ gchar *uri_prefix, *sruri, *tmpruri;
+ gint prefix_len;
+ GtkTreeSelection *selection;
+
+ uri_prefix = g_strconcat (account->account_filename, "/;", NULL);
+ prefix_len = strlen (uri_prefix);
+
+ tmpruri = (gchar *) rel_uri;
+
+ if (g_str_has_prefix (tmpruri, uri_prefix)) {
+ sruri = g_strdup (tmpruri+prefix_len);
+ }
+ else {
+ sruri = NULL;
+ }
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv_pcalendar));
+ exchange_operations_cta_select_node_from_tree (ts_pcalendar, NULL, sruri, sruri, selection);
+ gtk_widget_set_sensitive (tv_pcalendar, FALSE);
+ g_free (uri_prefix);
+ g_free (sruri);
+ }
+
+ g_object_unref (ts_pcalendar);
+ return tv_pcalendar;
+}
+
+gboolean
+e_exchange_calendar_check (EPlugin *epl, EConfigHookPageCheckData *data)
+{
+ /* FIXME - check pageid */
+ ECalConfigTargetSource *t = (ECalConfigTargetSource *) data->target;
+ ESourceGroup *group;
+ const gchar *base_uri;
+ const gchar *rel_uri;
+ gint offline_status;
+ ExchangeAccount *account;
+ EUri *euri;
+ gint uri_len;
+ gchar *uri_text, *uri_string, *path, *folder_name;
+ gboolean is_personal;
+
+ rel_uri = e_source_peek_relative_uri (t->source);
+ group = e_source_peek_group (t->source);
+ base_uri = e_source_group_peek_base_uri (group);
+ exchange_config_listener_get_offline_status (exchange_global_config_listener,
+ &offline_status);
+ if (base_uri && !strncmp (base_uri, "exchange", 8)) {
+ if (offline_status == OFFLINE_MODE)
+ return FALSE;
+ if (rel_uri && !strlen (rel_uri))
+ return FALSE;
+ }
+ else {
+ return TRUE;
+ }
+
+ if (!calendar_src_exists) {
+ /* new folder */
+ return TRUE;
+ }
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account)
+ return FALSE;
+
+ uri_text = e_source_get_uri (t->source);
+ euri = e_uri_new (uri_text);
+ uri_string = e_uri_to_string (euri, FALSE);
+ e_uri_free (euri);
+
+ is_personal = is_exchange_personal_folder (account, uri_text);
+
+ uri_len = strlen (uri_string) + 1;
+ g_free (uri_string);
+ path = g_build_filename ("/", uri_text + uri_len, NULL);
+ g_free (uri_text);
+ folder_name = g_strdup (g_strrstr (path, "/") +1);
+ g_free (path);
+
+ if (strcmp (folder_name, e_source_peek_name (t->source))) {
+ /* rename */
+ if (exchange_account_get_standard_uri (account, folder_name) ||
+ !is_personal) {
+ /* rename of standard/non-personal folder */
+ g_free (folder_name);
+ return FALSE;
+ }
+ }
+ g_free (folder_name);
+
+ return TRUE;
+}
+
+void
+e_exchange_calendar_commit (EPlugin *epl, EConfigTarget *target)
+{
+ ECalConfigTargetSource *t = (ECalConfigTargetSource *) target;
+ ESource *source = t->source;
+ gchar *uri_text, *gruri, *gname, *ruri, *ftype, *path, *path_prefix, *oldpath=NULL;
+ gchar *username, *windows_domain, *authtype;
+ gint prefix_len;
+ ExchangeAccount *account;
+ ExchangeAccountFolderResult result;
+ ExchangeConfigListenerStatus status;
+ gint offline_status;
+ gboolean rename = FALSE;
+
+ uri_text = e_source_get_uri (source);
+ if (uri_text && strncmp (uri_text, "exchange", 8)) {
+ g_free (uri_text);
+ return;
+ }
+
+ status = exchange_is_offline (&offline_status);
+ if (offline_status == OFFLINE_MODE || status != CONFIG_LISTENER_STATUS_OK) {
+ g_free (uri_text);
+ return;
+ }
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account || !is_exchange_personal_folder (account, uri_text))
+ return;
+
+ windows_domain = exchange_account_get_windows_domain (account);
+ if (windows_domain)
+ username = g_strdup_printf ("%s\\%s", windows_domain,
+ exchange_account_get_username (account));
+ else
+ username = g_strdup (exchange_account_get_username (account));
+
+ authtype = exchange_account_get_authtype (account);
+
+ path_prefix = g_strconcat (account->account_filename, "/;", NULL);
+ prefix_len = strlen (path_prefix);
+ g_free (path_prefix);
+
+ /* FIXME: Compiler gives a warning here; review needed */
+ if (t->source_type == E_CAL_SOURCE_TYPE_EVENT) {
+ ftype = g_strdup ("calendar");
+ }
+ else if (t->source_type == E_CAL_SOURCE_TYPE_TODO) {
+ ftype = g_strdup ("tasks");
+ }
+ else {
+ /* FIXME: This one would ever occur? */
+ ftype = g_strdup ("mail");
+ }
+
+ gname = (gchar *) e_source_peek_name (source);
+ gruri = (gchar *) e_source_peek_relative_uri (source);
+
+ if (calendar_src_exists) {
+ gchar *tmpruri, *uri_string, *temp_path, *prefix;
+ EUri *euri;
+ gint uri_len;
+
+ /* sample uri_string: exchange://user;auth=NTLM host/ */
+ /* sample uri_text: exchange://user;auth=NTLM host/;personal/Calendar */
+
+ euri = e_uri_new (uri_text);
+ uri_string = e_uri_to_string (euri, FALSE);
+ e_uri_free (euri);
+
+ /* sample gruri: user;auth=NTLM host/;personal/Calendar */
+ /* sample ruri: user;auth=NTLM host/personal/Calendar */
+ /* sample path: /personal/Calendar */
+
+ uri_len = strlen (uri_string) + 1;
+ tmpruri = g_strdup (uri_string + strlen ("exchange://"));
+ temp_path = g_build_filename ("/", uri_text + uri_len, NULL);
+ prefix = g_strndup (temp_path, strlen (temp_path) - strlen (g_strrstr (temp_path, "/")));
+ g_free (temp_path);
+ path = g_build_filename (prefix, "/", gname, NULL);
+ ruri = g_strconcat (tmpruri, ";", path+1, NULL);
+ oldpath = g_build_filename ("/", calendar_old_source_uri + prefix_len, NULL);
+ g_free (prefix);
+ g_free (uri_string);
+ g_free (tmpruri);
+ }
+ else {
+ /* new folder */
+ ruri = g_strconcat (gruri, "/", gname, NULL);
+ path = g_build_filename ("/", ruri+prefix_len, NULL);
+ }
+
+ if (!calendar_src_exists) {
+ /* Create the new folder */
+ result = exchange_account_create_folder (account, path, ftype);
+ }
+ else if (gruri && strcmp (path, oldpath)) {
+ /* Rename the folder */
+ rename = TRUE;
+ result = exchange_account_xfer_folder (account, oldpath, path, TRUE);
+ }
+ else {
+ /* Nothing happened specific to exchange; just return */
+ goto done;
+ }
+
+ switch (result) {
+ case EXCHANGE_ACCOUNT_FOLDER_OK:
+ if (result == EXCHANGE_ACCOUNT_FOLDER_OK) {
+ e_source_set_name (source, gname);
+ e_source_set_relative_uri (source, ruri);
+ e_source_set_property (source, "username", username);
+ e_source_set_property (source, "auth-domain", "Exchange");
+ if (authtype) {
+ e_source_set_property (source, "auth-type", authtype);
+ g_free (authtype);
+ authtype=NULL;
+ }
+ e_source_set_property (source, "auth", "1");
+ if (rename) {
+ exchange_operations_update_child_esources (source,
+ calendar_old_source_uri,
+ ruri);
+ }
+ }
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_ALREADY_EXISTS:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-exists-error", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-doesnt-exist-error", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_UNKNOWN_TYPE:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-unknown-type", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-perm-error", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_OFFLINE:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-offline-error", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_UNSUPPORTED_OPERATION:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-unsupported-error", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-generic-error", NULL);
+ break;
+ default:
+ break;
+ }
+
+done:
+ g_free (uri_text);
+ g_free (username);
+ if (authtype)
+ g_free (authtype);
+ g_free (ruri);
+ g_free (path);
+ g_free (ftype);
+ g_free (oldpath);
+ g_free (calendar_old_source_uri);
+ calendar_old_source_uri = NULL;
+}
diff --git a/eplugin/exchange-change-password.c b/eplugin/exchange-change-password.c
new file mode 100644
index 0000000..68e93ab
--- /dev/null
+++ b/eplugin/exchange-change-password.c
@@ -0,0 +1,194 @@
+/*
+ *
+ * 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/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+/* exchange-change-password: Change Password code */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "exchange-change-password.h"
+
+#include <exchange-account.h>
+#include <e2k-utils.h>
+
+#include <gtk/gtk.h>
+
+static void
+entry_changed (GtkEntry *entry, gpointer user_data)
+{
+ GtkEntry *new_entry, *confirm_entry;
+ GtkDialog *pass_dialog;
+ const gchar *text;
+
+ new_entry = GTK_ENTRY (entry);
+ confirm_entry = GTK_ENTRY (user_data);
+ pass_dialog = GTK_DIALOG (g_object_get_data (G_OBJECT (new_entry), "pass_dialog"));
+
+ text = gtk_entry_get_text (new_entry);
+ if (!text || !*text) {
+ gtk_dialog_set_response_sensitive (pass_dialog, GTK_RESPONSE_OK, FALSE);
+ return;
+ }
+
+ text = gtk_entry_get_text (confirm_entry);
+ if (!text || !*text) {
+ gtk_dialog_set_response_sensitive (pass_dialog, GTK_RESPONSE_OK, FALSE);
+ return;
+ }
+
+ gtk_dialog_set_response_sensitive (pass_dialog, GTK_RESPONSE_OK, TRUE);
+}
+
+/**
+ * exchange_get_new_password:
+ * @existing_password: The user's current password
+ * @voluntary: %TRUE if the user has chosen "Change Password",
+ * %FALSE if their old password has expired.
+ *
+ * Prompt the user for a new password.
+ */
+gchar *
+exchange_get_new_password (const gchar *existing_password, gboolean voluntary)
+{
+ GtkResponseType response;
+ gchar *new_pass;
+ GtkWidget *pass_dialog;
+ GtkWidget *dialog_vbox1;
+ GtkWidget *pass_label;
+ GtkWidget *table1;
+ GtkWidget *current_pass_label;
+ GtkWidget *new_pass_label;
+ GtkWidget *confirm_pass_label;
+ GtkWidget *current_pass_entry;
+ GtkWidget *new_pass_entry;
+ GtkWidget *confirm_pass_entry;
+
+ pass_dialog = gtk_dialog_new_with_buttons (
+ _("Change Password"),
+ NULL,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+
+ dialog_vbox1 = gtk_dialog_get_content_area (GTK_DIALOG (pass_dialog));
+ gtk_widget_show (dialog_vbox1);
+
+ pass_label = gtk_label_new (_("Your current password has expired. Please change your password now."));
+ gtk_widget_show (pass_label);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox1), pass_label, FALSE, FALSE, 0);
+ gtk_label_set_justify (GTK_LABEL (pass_label), GTK_JUSTIFY_CENTER);
+ gtk_label_set_line_wrap (GTK_LABEL (pass_label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (pass_label), 0.52, 0.5);
+ gtk_misc_set_padding (GTK_MISC (pass_label), 0, 6);
+
+ table1 = gtk_table_new (3, 2, FALSE);
+ gtk_widget_show (table1);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox1), table1, TRUE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (table1), 6);
+ gtk_table_set_row_spacings (GTK_TABLE (table1), 6);
+ gtk_table_set_col_spacings (GTK_TABLE (table1), 6);
+
+ current_pass_label = gtk_label_new_with_mnemonic (_("Current _Password:"));
+ gtk_widget_show (current_pass_label);
+ gtk_table_attach (GTK_TABLE (table1), current_pass_label, 0, 1, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (current_pass_label), 0, 0.5);
+
+ new_pass_label = gtk_label_new_with_mnemonic (_("_New Password:"));
+ gtk_widget_show (new_pass_label);
+ gtk_table_attach (GTK_TABLE (table1), new_pass_label, 0, 1, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (new_pass_label), 0, 0.5);
+
+ confirm_pass_label = gtk_label_new_with_mnemonic (_("_Confirm Password:"));
+ gtk_widget_show (confirm_pass_label);
+ gtk_table_attach (GTK_TABLE (table1), confirm_pass_label, 0, 1, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (confirm_pass_label), 0, 0.5);
+
+ new_pass_entry = gtk_entry_new ();
+ gtk_widget_show (new_pass_entry);
+ gtk_table_attach (GTK_TABLE (table1), new_pass_entry, 1, 2, 1, 2,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_entry_set_visibility (GTK_ENTRY (new_pass_entry), FALSE);
+
+ confirm_pass_entry = gtk_entry_new ();
+ gtk_widget_show (confirm_pass_entry);
+ gtk_table_attach (GTK_TABLE (table1), confirm_pass_entry, 1, 2, 2, 3,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_entry_set_visibility (GTK_ENTRY (confirm_pass_entry), FALSE);
+
+ current_pass_entry = gtk_entry_new ();
+ gtk_widget_show (current_pass_entry);
+ gtk_table_attach (GTK_TABLE (table1), current_pass_entry, 1, 2, 0, 1,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (0), 0, 12);
+ gtk_entry_set_visibility (GTK_ENTRY (current_pass_entry), FALSE);
+
+ g_object_set_data (G_OBJECT (new_pass_entry), "pass_dialog", pass_dialog);
+ g_object_set_data (G_OBJECT (confirm_pass_entry), "pass_dialog", pass_dialog);
+ g_signal_connect (new_pass_entry, "changed", G_CALLBACK (entry_changed), confirm_pass_entry);
+ g_signal_connect (confirm_pass_entry, "changed", G_CALLBACK (entry_changed), new_pass_entry);
+ entry_changed (GTK_ENTRY (new_pass_entry), confirm_pass_entry);
+
+ if (voluntary)
+ gtk_widget_hide (GTK_WIDGET (pass_label));
+
+run_dialog_again:
+ response = gtk_dialog_run (GTK_DIALOG (pass_dialog));
+ if (response == GTK_RESPONSE_OK) {
+ const gchar *cur_pass, *new_pass1, *new_pass2;
+
+ cur_pass = gtk_entry_get_text (GTK_ENTRY (current_pass_entry));
+ new_pass1 = gtk_entry_get_text (GTK_ENTRY (new_pass_entry));
+ new_pass2 = gtk_entry_get_text (GTK_ENTRY (confirm_pass_entry));
+
+ if (existing_password) {
+ if (strcmp (cur_pass, existing_password) != 0) {
+ /* User entered a wrong existing
+ * password. Prompt him again.
+ */
+ gtk_label_set_text (GTK_LABEL (pass_label), _("The current password does not match the existing password for your account. Please enter the correct password"));
+ gtk_widget_show (pass_label);
+ goto run_dialog_again;
+ }
+ }
+
+ if (strcmp (new_pass1, new_pass2) != 0) {
+ gtk_label_set_text (GTK_LABEL (pass_label), _("The two passwords do not match. Please re-enter the passwords."));
+ gtk_widget_show (pass_label);
+ goto run_dialog_again;
+ }
+
+ new_pass = g_strdup (new_pass1);
+ } else
+ new_pass = NULL;
+
+ gtk_widget_destroy (pass_dialog);
+
+ return new_pass;
+}
diff --git a/eplugin/exchange-change-password.h b/eplugin/exchange-change-password.h
new file mode 100644
index 0000000..c33a887
--- /dev/null
+++ b/eplugin/exchange-change-password.h
@@ -0,0 +1,33 @@
+/*
+ *
+ * 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/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __EXCHANGE_CHANGE_PASSWORD_H__
+#define __EXCHANGE_CHANGE_PASSWORD_H__
+
+#include <exchange-types.h>
+
+G_BEGIN_DECLS
+
+gchar *exchange_get_new_password (const gchar *existing_password,
+ gboolean voluntary);
+
+G_END_DECLS
+
+#endif /* __EXCHANGE_CHANGE_PASSWORD_H__ */
diff --git a/eplugin/exchange-config-listener.c b/eplugin/exchange-config-listener.c
new file mode 100644
index 0000000..dc6582b
--- /dev/null
+++ b/eplugin/exchange-config-listener.c
@@ -0,0 +1,1520 @@
+/*
+ * ExchangeConfigListener: a class that listens to the config database
+ * and handles creating the ExchangeAccount object and making sure that
+ * default folders are updated as needed.
+ *
+ * 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/>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "exchange-config-listener.h"
+#include "exchange-operations.h"
+#include "exchange-change-password.h"
+
+#include <exchange-constants.h>
+#include <exchange-hierarchy.h>
+#include <exchange-oof.h>
+#include <e-folder-exchange.h>
+#include <e2k-marshal.h>
+#include <e2k-uri.h>
+#include <camel/camel-url.h>
+
+#include <e-util/e-error.h>
+
+#include <libedataserver/e-source.h>
+#include <libedataserver/e-source-list.h>
+#include <libedataserver/e-source-group.h>
+#include <libedataserverui/e-passwords.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+struct _ExchangeConfigListenerPrivate {
+ GConfClient *gconf;
+ guint idle_id;
+
+ gchar *configured_uri, *configured_name;
+ EAccount *configured_account;
+
+ ExchangeAccount *exchange_account;
+};
+
+typedef struct {
+ const gchar *name;
+ const gchar *uri;
+ gint type;
+}FolderInfo;
+
+enum {
+ EXCHANGE_ACCOUNT_CREATED,
+ EXCHANGE_ACCOUNT_REMOVED,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+#define PARENT_TYPE E_TYPE_ACCOUNT_LIST
+
+#define CONF_KEY_SELECTED_CAL_SOURCES "/apps/evolution/calendar/display/selected_calendars"
+#define CONF_KEY_SELECTED_TASKS_SOURCES "/apps/evolution/calendar/tasks/selected_tasks"
+
+static EAccountListClass *parent_class = NULL;
+
+static void dispose (GObject *object);
+static void finalize (GObject *object);
+
+static void account_added (EAccountList *account_listener,
+ EAccount *account);
+static void account_changed (EAccountList *account_listener,
+ EAccount *account);
+static void account_removed (EAccountList *account_listener,
+ EAccount *account);
+#ifdef LDEAD
+static void exchange_add_autocompletion_folders (GConfClient *gc_client,
+ ExchangeAccount *account);
+#endif
+static gboolean exchange_camel_urls_is_equal (const gchar *url1,
+ const gchar *url2);
+static void remove_selected_non_offline_esources (ExchangeAccount *account,
+ const gchar *gconf_key);
+static void
+class_init (GObjectClass *object_class)
+{
+ EAccountListClass *e_account_list_class =
+ E_ACCOUNT_LIST_CLASS (object_class);
+
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ /* virtual method override */
+ object_class->dispose = dispose;
+ object_class->finalize = finalize;
+
+ e_account_list_class->account_added = account_added;
+ e_account_list_class->account_changed = account_changed;
+ e_account_list_class->account_removed = account_removed;
+
+ /* signals */
+ signals[EXCHANGE_ACCOUNT_CREATED] =
+ g_signal_new ("exchange_account_created",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ExchangeConfigListenerClass, exchange_account_created),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1,
+ G_TYPE_POINTER);
+ signals[EXCHANGE_ACCOUNT_REMOVED] =
+ g_signal_new ("exchange_account_removed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ExchangeConfigListenerClass, exchange_account_removed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1,
+ G_TYPE_POINTER);
+}
+
+static void
+init (GObject *object)
+{
+ ExchangeConfigListener *config_listener =
+ EXCHANGE_CONFIG_LISTENER (object);
+
+ config_listener->priv = g_new0 (ExchangeConfigListenerPrivate, 1);
+}
+
+static void
+dispose (GObject *object)
+{
+ ExchangeConfigListener *config_listener =
+ EXCHANGE_CONFIG_LISTENER (object);
+
+ if (config_listener->priv->idle_id) {
+ g_source_remove (config_listener->priv->idle_id);
+ config_listener->priv->idle_id = 0;
+ }
+
+ if (config_listener->priv->gconf) {
+ g_object_unref (config_listener->priv->gconf);
+ config_listener->priv->gconf = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+ ExchangeConfigListener *config_listener =
+ EXCHANGE_CONFIG_LISTENER (object);
+
+ g_free (config_listener->priv->configured_name);
+ g_free (config_listener->priv->configured_uri);
+ g_free (config_listener->priv);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+E2K_MAKE_TYPE (exchange_config_listener, ExchangeConfigListener, class_init, init, PARENT_TYPE)
+
+#define EVOLUTION_URI_PREFIX "evolution:/"
+#define EVOLUTION_URI_PREFIX_LEN (sizeof (EVOLUTION_URI_PREFIX) - 1)
+
+static EFolder *
+standard_folder (ExchangeAccount *account, const gchar *folder_type)
+{
+ const gchar *uri;
+
+ uri = exchange_account_get_standard_uri (account, folder_type);
+ if (!uri)
+ return NULL;
+ return exchange_account_get_folder (account, uri);
+}
+
+static void
+set_special_mail_folder (ExchangeAccount *account, const gchar *folder_type,
+ gchar **folder_uri)
+{
+ EFolder *folder;
+ const gchar *physical_uri;
+ gchar *url_string, *path;
+ CamelURL *camel_url;
+ gint uri_len;
+
+ folder = standard_folder (account, folder_type);
+ if (!folder)
+ return;
+ physical_uri = e_folder_get_physical_uri (folder);
+
+ /* remove; form the uri */
+ camel_url = camel_url_new (physical_uri, NULL);
+ url_string = camel_url_to_string (camel_url, CAMEL_URL_HIDE_ALL);
+ camel_url_free (camel_url);
+ /* sample physical uri: exchange://pnayak;auth=NTLM 164 99 168 136/;personal/Drafts */
+ /* sample url_string: exchange://pnayak;auth=NTLM 164 99 168 136/ */
+ /* sample path: personal/Drafts */
+ uri_len = strlen (url_string) + 1;
+ path = g_build_filename (physical_uri + uri_len, NULL);
+ *folder_uri = g_strconcat (url_string, path, NULL);
+ g_free (path);
+ g_free (url_string);
+}
+
+static void
+add_defaults_for_account (ExchangeConfigListener *config_listener,
+ E2kContext *ctx,
+ ExchangeAccount *account)
+{
+ EAccount *eaccount;
+ gboolean save = FALSE;
+
+#ifdef LDEAD
+ exchange_add_autocompletion_folders (config_listener->priv->gconf, account);
+#endif
+
+ /* FIXME: set exchange account's sent items and drafts folders, by default */
+ eaccount = config_listener->priv->configured_account;
+ if (!e_account_get_string (eaccount, E_ACCOUNT_DRAFTS_FOLDER_URI)) {
+ set_special_mail_folder (account, "drafts",
+ &eaccount->drafts_folder_uri);
+ save = TRUE;
+ }
+ if (!e_account_get_string (eaccount, E_ACCOUNT_SENT_FOLDER_URI)) {
+ set_special_mail_folder (account, "sentitems",
+ &eaccount->sent_folder_uri);
+ save = TRUE;
+ }
+ if (save) {
+ e_account_list_change (E_ACCOUNT_LIST (config_listener), eaccount);
+ e_account_list_save (E_ACCOUNT_LIST (config_listener));
+ }
+}
+
+static gboolean
+is_active_exchange_account (EAccount *account)
+{
+ if (!account->enabled)
+ return FALSE;
+ if (!account->source || !account->source->url)
+ return FALSE;
+ return (strncmp (account->source->url, EXCHANGE_URI_PREFIX, 11) == 0);
+}
+
+#if 0 /* Not using the following code anywhere for the moment */
+static void
+add_account_esources (ExchangeAccount *account,
+ GSList *folders)
+{
+ ESource *source = NULL;
+ ESourceGroup *cal_source_group = NULL;
+ ESourceGroup *tasks_source_group = NULL;
+ ESourceGroup *contacts_source_group = NULL;
+ gchar *relative_uri = NULL, *username = NULL;
+#if 0
+ GSList *ids;
+#endif
+ GConfClient *client;
+ gint mode;
+ ESourceList *cal_source_list, *tasks_source_list, *contacts_source_list;
+ FolderInfo *folder=NULL;
+ gboolean offline_mode = FALSE;
+
+ client = gconf_client_get_default ();
+
+ cal_source_list = e_source_list_new_for_gconf ( client, CONF_KEY_CAL);
+ tasks_source_list = e_source_list_new_for_gconf ( client, CONF_KEY_TASKS);
+ contacts_source_list = e_source_list_new_for_gconf ( client, CONF_KEY_CONTACTS);
+
+ exchange_account_is_offline_sync_set (account, &mode);
+ if (mode == OFFLINE_MODE) {
+ /* If account is marked for offline sync during account
+ * creation, mark all the folders for offline sync
+ */
+ offline_mode = TRUE;
+ }
+
+ username = exchange_account_get_username (account);
+
+ /* For each component create a source group */
+
+ cal_source_group = e_source_group_new (account->account_name,
+ EXCHANGE_URI_PREFIX);
+ tasks_source_group = e_source_group_new (account->account_name,
+ EXCHANGE_URI_PREFIX);
+ contacts_source_group = e_source_group_new (account->account_name,
+ EXCHANGE_URI_PREFIX);
+
+ if (!e_source_list_add_group (contacts_source_list, contacts_source_group, -1) ||
+ !e_source_list_add_group (cal_source_list, cal_source_group, -1) ||
+ !e_source_list_add_group (tasks_source_list, tasks_source_group, -1)) {
+ goto done;
+ }
+ for (; folders != NULL; folders = g_slist_next (folders)) {
+ /* Create source for each folder and add to the group */
+
+ folder = folders->data;
+ if (folder->type == EXCHANGE_CONTACTS_FOLDER) {
+ source = e_source_new_with_absolute_uri (folder->name,
+ folder->uri);
+ if (offline_mode)
+ e_source_set_property (source, "offline_sync", "1");
+ if (username)
+ e_source_set_property (source, "username", username);
+ e_source_set_property (source, "auth", "1");
+ e_source_set_property (source, "auth-domain", "Exchange");
+ e_source_group_add_source (contacts_source_group,
+ source, -1);
+ g_object_unref (source);
+ }
+ else if (folder->type == EXCHANGE_CALENDAR_FOLDER) {
+ relative_uri = g_strdup (folder->uri +
+ strlen (EXCHANGE_URI_PREFIX));
+ source = e_source_new (folder->name, relative_uri);
+ if (offline_mode)
+ e_source_set_property (source, "offline_sync", "1");
+ if (username)
+ e_source_set_property (source, "username", username);
+ e_source_set_property (source, "auth", "1");
+ e_source_set_property (source, "auth-domain", "Exchange");
+ e_source_group_add_source (cal_source_group,
+ source, -1);
+#if 0
+ ids = gconf_client_get_list (client,
+ CONF_KEY_SELECTED_CAL_SOURCES,
+ GCONF_VALUE_STRING, NULL);
+ ids = g_slist_append (ids,
+ g_strdup (e_source_peek_uid (source)));
+ gconf_client_set_list (client,
+ CONF_KEY_SELECTED_CAL_SOURCES,
+ GCONF_VALUE_STRING, ids, NULL);
+ g_slist_foreach (ids, (GFunc) g_free, NULL);
+ g_slist_free (ids);
+#endif
+ g_object_unref (source);
+ g_free (relative_uri);
+
+ }
+ else if (folder->type == EXCHANGE_TASKS_FOLDER) {
+ relative_uri = g_strdup (folder->uri +
+ strlen (EXCHANGE_URI_PREFIX));
+ source = e_source_new (folder->name, relative_uri);
+ if (offline_mode == ONLINE_MODE)
+ e_source_set_property (source, "offline_sync", "1");
+ if (username)
+ e_source_set_property (source, "username", username);
+ e_source_set_property (source, "auth", "1");
+ e_source_set_property (source, "auth-domain", "Exchange");
+ e_source_group_add_source (tasks_source_group,
+ source, -1);
+#if 0
+ ids = gconf_client_get_list (client,
+ CONF_KEY_SELECTED_TASKS_SOURCES,
+ GCONF_VALUE_STRING, NULL);
+ ids = g_slist_append (ids,
+ g_strdup (e_source_peek_uid (source)));
+ gconf_client_set_list (client,
+ CONF_KEY_SELECTED_TASKS_SOURCES,
+ GCONF_VALUE_STRING, ids, NULL);
+ g_slist_foreach (ids, (GFunc) g_free, NULL);
+ g_slist_free (ids);
+#endif
+ g_object_unref (source);
+ g_free (relative_uri);
+ }
+ }
+
+ e_source_list_sync (cal_source_list, NULL);
+ e_source_list_sync (tasks_source_list, NULL);
+ e_source_list_sync (contacts_source_list, NULL);
+
+done:
+ g_object_unref (cal_source_group);
+ g_object_unref (tasks_source_group);
+ g_object_unref (contacts_source_group);
+
+ g_object_unref (cal_source_list);
+ g_object_unref (tasks_source_list);
+ g_object_unref (contacts_source_list);
+
+ g_object_unref (client);
+}
+
+static void
+add_new_sources (ExchangeAccount *account)
+{
+ GPtrArray *exchange_folders;
+
+ exchange_folders = exchange_account_get_folders (account);
+ if (exchange_folders && exchange_folders->len > 0) {
+ gint i;
+ const gchar *folder_type;
+ const gchar *folder_name;
+ const gchar *folder_uri;
+ gint type;
+ EFolder *folder;
+ ExchangeHierarchy *hier;
+ gboolean create_esource = FALSE;
+
+ for (i = 0; i < exchange_folders->len; i++) {
+
+ folder = exchange_folders->pdata[i];
+ hier = e_folder_exchange_get_hierarchy (folder);
+ if (hier->type != EXCHANGE_HIERARCHY_PUBLIC) {
+ folder_name = e_folder_get_name (folder);
+ folder_uri = e_folder_get_physical_uri (folder);
+ folder_type = e_folder_get_type_string (folder);
+
+ if (!(strcmp (folder_type, "calendar")) ||
+ !(strcmp (folder_type, "calendar/public"))) {
+ type = EXCHANGE_CALENDAR_FOLDER;
+ create_esource = TRUE;
+ }
+ else if (!(strcmp (folder_type, "tasks")) ||
+ !(strcmp (folder_type, "tasks/public"))) {
+ type = EXCHANGE_TASKS_FOLDER;
+ create_esource = TRUE;
+ }
+ else if (!(strcmp (folder_type, "contacts")) ||
+ !(strcmp (folder_type, "contacts/public")) ||
+ !(strcmp (folder_type, "contacts/ldap"))) {
+ type = EXCHANGE_CONTACTS_FOLDER;
+ create_esource = TRUE;
+ }
+ else {
+ create_esource = FALSE;
+ }
+
+ if (create_esource)
+ add_folder_esource (account, type,
+ folder_name, folder_uri);
+ } /* End hierarchy type check */
+ } /* End for loop */
+ } /* End check for a list of folders */
+}
+
+static void
+add_sources (ExchangeAccount *account)
+{
+ GPtrArray *exchange_folders;
+
+ exchange_folders = exchange_account_get_folders (account);
+ if (exchange_folders && exchange_folders->len > 0) {
+ gint i;
+ const gchar *folder_type;
+ EFolder *folder;
+ GSList *folders = NULL;
+
+ for (i = 0; i < exchange_folders->len; i++) {
+ FolderInfo *folder_info = g_new0 (FolderInfo, 1);
+
+ folder = exchange_folders->pdata[i];
+ folder_type = e_folder_get_type_string (folder);
+
+ if (!(strcmp (folder_type, "calendar")) ||
+ !(strcmp (folder_type, "calendar/public"))) {
+ folder_info->name = e_folder_get_name (folder);
+ folder_info->uri = e_folder_get_physical_uri (folder);
+ folder_info->type = EXCHANGE_CALENDAR_FOLDER;
+ folders = g_slist_append (folders, folder_info);
+ }
+ else if (!(strcmp (folder_type, "tasks")) ||
+ !(strcmp (folder_type, "tasks/public"))) {
+ folder_info->name = e_folder_get_name (folder);
+ folder_info->uri = e_folder_get_physical_uri (folder);
+ folder_info->type = EXCHANGE_TASKS_FOLDER;
+ folders = g_slist_append (folders, folder_info);
+ }
+ else if (!(strcmp (folder_type, "contacts")) ||
+ !(strcmp (folder_type, "contacts/public")) ||
+ !(strcmp (folder_type, "contacts/ldap"))) {
+ folder_info->name = e_folder_get_name (folder);
+ folder_info->uri = e_folder_get_physical_uri (folder);
+ folder_info->type = EXCHANGE_CONTACTS_FOLDER;
+ folders = g_slist_append (folders, folder_info);
+ }
+ else
+ g_free (folder_info);
+ }
+ /* Add e-sources for all the folders */
+ add_account_esources (account, folders);
+ g_slist_foreach (folders, (GFunc) g_free, NULL);
+ g_slist_free (folders);
+ }
+}
+#endif
+
+static void
+remove_account_esource (ExchangeAccount *account,
+ FolderType folder_type)
+{
+ ESourceGroup *group;
+ ESource *source = NULL;
+ GSList *groups;
+ GSList *sources;
+ GSList *ids, *node_to_be_deleted;
+ gboolean found_group;
+ const gchar *source_uid;
+ GConfClient *client;
+ ESourceList *source_list = NULL;
+
+ /* Remove the ESource group, to remove all the folders in a component */
+
+ client = gconf_client_get_default ();
+
+ if (folder_type == EXCHANGE_CONTACTS_FOLDER)
+ source_list = e_source_list_new_for_gconf ( client,
+ CONF_KEY_CONTACTS);
+ else if (folder_type == EXCHANGE_CALENDAR_FOLDER)
+ source_list = e_source_list_new_for_gconf ( client,
+ CONF_KEY_CAL);
+ else if (folder_type == EXCHANGE_TASKS_FOLDER)
+ source_list = e_source_list_new_for_gconf ( client,
+ CONF_KEY_TASKS);
+
+ groups = e_source_list_peek_groups (source_list);
+ found_group = FALSE;
+
+ for (; groups != NULL && !found_group; groups = g_slist_next (groups)) {
+ group = E_SOURCE_GROUP (groups->data);
+
+ if (strcmp (e_source_group_peek_name (group), account->account_name) == 0
+ &&
+ strcmp (e_source_group_peek_base_uri (group), EXCHANGE_URI_PREFIX) == 0) {
+ sources = e_source_group_peek_sources (group);
+
+ for (; sources != NULL; sources = g_slist_next (sources)) {
+ source = E_SOURCE (sources->data);
+ source_uid = e_source_peek_uid (source);
+
+ /* Remove from the selected folders */
+ if (folder_type == EXCHANGE_CALENDAR_FOLDER) {
+ ids = gconf_client_get_list (
+ client,
+ CONF_KEY_SELECTED_CAL_SOURCES ,
+ GCONF_VALUE_STRING, NULL);
+ if (ids) {
+ node_to_be_deleted = g_slist_find_custom (
+ ids,
+ source_uid,
+ (GCompareFunc) strcmp);
+ if (node_to_be_deleted) {
+ g_free (node_to_be_deleted->data);
+ ids = g_slist_delete_link (ids,
+ node_to_be_deleted);
+ gconf_client_set_list (client,
+ CONF_KEY_SELECTED_CAL_SOURCES,
+ GCONF_VALUE_STRING, ids, NULL);
+ }
+ g_slist_foreach (ids, (GFunc) g_free, NULL);
+ g_slist_free (ids);
+ }
+ }
+ else if (folder_type == EXCHANGE_TASKS_FOLDER) {
+ ids = gconf_client_get_list (client,
+ CONF_KEY_SELECTED_TASKS_SOURCES ,
+ GCONF_VALUE_STRING, NULL);
+ if (ids) {
+ node_to_be_deleted = g_slist_find_custom (
+ ids,
+ source_uid,
+ (GCompareFunc) strcmp);
+ if (node_to_be_deleted) {
+ g_free (node_to_be_deleted->data);
+ ids = g_slist_delete_link (ids,
+ node_to_be_deleted);
+ gconf_client_set_list (client,
+ CONF_KEY_SELECTED_TASKS_SOURCES,
+ GCONF_VALUE_STRING, ids, NULL);
+ }
+ g_slist_foreach (ids, (GFunc) g_free, NULL);
+ g_slist_free (ids);
+ }
+ }
+ }
+ e_source_list_remove_group (source_list, group);
+ e_source_list_sync (source_list, NULL);
+ found_group = TRUE;
+ }
+ }
+ g_object_unref (source_list);
+ g_object_unref (client);
+}
+
+static void
+remove_account_esources (ExchangeAccount *account)
+{
+ /* Remove ESources for all the folders in all the components */
+
+ remove_account_esource (account, EXCHANGE_CALENDAR_FOLDER);
+ remove_account_esource (account, EXCHANGE_TASKS_FOLDER);
+ remove_account_esource (account, EXCHANGE_CONTACTS_FOLDER);
+}
+
+#ifdef HAVE_KRB5
+static gchar *
+get_new_exchange_password (ExchangeAccount *account)
+{
+ gchar *old_password, *new_password;
+
+ old_password = exchange_account_get_password (account);
+ new_password = exchange_get_new_password (old_password, 0);
+
+ if (new_password) {
+ exchange_account_set_password (account,
+ old_password,
+ new_password);
+ g_free (old_password);
+ return new_password;
+ }
+ g_free (old_password);
+ return NULL;
+}
+#endif
+
+#ifdef HAVE_KRB5
+static void
+change_passwd_cb (GtkWidget *button, ExchangeAccount *account)
+{
+ gchar *current_passwd, *new_passwd;
+
+ gtk_widget_hide (gtk_widget_get_toplevel(button));
+ current_passwd = exchange_account_get_password (account);
+ new_passwd = exchange_get_new_password (current_passwd, TRUE);
+ exchange_account_set_password (account, current_passwd, new_passwd);
+ g_free (current_passwd);
+ g_free (new_passwd);
+}
+#endif
+
+static void
+display_passwd_expiry_message (gint max_passwd_age, ExchangeAccount *account)
+{
+ GtkResponseType response;
+ GtkWidget *passwd_exp_dialog;
+ GtkWidget *dialog_vbox1;
+ GtkWidget *dialog_action_area1;
+ GtkWidget *change_passwd_button;
+ GtkWidget *warning_msg_label;
+ GtkWidget *ok_button;
+ AtkObject *atko;
+ gchar *passwd_expiry_msg =
+ g_strdup_printf (_("Your password will expire in the next %d days"), max_passwd_age);
+
+
+ passwd_exp_dialog = gtk_dialog_new ();
+ gtk_window_set_title (GTK_WINDOW (passwd_exp_dialog), _("Password Expiry Warning..."));
+ gtk_window_set_position (GTK_WINDOW (passwd_exp_dialog), GTK_WIN_POS_CENTER_ON_PARENT);
+ gtk_window_set_type_hint (GTK_WINDOW (passwd_exp_dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
+
+ dialog_vbox1 = gtk_dialog_get_content_area (GTK_DIALOG (passwd_exp_dialog));
+ gtk_widget_show (dialog_vbox1);
+
+ warning_msg_label = gtk_label_new (passwd_expiry_msg);
+ gtk_widget_show (warning_msg_label);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox1), warning_msg_label, FALSE, FALSE, 0);
+ gtk_label_set_justify (GTK_LABEL (warning_msg_label), GTK_JUSTIFY_CENTER);
+ gtk_misc_set_padding (GTK_MISC (warning_msg_label), 0, 20);
+
+ dialog_action_area1 = gtk_dialog_get_action_area (GTK_DIALOG (passwd_exp_dialog));
+ gtk_widget_show (dialog_action_area1);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1), GTK_BUTTONBOX_END);
+
+ change_passwd_button = gtk_button_new_with_mnemonic (_("_Change Password"));
+ gtk_widget_show (change_passwd_button);
+ gtk_dialog_add_action_widget (GTK_DIALOG (passwd_exp_dialog), change_passwd_button, 0);
+ GTK_WIDGET_SET_FLAGS (change_passwd_button, GTK_CAN_DEFAULT);
+
+ ok_button = gtk_button_new_from_stock ("gtk-ok");
+ gtk_widget_show (ok_button);
+ gtk_dialog_add_action_widget (GTK_DIALOG (passwd_exp_dialog), ok_button, GTK_RESPONSE_OK);
+ GTK_WIDGET_SET_FLAGS (ok_button, GTK_CAN_DEFAULT);
+
+ atko = gtk_widget_get_accessible (ok_button);
+ atk_object_set_name (atko, "ok_button");
+
+ gtk_widget_grab_focus (change_passwd_button);
+ gtk_widget_grab_default (change_passwd_button);
+
+ gtk_widget_set_sensitive (change_passwd_button, TRUE);
+#ifdef HAVE_KRB5
+ g_signal_connect (change_passwd_button,
+ "clicked",
+ G_CALLBACK (change_passwd_cb),
+ account);
+#endif
+ response = gtk_dialog_run (GTK_DIALOG (passwd_exp_dialog));
+
+ gtk_widget_destroy (passwd_exp_dialog);
+ g_free (passwd_expiry_msg);
+}
+
+static gint
+run_oof_dialog (void)
+{
+ GtkWidget *oof_dialog;
+ GtkWidget *dialog_vbox1;
+ GtkWidget *hbox9;
+ GtkWidget *image3;
+ GtkWidget *label7;
+ GtkWidget *dialog_action_area1;
+ GtkWidget *button3;
+ GtkWidget *alignment3;
+ GtkWidget *hbox6;
+ GtkWidget *image7;
+ GtkWidget *label10;
+ GtkWidget *button4;
+ GtkWidget *alignment4;
+ GtkWidget *hbox7;
+ GtkWidget *image8;
+ GtkWidget *label11;
+ gchar *tmp_str;
+ gint res;
+
+ oof_dialog = gtk_dialog_new ();
+ gtk_container_set_border_width (GTK_CONTAINER (oof_dialog), 6);
+ gtk_window_set_title (GTK_WINDOW (oof_dialog), _("Out of Office Assistant"));
+ gtk_window_set_position (GTK_WINDOW (oof_dialog), GTK_WIN_POS_CENTER_ON_PARENT);
+ gtk_window_set_resizable (GTK_WINDOW (oof_dialog), FALSE);
+ gtk_window_set_type_hint (GTK_WINDOW (oof_dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
+
+ dialog_vbox1 = gtk_dialog_get_content_area (GTK_DIALOG (oof_dialog));
+ gtk_widget_show (dialog_vbox1);
+
+ hbox9 = gtk_hbox_new (FALSE, 6);
+ gtk_widget_show (hbox9);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox1), hbox9, TRUE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox9), 6);
+
+ image3 = gtk_image_new_from_stock ("gtk-dialog-question", GTK_ICON_SIZE_DIALOG);
+ gtk_widget_show (image3);
+ gtk_box_pack_start (GTK_BOX (hbox9), image3, FALSE, TRUE, 0);
+
+ tmp_str = g_strconcat ("<b>", _("Currently, your status is \"Out of the Office\"."), "</b>\n\n", _("Would you like to change your status to \"In the Office\"?"), NULL);
+ label7 = gtk_label_new (tmp_str);
+ g_free (tmp_str);
+ gtk_widget_show (label7);
+ gtk_box_pack_start (GTK_BOX (hbox9), label7, TRUE, TRUE, 0);
+ gtk_label_set_use_markup (GTK_LABEL (label7), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label7), 0, 0.5);
+
+ dialog_action_area1 = gtk_dialog_get_action_area (GTK_DIALOG (oof_dialog));
+ gtk_widget_show (dialog_action_area1);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area1), GTK_BUTTONBOX_END);
+
+ button3 = gtk_button_new ();
+ gtk_widget_show (button3);
+ gtk_dialog_add_action_widget (GTK_DIALOG (oof_dialog), button3, GTK_RESPONSE_NO);
+ GTK_WIDGET_SET_FLAGS (button3, GTK_CAN_DEFAULT);
+
+ alignment3 = gtk_alignment_new (0.5, 0.5, 0, 0);
+ gtk_widget_show (alignment3);
+ gtk_container_add (GTK_CONTAINER (button3), alignment3);
+
+ hbox6 = gtk_hbox_new (FALSE, 2);
+ gtk_widget_show (hbox6);
+ gtk_container_add (GTK_CONTAINER (alignment3), hbox6);
+
+ image7 = gtk_image_new_from_stock ("gtk-no", GTK_ICON_SIZE_BUTTON);
+ gtk_widget_show (image7);
+ gtk_box_pack_start (GTK_BOX (hbox6), image7, FALSE, FALSE, 0);
+
+ label10 = gtk_label_new_with_mnemonic (_("_No, Don't Change Status"));
+ gtk_widget_show (label10);
+ gtk_box_pack_start (GTK_BOX (hbox6), label10, FALSE, FALSE, 0);
+
+ button4 = gtk_button_new ();
+ gtk_widget_show (button4);
+ gtk_dialog_add_action_widget (GTK_DIALOG (oof_dialog), button4, GTK_RESPONSE_YES);
+ GTK_WIDGET_SET_FLAGS (button4, GTK_CAN_DEFAULT);
+
+ alignment4 = gtk_alignment_new (0.5, 0.5, 0, 0);
+ gtk_widget_show (alignment4);
+ gtk_container_add (GTK_CONTAINER (button4), alignment4);
+
+ hbox7 = gtk_hbox_new (FALSE, 2);
+ gtk_widget_show (hbox7);
+ gtk_container_add (GTK_CONTAINER (alignment4), hbox7);
+
+ image8 = gtk_image_new_from_stock ("gtk-yes", GTK_ICON_SIZE_BUTTON);
+ gtk_widget_show (image8);
+ gtk_box_pack_start (GTK_BOX (hbox7), image8, FALSE, FALSE, 0);
+
+ label11 = gtk_label_new_with_mnemonic (_("_Yes, Change Status"));
+ gtk_widget_show (label11);
+ gtk_box_pack_start (GTK_BOX (hbox7), label11, FALSE, FALSE, 0);
+
+ res = gtk_dialog_run (GTK_DIALOG (oof_dialog));
+ gtk_widget_destroy (oof_dialog);
+
+ return res;
+}
+
+ExchangeAccountResult
+exchange_config_listener_authenticate (ExchangeConfigListener *ex_conf_listener, ExchangeAccount *account)
+{
+ ExchangeConfigListenerPrivate *priv;
+ ExchangeAccountResult result;
+ gchar *key, *password, *title, *url_string;
+#ifdef HAVE_KRB5
+ gchar *new_password;
+#endif
+ gboolean oldremember, remember = FALSE;
+ CamelURL *camel_url;
+ const gchar *remember_password;
+
+ g_return_val_if_fail (EXCHANGE_IS_CONFIG_LISTENER (ex_conf_listener), EXCHANGE_ACCOUNT_CONFIG_ERROR);
+ priv = ex_conf_listener->priv;
+
+ camel_url = camel_url_new (priv->configured_uri, NULL);
+ key = camel_url_to_string (camel_url, CAMEL_URL_HIDE_PASSWORD | CAMEL_URL_HIDE_PARAMS);
+ remember_password = camel_url_get_param (camel_url, "save-passwd");
+ password = e_passwords_get_password ("Exchange", key);
+ if (!password) {
+ oldremember = remember = exchange_account_is_save_password (account);
+ title = g_strdup_printf (_("Enter Password for %s"), account->account_name);
+ password = e_passwords_ask_password (title, "Exchange", key, title,
+ E_PASSWORDS_REMEMBER_FOREVER|E_PASSWORDS_SECRET,
+ &remember, NULL);
+ if (remember != oldremember) {
+ exchange_account_set_save_password (account, remember);
+ camel_url_set_param (camel_url, "save-passwd", remember? "true" : "false");
+ url_string = camel_url_to_string (camel_url, 0);
+ e_account_set_string (ex_conf_listener->priv->configured_account, E_ACCOUNT_SOURCE_URL, url_string);
+ e_account_set_string (ex_conf_listener->priv->configured_account, E_ACCOUNT_TRANSPORT_URL, url_string);
+ e_account_set_bool (ex_conf_listener->priv->configured_account, E_ACCOUNT_SOURCE_SAVE_PASSWD, remember);
+ e_account_list_change (E_ACCOUNT_LIST (ex_conf_listener), ex_conf_listener->priv->configured_account);
+ e_account_list_save (E_ACCOUNT_LIST (ex_conf_listener));
+ g_free (url_string);
+ }
+ g_free (title);
+ }
+ else if (remember_password && !g_ascii_strcasecmp (remember_password, "false")) {
+ /* get_password returns the password cached but user has not
+ * selected remember password option, forget this password
+ * whis is stored temporarily by e2k_validate_user(), to avoid
+ * asking for password again, at the end of account creation.
+ */
+ e_passwords_forget_password ("Exchange", key);
+ exchange_account_set_save_password (account, FALSE);
+ }
+
+ exchange_account_connect (account, password, &result);
+
+ g_free (password);
+ g_free (key);
+ camel_url_free (camel_url);
+
+ if (result == EXCHANGE_ACCOUNT_PASSWORD_EXPIRED) {
+#ifdef HAVE_KRB5
+ new_password = get_new_exchange_password (account);
+ if (new_password) {
+ /* try connecting with new password */
+ exchange_account_connect (account, new_password, &result);
+ g_free (new_password);
+ }
+#endif
+ }
+ else if (result == EXCHANGE_ACCOUNT_QUOTA_RECIEVE_ERROR ||
+ result == EXCHANGE_ACCOUNT_QUOTA_SEND_ERROR ||
+ result == EXCHANGE_ACCOUNT_QUOTA_WARN) {
+ gchar *current_quota_usage = NULL;
+ const gchar *error_code = NULL;
+ GtkWidget *widget;
+
+ switch (result) {
+ case EXCHANGE_ACCOUNT_QUOTA_RECIEVE_ERROR:
+ current_quota_usage = g_strdup_printf ("%.2f",
+ account->mbox_size);
+ error_code = "org-gnome-exchange-operations:account-quota-error";
+ break;
+ case EXCHANGE_ACCOUNT_QUOTA_SEND_ERROR:
+ current_quota_usage = g_strdup_printf ("%.2f",
+ account->mbox_size);
+ error_code = "org-gnome-exchange-operations:account-quota-send-error";
+ break;
+ case EXCHANGE_ACCOUNT_QUOTA_WARN:
+ current_quota_usage = g_strdup_printf ("%.2f",
+ account->mbox_size);
+ error_code = "org-gnome-exchange-operations:account-quota-warn";
+ break;
+ default:
+ break;
+ }
+
+ if (current_quota_usage) {
+ widget = e_error_new (NULL, error_code, current_quota_usage, NULL);
+ g_signal_connect ((GtkDialog *)widget, "response",
+ G_CALLBACK (gtk_widget_destroy), widget);
+ gtk_widget_show (widget);
+ g_free (current_quota_usage);
+ }
+
+ /* reset result, so that we check if the password
+ * expiry warning period
+ */
+ result = EXCHANGE_ACCOUNT_CONNECT_SUCCESS;
+ }
+ if (result == EXCHANGE_ACCOUNT_CONNECT_SUCCESS) {
+ gint max_pwd_age_days;
+ gboolean oof;
+
+ /* check for password expiry warning */
+ max_pwd_age_days = exchange_account_check_password_expiry (account);
+ if (max_pwd_age_days >= 0) {
+ display_passwd_expiry_message (max_pwd_age_days, account);
+ }
+
+ /* check for oof state */
+ if (exchange_oof_get (account, &oof, NULL)) {
+ if (oof) {
+ /* OOF state is set, check if user wants to set it back to in-office */
+ if (run_oof_dialog () == GTK_RESPONSE_YES)
+ if (!exchange_oof_set (account, FALSE, NULL))
+ e_error_run (NULL, "org-gnome-exchange-operations:state-update-error", NULL);
+ }
+ }
+ }
+ return result;
+}
+
+static void
+account_added (EAccountList *account_list, EAccount *account)
+{
+ ExchangeConfigListener *config_listener;
+ ExchangeAccount *exchange_account;
+ gint is_offline;
+
+ if (!is_active_exchange_account (account))
+ return;
+
+ config_listener = EXCHANGE_CONFIG_LISTENER (account_list);
+ if (config_listener->priv->configured_account) {
+ /* Multiple accounts configured. */
+ e_error_run (NULL, "org-gnome-exchange-operations:single-account-error", NULL);
+ return;
+ }
+
+ /* New account! Yippee! */
+ exchange_account = exchange_account_new (account_list, account);
+ if (!exchange_account) {
+ g_warning ("Could not parse exchange uri '%s'",
+ account->source->url);
+ return;
+ }
+
+ config_listener->priv->exchange_account = exchange_account;
+ config_listener->priv->configured_account = account;
+
+ g_free (config_listener->priv->configured_uri);
+ config_listener->priv->configured_uri = g_strdup (account->source->url);
+ g_free (config_listener->priv->configured_name);
+ config_listener->priv->configured_name = g_strdup (account->name);
+
+ g_signal_connect_swapped (config_listener->priv->exchange_account,
+ "connected",
+ G_CALLBACK (add_defaults_for_account),
+ config_listener);
+
+ g_signal_emit (config_listener, signals[EXCHANGE_ACCOUNT_CREATED], 0,
+ exchange_account);
+/* add_sources (exchange_account); */
+
+ exchange_config_listener_get_offline_status (config_listener, &is_offline);
+
+ if (is_offline == OFFLINE_MODE) {
+ remove_selected_non_offline_esources (exchange_account, CONF_KEY_CAL);
+ remove_selected_non_offline_esources (exchange_account, CONF_KEY_TASKS);
+ return;
+ }
+ exchange_account_set_online (exchange_account);
+ exchange_config_listener_authenticate (config_listener, exchange_account);
+ exchange_account_set_online (exchange_account);
+}
+
+struct account_update_data {
+ EAccountList *account_list;
+ EAccount *account;
+};
+
+static void
+configured_account_destroyed (gpointer user_data, GObject *where_account_was)
+{
+ struct account_update_data *aud = user_data;
+
+ if (!EXCHANGE_CONFIG_LISTENER (aud->account_list)->priv->configured_account)
+ account_added (aud->account_list, aud->account);
+
+ g_object_unref (aud->account_list);
+ g_object_unref (aud->account);
+ g_free (aud);
+}
+
+static gboolean
+requires_relogin (gchar *current_url, gchar *new_url)
+{
+ E2kUri *current_uri, *new_uri;
+ const gchar *current_param_val, *new_param_val;
+ const gchar *params [] = { "owa_url", "ad_server", "use_ssl" };
+ const gint n_params = G_N_ELEMENTS (params);
+ gint i;
+ gboolean relogin = FALSE;
+
+ current_uri = e2k_uri_new (current_url);
+ new_uri = e2k_uri_new (new_url);
+
+ if (strcmp (current_uri->user, new_uri->user) ||
+ strcmp (current_uri->host, new_uri->host)) {
+ relogin = TRUE;
+ goto end;
+ }
+
+ if (current_uri->authmech || new_uri->authmech) {
+ if (current_uri->authmech && new_uri->authmech) {
+ if (strcmp (current_uri->authmech, new_uri->authmech)) {
+ /* Auth mechanism has changed */
+ relogin = TRUE;
+ goto end;
+ }
+ }
+ else {
+ /* Auth mechanism is set for the first time */
+ relogin = TRUE;
+ goto end;
+ }
+ }
+
+ for (i=0; i<n_params; i++) {
+ current_param_val = e2k_uri_get_param (current_uri, params[i]);
+ new_param_val = e2k_uri_get_param (new_uri, params[i]);
+
+ if (current_param_val && new_param_val) {
+ /* both the urls have params to be compared */
+ if (strcmp (current_param_val, new_param_val)) {
+ relogin = TRUE;
+ break;
+ }
+ }
+ else if (current_param_val || new_param_val) {
+ /* check for added or deleted parameter */
+ relogin = TRUE;
+ break;
+ }
+ }
+end:
+ e2k_uri_free (new_uri);
+ e2k_uri_free (current_uri);
+ return relogin;
+}
+
+static void
+account_changed (EAccountList *account_list, EAccount *account)
+{
+ ExchangeConfigListener *config_listener =
+ EXCHANGE_CONFIG_LISTENER (account_list);
+ ExchangeConfigListenerPrivate *priv = config_listener->priv;
+
+ if (account != config_listener->priv->configured_account) {
+ if (!is_active_exchange_account (account))
+ return;
+
+ /* The user has converted an existing non-Exchange
+ * account to an Exchange account, so treat it like an
+ * add.
+ */
+ account_added (account_list, account);
+ return;
+ } else if (!is_active_exchange_account (account)) {
+ /* The user has disabled the Exchange account or
+ * converted it to non-Exchange, so treat it like a
+ * remove.
+ */
+ account_removed (account_list, account);
+ return;
+ }
+
+ /* FIXME: The order of the parameters in the Camel URL string is not in
+ * order for the two given strings. So, we will not be able to use
+ * plain string comparison. Instead compare the parameters one by one.
+ */
+ if (exchange_camel_urls_is_equal (config_listener->priv->configured_uri,
+ account->source->url) &&
+ !strcmp (config_listener->priv->configured_name, account->name)) {
+ /* The user changed something we don't care about. */
+ return;
+ }
+
+ /* OK, so he modified the active account in a way we care
+ * about. If the user hasn't connected yet, we're still ok.
+ */
+ if (!exchange_account_get_context (config_listener->priv->exchange_account)) {
+ /* Good. Remove the current account, and wait for it
+ * to actually go away (which may not happen immediately
+ * since there may be a function higher up on the stack
+ * still holding a ref on it). Then create the new one.
+ * (We have to wait for it to go away because the new
+ * storage probably still has the same name as the old
+ * one, so trying to create it before the old one is
+ * removed would fail.)
+ */
+ struct account_update_data *aud;
+
+ aud = g_new (struct account_update_data, 1);
+ aud->account = g_object_ref (account);
+ aud->account_list = g_object_ref (account_list);
+ g_object_weak_ref (G_OBJECT (config_listener->priv->exchange_account), configured_account_destroyed, aud);
+
+ account_removed (account_list, account);
+ return;
+ }
+
+ /* If account name has changed, or the url value has changed, which
+ * could be due to change in hostname or some parameter value,
+ * remove old e-sources
+ */
+ if (requires_relogin (config_listener->priv->configured_uri,
+ account->source->url)) {
+ remove_account_esources (priv->exchange_account);
+ exchange_account_forget_password (priv->exchange_account);
+ } else if (strcmp (config_listener->priv->configured_name, account->name)) {
+/* remove_account_esources (priv->exchange_account); */
+ exchange_config_listener_modify_esource_group_name (config_listener,
+ config_listener->priv->configured_name,
+ account->name);
+ g_free (config_listener->priv->configured_name);
+ config_listener->priv->configured_name = g_strdup (account->name);
+ return;
+ } else {
+ /* FIXME: Do ESources need to be modified? */
+ return;
+ }
+
+ /* Nope. Let the user know we're ignoring him. */
+ e_error_run (NULL, "org-gnome-exchange-operations:apply-restart",
+ priv->configured_name, NULL);
+
+ /* But note the new URI so if he changes something else, we
+ * only warn again if he changes again.
+ */
+ g_free (config_listener->priv->configured_uri);
+ config_listener->priv->configured_uri = g_strdup (account->source->url);
+}
+
+static void
+account_removed (EAccountList *account_list, EAccount *account)
+{
+ ExchangeConfigListener *config_listener =
+ EXCHANGE_CONFIG_LISTENER (account_list);
+ ExchangeConfigListenerPrivate *priv = config_listener->priv;
+
+ if (account != priv->configured_account)
+ return;
+
+ /* Remove all ESources */
+ remove_account_esources (priv->exchange_account);
+
+ exchange_account_forget_password (priv->exchange_account);
+
+ if (!exchange_account_get_context (priv->exchange_account)) {
+ /* The account isn't connected yet, so we can destroy
+ * it without problems.
+ */
+ g_signal_emit (config_listener,
+ signals[EXCHANGE_ACCOUNT_REMOVED], 0,
+ priv->exchange_account);
+
+ priv->configured_account = NULL;
+ g_free (priv->configured_uri);
+ priv->configured_uri = NULL;
+ g_free (priv->configured_name);
+ priv->configured_name = NULL;
+ }
+}
+
+static gboolean
+idle_construct (gpointer data)
+{
+ ExchangeConfigListener *config_listener = data;
+
+ config_listener->priv->idle_id = 0;
+ e_account_list_construct (E_ACCOUNT_LIST (config_listener),
+ config_listener->priv->gconf);
+ return FALSE;
+}
+
+ExchangeConfigListenerStatus
+exchange_config_listener_get_offline_status (ExchangeConfigListener *excl,
+ gint *mode)
+{
+ ExchangeConfigListenerPrivate *priv;
+ GConfValue *value;
+ ExchangeConfigListenerStatus status = CONFIG_LISTENER_STATUS_OK;
+ gboolean offline = FALSE;
+
+ g_return_val_if_fail (excl != NULL, CONFIG_LISTENER_STATUS_NOT_FOUND);
+
+ priv = excl->priv;
+ value = gconf_client_get (priv->gconf,
+ "/apps/evolution/shell/start_offline", NULL);
+ if (value)
+ offline = gconf_value_get_bool (value);
+
+ if (offline)
+ *mode = OFFLINE_MODE;
+ else
+ *mode = ONLINE_MODE;
+
+ gconf_value_free (value);
+ return status;
+
+}
+
+/**
+ * exchange_config_listener_new:
+ *
+ * This creates and returns a new #ExchangeConfigListener, which
+ * monitors GConf and creates and (theoretically) destroys accounts
+ * accordingly. It will emit an %account_created signal when a new
+ * account is created (or shortly after the listener itself is created
+ * if an account already exists).
+ *
+ * Due to various constraints, the user is currently limited to a
+ * single account, and it is not possible to destroy an existing
+ * account. Thus, the %account_created signal will never be emitted
+ * more than once currently.
+ *
+ * Return value: the new config listener.
+ **/
+ExchangeConfigListener *
+exchange_config_listener_new (void)
+{
+ ExchangeConfigListener *config_listener;
+
+ config_listener = g_object_new (EXCHANGE_TYPE_CONFIG_LISTENER, NULL);
+ config_listener->priv->gconf = gconf_client_get_default ();
+
+ config_listener->priv->idle_id =
+ g_idle_add (idle_construct, config_listener);
+
+ return config_listener;
+}
+
+GSList *
+exchange_config_listener_get_accounts (ExchangeConfigListener *config_listener)
+{
+ g_return_val_if_fail (EXCHANGE_IS_CONFIG_LISTENER (config_listener), NULL);
+
+ if (config_listener->priv->exchange_account)
+ return g_slist_append (NULL, config_listener->priv->exchange_account);
+ else
+ return NULL;
+}
+
+/**
+ * exchange_config_listener_modify_esource_group_name
+ *
+ * @excl: Handle for Exchange Config Listener
+ * @old_name: Old name of the ESourceGroup
+ * @new_name: New name of the ESourceGroup
+ *
+ * This function modifies the old source group name to the specified new
+ * source group name
+ **/
+void
+exchange_config_listener_modify_esource_group_name (ExchangeConfigListener *excl,
+ const gchar *old_name,
+ const gchar *new_name)
+{
+ GConfClient *client;
+ ESourceGroup *group;
+ GSList *groups;
+ ESourceList *c_source_list = NULL, *t_source_list = NULL,
+ *a_source_list = NULL;
+
+ client = excl->priv->gconf;
+
+ c_source_list = e_source_list_new_for_gconf ( client, CONF_KEY_CAL);
+ t_source_list = e_source_list_new_for_gconf ( client, CONF_KEY_TASKS);
+ a_source_list = e_source_list_new_for_gconf ( client, CONF_KEY_CONTACTS);
+
+ groups = e_source_list_peek_groups (c_source_list);
+
+ for (; groups != NULL; groups = g_slist_next (groups)) {
+ group = E_SOURCE_GROUP (groups->data);
+ if (!strcmp (e_source_group_peek_name (group), old_name)) {
+ e_source_group_set_name (group, new_name);
+ break;
+ }
+ }
+
+ groups = e_source_list_peek_groups (t_source_list);
+
+ for (; groups != NULL; groups = g_slist_next (groups)) {
+ group = E_SOURCE_GROUP (groups->data);
+ if (!strcmp (e_source_group_peek_name (group), old_name)) {
+ e_source_group_set_name (group, new_name);
+ break;
+ }
+ }
+
+ groups = e_source_list_peek_groups (a_source_list);
+
+ for (; groups != NULL; groups = g_slist_next (groups)) {
+ group = E_SOURCE_GROUP (groups->data);
+ if (!strcmp (e_source_group_peek_name (group), old_name)) {
+ e_source_group_set_name (group, new_name);
+ break;
+ }
+ }
+
+ e_source_list_sync (c_source_list, NULL);
+ e_source_list_sync (t_source_list, NULL);
+ e_source_list_sync (a_source_list, NULL);
+
+ g_object_unref (c_source_list);
+ g_object_unref (t_source_list);
+ g_object_unref (a_source_list);
+}
+
+#ifdef LDEAD
+/**
+ * exchange_add_autocompletion_folders:
+ *
+ * @gc_client: GConfClient handle
+ * @account: ExchangeAccount handle
+ *
+ * This function adds the GAL of the Exchange account to the autocompletion list
+ * while configuring a new Exchange account
+ *
+ **/
+static void
+exchange_add_autocompletion_folders (GConfClient *gc_client, ExchangeAccount *account)
+{
+ ESourceList *sl=NULL;
+ ESource *source;
+ GSList *groups;
+ gboolean found_group=FALSE;
+
+ sl = e_source_list_new_for_gconf (gc_client, CONF_KEY_CONTACTS);
+ groups = e_source_list_peek_groups (sl);
+
+ for (; groups != NULL && !found_group; groups = g_slist_next (groups)) {
+ ESourceGroup *group = E_SOURCE_GROUP (groups->data);
+
+ if (strcmp (e_source_group_peek_name (group), account->account_name) == 0
+ &&
+ strcmp (e_source_group_peek_base_uri (group), EXCHANGE_URI_PREFIX) == 0) {
+ GSList *sources = e_source_group_peek_sources (group);
+
+ for (; sources != NULL; sources = g_slist_next (sources)) {
+ ESource *source = E_SOURCE (sources->data);
+ const gchar *absolute_uri;
+
+ absolute_uri = e_source_peek_absolute_uri (source);
+ if (absolute_uri == NULL)
+ continue;
+ if (g_str_has_prefix (absolute_uri, "gal://")) {
+ /* Set autocompletion on GAL alone by default */
+ e_source_set_property (source, "completion", "true");
+ break;
+ }
+ }
+ found_group = TRUE;
+ }
+ }
+
+ g_object_unref (sl);
+}
+#endif
+
+/**
+ * exchange_camel_urls_is_equal
+ *
+ * @url1: CAMEL URL string 1
+ * @url2: CAMEL URL string 2
+ *
+ * This function checks if the parameters present in two given CAMEL URLS are
+ * identical and returns the result.
+ *
+ * Return Value: Boolean result of the comparision.
+ *
+ **/
+static gboolean
+exchange_camel_urls_is_equal (const gchar *url1, const gchar *url2)
+{
+ CamelURL *curl1, *curl2;
+ gchar *param1, *param2;
+ const gchar *params[] = {
+ "auth",
+ "owa_url",
+ "owa_path",
+ "mailbox",
+ "ad_server",
+ };
+ const gint n_params = 5;
+ gint i;
+
+ curl1 = camel_url_new (url1, NULL);
+ curl2 = camel_url_new (url2, NULL);
+
+ for (i = 0; i < n_params; ++i) {
+ param1 = (gchar *) camel_url_get_param (curl1, params[i]);
+ param2 = (gchar *) camel_url_get_param (curl2, params[i]);
+ if ((param1 && !param2) || (!param1 && param2) || /* Missing */
+ (param1 && param2 && strcmp (param1, param2))) { /* Differing */
+ g_free (param1);
+ g_free (param2);
+ g_free (curl1);
+ g_free (curl2);
+ return FALSE;
+ }
+ g_free (param1);
+ g_free (param2);
+ }
+ g_free (curl1);
+ g_free (curl2);
+ return TRUE;
+}
+
+/**
+ * remove_selected_non_offline_esources
+ *
+ * @account: Handle for Exchange Account
+ * @gconf_key: GConf key of the calendar or tasks
+ *
+ * This function removes the non-offline calendars and taks list from the
+ * selection list
+ **/
+static void
+remove_selected_non_offline_esources (ExchangeAccount *account, const gchar *gconf_key)
+{
+ ESourceGroup *group;
+ ESource *source = NULL;
+ GSList *groups;
+ GSList *sources;
+ GSList *ids, *node_to_be_deleted;
+ gboolean found_group;
+ const gchar *source_uid;
+ GConfClient *client;
+ ESourceList *source_list = NULL;
+ const gchar *offline_mode=NULL;
+ gchar *selected_gconf_key;
+
+ if (gconf_key && !strcmp (gconf_key, CONF_KEY_CAL)) {
+ selected_gconf_key = g_strdup (CONF_KEY_SELECTED_CAL_SOURCES);
+ } else if (gconf_key && !strcmp (gconf_key, CONF_KEY_TASKS)) {
+ selected_gconf_key = g_strdup (CONF_KEY_SELECTED_TASKS_SOURCES);
+ }
+ else {
+ return;
+ }
+
+ client = gconf_client_get_default ();
+ source_list = e_source_list_new_for_gconf ( client, gconf_key);
+
+ groups = e_source_list_peek_groups (source_list);
+ found_group = FALSE;
+
+ for (; groups != NULL && !found_group; groups = g_slist_next (groups)) {
+ group = E_SOURCE_GROUP (groups->data);
+
+ if (strcmp (e_source_group_peek_name (group), account->account_name) == 0
+ &&
+ strcmp (e_source_group_peek_base_uri (group), EXCHANGE_URI_PREFIX) == 0) {
+ sources = e_source_group_peek_sources (group);
+
+ for (; sources != NULL; sources = g_slist_next (sources)) {
+ source = E_SOURCE (sources->data);
+ source_uid = e_source_peek_uid (source);
+
+ /* Remove from the selected folders */
+ ids = gconf_client_get_list (client,
+ selected_gconf_key,
+ GCONF_VALUE_STRING, NULL);
+ if (ids) {
+ offline_mode = e_source_get_property (source, "offline_sync");
+ if (!offline_mode ||
+ (offline_mode && strcmp (offline_mode, "1"))) {
+ while ((node_to_be_deleted =
+ g_slist_find_custom (ids,
+ source_uid,
+ (GCompareFunc) strcmp))) {
+ g_free (node_to_be_deleted->data);
+ ids = g_slist_delete_link (ids,
+ node_to_be_deleted);
+ gconf_client_set_list (client,
+ selected_gconf_key,
+ GCONF_VALUE_STRING, ids, NULL);
+ }
+ }
+ g_slist_foreach (ids, (GFunc) g_free, NULL);
+ g_slist_free (ids);
+ }
+ }
+ found_group = TRUE;
+ e_source_list_sync (source_list, NULL);
+ }
+ }
+
+ g_free (selected_gconf_key);
+ g_object_unref (source_list);
+ g_object_unref (client);
+}
diff --git a/eplugin/exchange-config-listener.h b/eplugin/exchange-config-listener.h
new file mode 100644
index 0000000..07051bc
--- /dev/null
+++ b/eplugin/exchange-config-listener.h
@@ -0,0 +1,84 @@
+/*
+ *
+ * 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/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __EXCHANGE_CONFIG_LISTENER_H__
+#define __EXCHANGE_CONFIG_LISTENER_H__
+
+#include <exchange-constants.h>
+#include <exchange-account.h>
+
+#include "exchange-types.h"
+#include "libedataserver/e-account-list.h"
+#include <libedataserver/e-source-list.h>
+#include <libedataserver/e-source-group.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+ CONFIG_LISTENER_STATUS_OK,
+ CONFIG_LISTENER_STATUS_NOT_FOUND
+} ExchangeConfigListenerStatus;
+
+#define EXCHANGE_TYPE_CONFIG_LISTENER (exchange_config_listener_get_type ())
+#define EXCHANGE_CONFIG_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXCHANGE_TYPE_CONFIG_LISTENER, ExchangeConfigListener))
+#define EXCHANGE_CONFIG_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EXCHANGE_TYPE_CONFIG_LISTENER, ExchangeConfigListenerClass))
+#define EXCHANGE_IS_CONFIG_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXCHANGE_TYPE_CONFIG_LISTENER))
+#define EXCHANGE_IS_CONFIG_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EXCHANGE_TYPE_CONFIG_LISTENER))
+
+struct _ExchangeConfigListener {
+ EAccountList parent;
+
+ ExchangeConfigListenerPrivate *priv;
+};
+
+struct _ExchangeConfigListenerClass {
+ EAccountListClass parent_class;
+
+ /* signals */
+ void (*exchange_account_created) (ExchangeConfigListener *,
+ ExchangeAccount *);
+ void (*exchange_account_removed) (ExchangeConfigListener *,
+ ExchangeAccount *);
+};
+
+#define CONF_KEY_CAL "/apps/evolution/calendar/sources"
+#define CONF_KEY_TASKS "/apps/evolution/tasks/sources"
+#define CONF_KEY_CONTACTS "/apps/evolution/addressbook/sources"
+#define EXCHANGE_URI_PREFIX "exchange://"
+
+GType exchange_config_listener_get_type (void);
+ExchangeConfigListener *exchange_config_listener_new (void);
+
+GSList *exchange_config_listener_get_accounts (ExchangeConfigListener *config_listener);
+
+void add_folder_esource (ExchangeAccount *account, FolderType folder_type, const gchar *folder_name, const gchar *physical_uri);
+void remove_folder_esource (ExchangeAccount *account, FolderType folder_type, const gchar *physical_uri);
+ExchangeConfigListenerStatus exchange_config_listener_get_offline_status (ExchangeConfigListener *excl, gint *mode);
+
+void exchange_config_listener_modify_esource_group_name (ExchangeConfigListener *excl,
+ const gchar *old_name,
+ const gchar *new_name);
+
+ExchangeAccountResult exchange_config_listener_authenticate (ExchangeConfigListener *excl,
+ ExchangeAccount *account);
+
+G_END_DECLS
+
+#endif /* __EXCHANGE_CONFIG_LISTENER_H__ */
diff --git a/eplugin/exchange-contacts.c b/eplugin/exchange-contacts.c
new file mode 100644
index 0000000..7fb9f85
--- /dev/null
+++ b/eplugin/exchange-contacts.c
@@ -0,0 +1,548 @@
+/*
+ * 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:
+ * Praveen Kumar <kpraveen novell com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <string.h>
+#include <gtk/gtk.h>
+#include <e-util/e-config.h>
+#include <calendar/gui/e-cal-config.h>
+#include <libedataserver/e-source.h>
+#include <libedataserver/e-source-list.h>
+#include <libedataserver/e-url.h>
+#include <e-folder.h>
+#include <exchange-account.h>
+
+#include <libebook/e-book.h>
+#include <libecal/e-cal.h>
+#include <addressbook/gui/widgets/eab-config.h>
+
+#include "mail/em-account-editor.h"
+#include "mail/em-config.h"
+#include "libedataserver/e-account.h"
+#include "e-util/e-error.h"
+
+#include "exchange-operations.h"
+#include "exchange-folder-size-display.h"
+
+enum {
+ CONTACTSNAME_COL,
+ CONTACTSRURI_COL,
+ NUM_COLS
+};
+
+gboolean contacts_src_exists = FALSE;
+gchar *contacts_old_src_uri = NULL;
+
+static GPtrArray *e_exchange_contacts_get_contacts (void);
+void e_exchange_contacts_pcontacts_on_change (GtkTreeView *treeview, ESource *source);
+GtkWidget *e_exchange_contacts_pcontacts (EPlugin *epl, EConfigHookItemFactoryData *data);
+gboolean e_exchange_contacts_check (EPlugin *epl, EConfigHookPageCheckData *data);
+void e_exchange_contacts_commit (EPlugin *epl, EConfigTarget *target);
+
+/* FIXME: Reconsider the prototype of this function */
+static GPtrArray *
+e_exchange_contacts_get_contacts (void)
+{
+ ExchangeAccount *account;
+ GPtrArray *folder_array;
+ GPtrArray *contacts_list;
+ EFolder *folder;
+
+ gint i, prefix_len;
+ gchar *uri_prefix, *ruri;
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account)
+ return NULL;
+
+ uri_prefix = g_strconcat ("exchange://", account->account_filename, "/;", NULL);
+ prefix_len = strlen (uri_prefix);
+
+ contacts_list = g_ptr_array_new ();
+ exchange_account_rescan_tree (account);
+ folder_array = exchange_account_get_folders (account);
+
+ for (i=0; i<folder_array->len; ++i) {
+ gchar *type, *tmp;
+ folder = g_ptr_array_index (folder_array, i);
+ type = (gchar *) e_folder_get_type_string (folder);
+ if (!strcmp (type, "contacts")) {
+ tmp = (gchar *) e_folder_get_physical_uri (folder);
+ if (g_str_has_prefix (tmp, uri_prefix)) {
+ ruri = g_strdup (tmp+prefix_len);
+ g_ptr_array_add (contacts_list, ruri);
+ }
+ }
+ }
+
+ g_free (uri_prefix);
+ if (folder_array)
+ g_ptr_array_free (folder_array, TRUE);
+ return contacts_list;
+}
+
+void
+e_exchange_contacts_pcontacts_on_change (GtkTreeView *treeview, ESource *source)
+{
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ ExchangeAccount *account;
+ gchar *es_ruri;
+ gchar *ruri;
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account)
+ return;
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
+ gtk_tree_selection_get_selected(selection, &model, &iter);
+
+ gtk_tree_model_get (model, &iter, CONTACTSRURI_COL, &ruri, -1);
+ es_ruri = g_strconcat (account->account_filename, "/;", ruri, NULL);
+ e_source_set_relative_uri (source, es_ruri);
+
+ g_free (ruri);
+ g_free (es_ruri);
+}
+
+GtkWidget *
+e_exchange_contacts_pcontacts (EPlugin *epl, EConfigHookItemFactoryData *data)
+{
+ static GtkWidget *lbl_pcontacts, *scrw_pcontacts, *tv_pcontacts, *vb_pcontacts, *lbl_size, *lbl_size_val, *hbx_size;
+ GtkTreeStore *ts_pcontacts;
+ GtkCellRenderer *cr_contacts;
+ GtkTreeViewColumn *tvc_contacts;
+ GtkListStore *model;
+ GPtrArray *conlist;
+ gchar *ruri, *account_name, *uri_text;
+ ExchangeAccount *account;
+ gint i;
+ gchar *folder_size, *abook_name;
+ const gchar *rel_uri;
+ const gchar *uid;
+ EABConfigTargetSource *t = (EABConfigTargetSource *) data->target;
+ ESource *source = t->source;
+ GtkWidget *lbl_offline_msg, *vb_offline_msg;
+ gchar *offline_msg;
+ gint offline_status;
+ gboolean gal_folder = FALSE, is_personal;
+
+ if (data->old) {
+ gtk_widget_destroy (vb_pcontacts);
+ }
+
+ uri_text = e_source_get_uri (source);
+ if (uri_text && g_ascii_strncasecmp (uri_text, "exchange", 8)) {
+ if (g_ascii_strncasecmp (uri_text, "gal", 3)) {
+ g_free (uri_text);
+ return NULL;
+ }
+ else {
+ gal_folder = TRUE;
+ }
+ }
+
+ exchange_config_listener_get_offline_status (exchange_global_config_listener,
+ &offline_status);
+ if (offline_status == OFFLINE_MODE) {
+ /* Evolution is in offline mode; we will not be able to create
+ new folders or modify existing folders. */
+ offline_msg = g_markup_printf_escaped ("<b>%s</b>",
+ _("Evolution is in offline mode. You cannot create or modify folders now.\nPlease switch to online mode for such operations."));
+ vb_offline_msg = gtk_vbox_new (FALSE, 6);
+ gtk_container_add (GTK_CONTAINER (data->parent), vb_offline_msg);
+ lbl_offline_msg = gtk_label_new ("");
+ gtk_label_set_markup (GTK_LABEL (lbl_offline_msg), offline_msg);
+ g_free (offline_msg);
+ gtk_box_pack_start (GTK_BOX (vb_offline_msg), lbl_offline_msg, FALSE, FALSE, 0);
+ gtk_widget_show_all (vb_offline_msg);
+ g_free (uri_text);
+ return vb_offline_msg;
+ }
+
+ if (gal_folder) {
+ contacts_src_exists = TRUE;
+ g_free (uri_text);
+ return NULL;
+ }
+
+ rel_uri = e_source_peek_relative_uri (source);
+ uid = e_source_peek_uid (source);
+ if (rel_uri && uid && (strcmp (rel_uri, uid))) {
+ contacts_src_exists = TRUE;
+ g_free (contacts_old_src_uri);
+ contacts_old_src_uri = g_strdup (rel_uri);
+ }
+ else {
+ /* new folder */
+ contacts_src_exists = FALSE;
+ e_source_set_relative_uri (source, ""); /* FIXME: Nasty hack */
+ }
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account) {
+ g_free (contacts_old_src_uri);
+ g_free (uri_text);
+ return NULL;
+ }
+ account_name = account->account_name;
+ hbx_size = NULL;
+
+ is_personal = is_exchange_personal_folder (account, uri_text);
+ g_free (uri_text);
+
+ if (contacts_src_exists && is_personal ) {
+ abook_name = (gchar *)e_source_peek_name (source);
+ model = exchange_account_folder_size_get_model (account);
+ if (model)
+ folder_size = g_strdup_printf (_("%s KB"), exchange_folder_size_get_val (model, abook_name));
+ else
+ folder_size = g_strdup_printf (_("0 KB"));
+
+ /* FIXME: Take care of i18n */
+ lbl_size = gtk_label_new_with_mnemonic (_("Size:"));
+ lbl_size_val = gtk_label_new_with_mnemonic (_(folder_size));
+ hbx_size = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbx_size), lbl_size, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (hbx_size), lbl_size_val, FALSE, TRUE, 10);
+ gtk_widget_show (lbl_size);
+ gtk_widget_show (lbl_size_val);
+ gtk_misc_set_alignment (GTK_MISC (lbl_size), 0.0, 0.5);
+ gtk_misc_set_alignment (GTK_MISC (lbl_size_val), 0.0, 0.5);
+ g_free (folder_size);
+ }
+ vb_pcontacts = gtk_vbox_new (FALSE, 6);
+ gtk_container_add (GTK_CONTAINER (data->parent), vb_pcontacts);
+
+ if (hbx_size)
+ gtk_box_pack_start (GTK_BOX (vb_pcontacts), hbx_size, FALSE, FALSE, 0);
+
+ lbl_pcontacts = gtk_label_new_with_mnemonic (_("_Location:"));
+ gtk_widget_show (lbl_pcontacts);
+ gtk_misc_set_alignment (GTK_MISC (lbl_pcontacts), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (vb_pcontacts), lbl_pcontacts, FALSE, FALSE, 0);
+
+ ts_pcontacts = gtk_tree_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_STRING);
+
+ conlist = e_exchange_contacts_get_contacts ();
+
+ if (conlist) {
+ for (i = 0; i < conlist->len; i++) {
+ ruri = g_ptr_array_index (conlist, i);
+ exchange_operations_cta_add_node_to_tree (ts_pcontacts, NULL, ruri);
+ }
+ g_ptr_array_free (conlist, TRUE);
+ }
+
+ cr_contacts = gtk_cell_renderer_text_new ();
+ tvc_contacts = gtk_tree_view_column_new_with_attributes (account_name, cr_contacts, "text", CONTACTSNAME_COL, NULL);
+ tv_pcontacts = gtk_tree_view_new_with_model (GTK_TREE_MODEL (ts_pcontacts));
+ gtk_tree_view_append_column (GTK_TREE_VIEW (tv_pcontacts), tvc_contacts);
+ g_object_set (tv_pcontacts,"expander-column", tvc_contacts, "headers-visible", TRUE, NULL);
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (tv_pcontacts));
+
+ scrw_pcontacts = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrw_pcontacts), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrw_pcontacts), GTK_SHADOW_IN);
+ g_object_set (scrw_pcontacts, "height-request", 150, NULL);
+ gtk_container_add (GTK_CONTAINER (scrw_pcontacts), tv_pcontacts);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (lbl_pcontacts), tv_pcontacts);
+ g_signal_connect (G_OBJECT (tv_pcontacts), "cursor-changed", G_CALLBACK (e_exchange_contacts_pcontacts_on_change), t->source);
+ gtk_widget_show_all (scrw_pcontacts);
+
+ gtk_box_pack_start (GTK_BOX (vb_pcontacts), scrw_pcontacts, FALSE, FALSE, 0);
+ gtk_widget_show_all (vb_pcontacts);
+
+ if (contacts_src_exists) {
+ gchar *uri_prefix, *sruri, *tmpruri;
+ gint prefix_len;
+ GtkTreeSelection *selection;
+
+ tmpruri = (gchar *) rel_uri;
+ uri_prefix = g_strconcat (account->account_filename, "/;", NULL);
+ prefix_len = strlen (uri_prefix);
+
+ if (g_str_has_prefix (tmpruri, uri_prefix)) {
+ sruri = g_strdup (tmpruri+prefix_len);
+ }
+ else {
+ sruri = NULL;
+ }
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv_pcontacts));
+ exchange_operations_cta_select_node_from_tree (ts_pcontacts,
+ NULL,
+ sruri,
+ sruri,
+ selection);
+ gtk_widget_set_sensitive (tv_pcontacts, FALSE);
+
+ g_free (uri_prefix);
+ g_free (sruri);
+ }
+
+ g_object_unref (ts_pcontacts);
+ return vb_pcontacts;
+}
+
+gboolean
+e_exchange_contacts_check (EPlugin *epl, EConfigHookPageCheckData *data)
+{
+ /* FIXME - check pageid */
+ EABConfigTargetSource *t = (EABConfigTargetSource *) data->target;
+ ESourceGroup *group;
+ const gchar *base_uri;
+ const gchar *rel_uri;
+ gint offline_status;
+ ExchangeAccount *account;
+
+ rel_uri = e_source_peek_relative_uri (t->source);
+ group = e_source_peek_group (t->source);
+ base_uri = e_source_group_peek_base_uri (group);
+ exchange_config_listener_get_offline_status (exchange_global_config_listener,
+ &offline_status);
+ if (base_uri && !g_ascii_strncasecmp (base_uri, "exchange", 8)) {
+ if (offline_status == OFFLINE_MODE)
+ return FALSE;
+ if (rel_uri && !strlen (rel_uri))
+ return FALSE;
+ }
+ else {
+ return TRUE;
+ }
+
+ if (!contacts_src_exists) {
+ return TRUE;
+ }
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account)
+ return FALSE;
+
+ if (!rel_uri) {
+ GConfClient *client;
+ ESourceList *source_list = NULL;
+ ESourceGroup *source_group = NULL;
+ ESource *source;
+ EAccount *eaccount;
+
+ /* GAL folder */
+ client = gconf_client_get_default ();
+ source_list = e_source_list_new_for_gconf ( client, CONF_KEY_CONTACTS);
+ g_object_unref (client);
+
+ eaccount = exchange_account_fetch (account);
+ g_return_val_if_fail (eaccount != NULL, FALSE);
+ g_return_val_if_fail (eaccount->uid != NULL, FALSE);
+
+ if ((source_group = e_source_list_peek_group_by_properties (source_list, "account-uid", eaccount->uid, NULL))) {
+ source = e_source_group_peek_source_by_name (source_group, e_source_peek_name (t->source));
+ if (e_source_group_peek_source_by_name (source_group,
+ e_source_peek_name (t->source))) {
+ /* not a rename of GAL */
+ g_object_unref (source_list);
+ return TRUE;
+ }
+ else {
+ g_object_unref (source_list);
+ return FALSE;
+ }
+ }
+ else {
+ g_object_unref (source_list);
+ return FALSE;
+ }
+ }
+ else {
+ EUri *euri;
+ gint uri_len;
+ gchar *uri_text, *uri_string, *path, *folder_name;
+ gboolean is_personal;
+
+ uri_text = e_source_get_uri (t->source);
+ euri = e_uri_new (uri_text);
+ uri_string = e_uri_to_string (euri, FALSE);
+ e_uri_free (euri);
+
+ is_personal = is_exchange_personal_folder (account, uri_text);
+
+ uri_len = strlen (uri_string) + 1;
+ g_free (uri_string);
+ path = g_build_filename ("/", uri_text + uri_len, NULL);
+ g_free (uri_text);
+ folder_name = g_strdup (g_strrstr (path, "/") +1);
+ g_free (path);
+
+ if (strcmp (folder_name, e_source_peek_name (t->source))) {
+ /* rename */
+ if (exchange_account_get_standard_uri (account, folder_name) ||
+ !is_personal) {
+ /* rename of standard/non-personal folder */
+ g_free (folder_name);
+ return FALSE;
+ }
+ g_free (folder_name);
+ }
+ }
+ return TRUE;
+}
+
+void
+e_exchange_contacts_commit (EPlugin *epl, EConfigTarget *target)
+{
+ EABConfigTargetSource *t = (EABConfigTargetSource *) target;
+ ESource *source = t->source;
+ gchar *uri_text, *gname, *gruri, *ruri = NULL, *path = NULL, *path_prefix, *oldpath=NULL;
+ gchar *username, *windows_domain, *authtype;
+ gint prefix_len;
+ ExchangeAccount *account;
+ ExchangeAccountFolderResult result;
+ gint offline_status;
+ gboolean rename = FALSE;
+
+ uri_text = e_source_get_uri (source);
+ if (uri_text && strncmp (uri_text, "exchange", 8)) {
+ /* here no need of checking for gal */
+ g_free (uri_text);
+ return;
+ }
+
+ exchange_config_listener_get_offline_status (exchange_global_config_listener,
+ &offline_status);
+ if (offline_status == OFFLINE_MODE) {
+ g_free (uri_text);
+ return;
+ }
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account || !is_exchange_personal_folder (account, uri_text))
+ return;
+
+ windows_domain = exchange_account_get_windows_domain (account);
+ if (windows_domain)
+ username = g_strdup_printf ("%s\\%s", windows_domain,
+ exchange_account_get_username (account));
+ else
+ username = g_strdup (exchange_account_get_username (account));
+
+ authtype = exchange_account_get_authtype (account);
+
+ path_prefix = g_strconcat (account->account_filename, "/;", NULL);
+ prefix_len = strlen (path_prefix);
+ g_free (path_prefix);
+
+ gname = (gchar *) e_source_peek_name (source);
+ gruri = (gchar *) e_source_peek_relative_uri (source);
+
+ if (contacts_src_exists) {
+ gchar *tmpruri, *uri_string, *temp_path, *prefix;
+ EUri *euri;
+ gint uri_len;
+
+ euri = e_uri_new (uri_text);
+ uri_string = e_uri_to_string (euri, FALSE);
+ e_uri_free (euri);
+
+ uri_len = strlen (uri_string) + 1;
+ tmpruri = g_strdup (uri_string + strlen ("exchange://"));
+ temp_path = g_build_filename ("/", uri_text + uri_len, NULL);
+ prefix = g_strndup (temp_path, strlen (temp_path) - strlen (g_strrstr (temp_path, "/")));
+ g_free (temp_path);
+ path = g_build_filename (prefix, "/", gname, NULL);
+ ruri = g_strconcat (tmpruri, ";", path+1, NULL);
+ oldpath = g_build_filename ("/", contacts_old_src_uri + prefix_len, NULL);
+ g_free (prefix);
+ g_free (uri_string);
+ g_free (tmpruri);
+ }
+ else {
+ /* new folder */
+ ruri = g_strconcat (gruri, "/", gname, NULL);
+ path = g_build_filename ("/", ruri+prefix_len, NULL);
+ }
+
+ if (!contacts_src_exists) {
+ /* Create the new folder */
+ result = exchange_account_create_folder (account, path, "contacts");
+ }
+ else if (gruri && strcmp (path, oldpath )) {
+ /* Rename the folder */
+ rename = TRUE;
+ result = exchange_account_xfer_folder (account, oldpath, path, TRUE);
+ }
+ else {
+ /* Nothing happened specific to exchange; just return */
+ goto done;
+ }
+ switch (result) {
+ case EXCHANGE_ACCOUNT_FOLDER_OK:
+ e_source_set_name (source, gname);
+ e_source_set_relative_uri (source, ruri);
+ e_source_set_property (source, "username", username);
+ e_source_set_property (source, "auth-domain", "Exchange");
+ if (authtype) {
+ e_source_set_property (source, "auth-type", authtype);
+ g_free (authtype);
+ authtype=NULL;
+ }
+ e_source_set_property (source, "auth", "plain/password");
+ if (rename) {
+ exchange_operations_update_child_esources (source,
+ contacts_old_src_uri,
+ ruri);
+ }
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_ALREADY_EXISTS:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-exists-error", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-doesnt-exist-error", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_UNKNOWN_TYPE:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-unknown-type", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-perm-error", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_OFFLINE:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-offline-error", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_UNSUPPORTED_OPERATION:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-unsupported-error", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-generic-error", NULL);
+ break;
+ default:
+ break;
+ }
+done:
+ g_free (ruri);
+ g_free (username);
+ if (authtype)
+ g_free (authtype);
+ g_free (path);
+ g_free (oldpath);
+ g_free (contacts_old_src_uri);
+ g_free (uri_text);
+ contacts_old_src_uri = NULL;
+}
diff --git a/eplugin/exchange-delegates-user.c b/eplugin/exchange-delegates-user.c
new file mode 100644
index 0000000..7c1101f
--- /dev/null
+++ b/eplugin/exchange-delegates-user.c
@@ -0,0 +1,628 @@
+/*
+ * 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:
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+/* ExchangeDelegatesUser: A single delegate */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "exchange-delegates.h"
+#include "exchange-delegates-user.h"
+
+#include <mail/mail-ops.h>
+#include <mail/mail-send-recv.h>
+#include <mail/e-mail-local.h>
+#include <camel/camel-multipart.h>
+#include <camel/camel-mime-utils.h>
+#include <camel/camel-stream-mem.h>
+#include <exchange-account.h>
+#include "exchange-delegates.h"
+#include <exchange/exchange-account.h>
+#include <e2k-global-catalog.h>
+#include <e2k-marshal.h>
+#include <e2k-sid.h>
+#include <e2k-utils.h>
+
+#include <e-util/e-dialog-utils.h>
+#include <e-util/e-dialog-widgets.h>
+
+#include <string.h>
+
+#define EXCHANGE_DELEGATES_USER_CUSTOM -3
+/* Can't use E2K_PERMISSIONS_ROLE_CUSTOM, because it's -1, which
+ * means "end of list" to e_dialog_combo_box_get/set
+ */
+
+static const gint exchange_perm_map[] = {
+ E2K_PERMISSIONS_ROLE_NONE,
+ E2K_PERMISSIONS_ROLE_REVIEWER,
+ E2K_PERMISSIONS_ROLE_AUTHOR,
+ E2K_PERMISSIONS_ROLE_EDITOR,
+
+ EXCHANGE_DELEGATES_USER_CUSTOM,
+
+ -1
+};
+
+const gchar *exchange_delegates_user_folder_names[] = {
+ "calendar", "tasks", "inbox", "contacts"
+};
+
+/* To translators: The folder names to be displayed in the message being
+ sent to the delegatee.
+*/
+static const gchar *folder_names_for_display[] = {
+ N_("Calendar"), N_("Tasks"), N_("Inbox"), N_("Contacts")
+};
+
+enum {
+ EDITED,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+#define PARENT_TYPE G_TYPE_OBJECT
+static GObjectClass *parent_class = NULL;
+
+static void
+finalize (GObject *object)
+{
+ ExchangeDelegatesUser *user = EXCHANGE_DELEGATES_USER (object);
+
+ if (user->display_name)
+ g_free (user->display_name);
+ if (user->dn)
+ g_free (user->dn);
+ if (user->entryid)
+ g_byte_array_free (user->entryid, TRUE);
+ if (user->sid)
+ g_object_unref (user->sid);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+class_init (GObjectClass *object_class)
+{
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ object_class->finalize = finalize;
+
+ /* signals */
+ signals[EDITED] =
+ g_signal_new ("edited",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ExchangeDelegatesUserClass, edited),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+E2K_MAKE_TYPE (exchange_delegates_user, ExchangeDelegatesUser, class_init, NULL, PARENT_TYPE)
+
+static inline gboolean
+is_delegate_role (E2kPermissionsRole role)
+{
+ return (role == E2K_PERMISSIONS_ROLE_NONE ||
+ role == E2K_PERMISSIONS_ROLE_REVIEWER ||
+ role == E2K_PERMISSIONS_ROLE_AUTHOR ||
+ role == E2K_PERMISSIONS_ROLE_EDITOR);
+}
+
+static void
+set_perms (GtkWidget *combobox, E2kPermissionsRole role)
+{
+ if (!is_delegate_role (role)) {
+ gtk_combo_box_append_text (GTK_COMBO_BOX (combobox), _("Custom"));
+ role = EXCHANGE_DELEGATES_USER_CUSTOM;
+ }
+
+ e_dialog_combo_box_set (combobox, role, exchange_perm_map);
+}
+
+static void
+parent_window_destroyed (gpointer dialog, GObject *where_parent_window_was)
+{
+ gtk_dialog_response (dialog, GTK_RESPONSE_CANCEL);
+}
+
+/* Maps the role_nam parameter to their corresponding Full role name
+*/
+static const gchar *
+map_to_full_role_name (E2kPermissionsRole role_nam)
+{
+ const gchar *role_name;
+
+ switch (role_nam)
+ {
+ /* To translators: The following are the various types of permissions that can
+ assigned by an user to his folders.
+ */
+ case E2K_PERMISSIONS_ROLE_EDITOR: role_name = g_strdup (
+ _("Editor (read, create, edit)"));
+ break;
+
+ case E2K_PERMISSIONS_ROLE_AUTHOR: role_name = g_strdup (
+ _("Author (read, create)"));
+ break;
+
+ case E2K_PERMISSIONS_ROLE_REVIEWER: role_name = g_strdup (
+ _("Reviewer (read-only)"));
+ break;
+
+ default: role_name = g_strdup (_("None"));
+ break;
+ }
+
+ return role_name;
+}
+
+static void
+em_utils_delegates_done (CamelFolder *folder, CamelMimeMessage *msg, CamelMessageInfo *info,
+ gint queued, const gchar *appended_uid, gpointer data)
+{
+ camel_message_info_free (info);
+ mail_send ();
+}
+
+/**
+ * exchange_delegates_user_edit:
+ * @user: a delegate
+ * @parent_window: parent window for the editor dialog
+ *
+ * Brings up a dialog to edit @user's permissions as a delegate.
+ * An %edited signal will be emitted if anything changed.
+ *
+ * Return value: %TRUE for "OK", %FALSE for "Cancel".
+ **/
+gboolean
+exchange_delegates_user_edit (ExchangeAccount *account,
+ ExchangeDelegatesUser *user,
+ GtkWidget *parent_window)
+{
+ gchar *title;
+ gint button, i;
+ E2kPermissionsRole role;
+ gboolean modified;
+ GtkWidget *delegate_permissions;
+ GtkWidget *dialog_vbox1;
+ GtkWidget *vbox3;
+ GtkWidget *delegate_label;
+ GtkWidget *folders_table;
+ GtkWidget *calendar_label;
+ GtkWidget *task_label;
+ GtkWidget *inbox_label;
+ GtkWidget *contact_label;
+ GtkWidget *calendar_perms_combobox;
+ GtkWidget *task_perms_combobox;
+ GtkWidget *inbox_perms_combobox;
+ GtkWidget *contact_perms_combobox;
+ GtkWidget *delegate_mail;
+ GtkWidget *see_private_checkbox;
+ GtkWidget *combobox, *comboboxes[EXCHANGE_DELEGATES_LAST];
+
+ g_return_val_if_fail (EXCHANGE_IS_DELEGATES_USER (user), FALSE);
+ g_return_val_if_fail (E2K_IS_SID (user->sid), FALSE);
+
+ delegate_permissions = gtk_dialog_new_with_buttons (
+ _("Delegate Permissions"),
+ NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+
+ if (parent_window)
+ gtk_window_set_transient_for (GTK_WINDOW (delegate_permissions), GTK_WINDOW (parent_window));
+
+ dialog_vbox1 = gtk_dialog_get_content_area (GTK_DIALOG (delegate_permissions));
+ gtk_widget_show (dialog_vbox1);
+
+ vbox3 = gtk_vbox_new (FALSE, 12);
+ gtk_widget_show (vbox3);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox1), vbox3, TRUE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox3), 12);
+
+ delegate_label = gtk_label_new (_("Permissions for"));
+ gtk_widget_show (delegate_label);
+ gtk_box_pack_start (GTK_BOX (vbox3), delegate_label, FALSE, FALSE, 0);
+ gtk_label_set_justify (GTK_LABEL (delegate_label), GTK_JUSTIFY_CENTER);
+
+ folders_table = gtk_table_new (4, 2, FALSE);
+ gtk_widget_show (folders_table);
+ gtk_box_pack_start (GTK_BOX (vbox3), folders_table, FALSE, FALSE, 0);
+ gtk_table_set_row_spacings (GTK_TABLE (folders_table), 6);
+ gtk_table_set_col_spacings (GTK_TABLE (folders_table), 6);
+
+ /* Translators: This is used for permissions for <user> for the folder Calendar. */
+ calendar_label = gtk_label_new_with_mnemonic (_("C_alendar:"));
+ gtk_widget_show (calendar_label);
+ gtk_table_attach (GTK_TABLE (folders_table), calendar_label, 0, 1, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_label_set_justify (GTK_LABEL (calendar_label), GTK_JUSTIFY_CENTER);
+ gtk_misc_set_alignment (GTK_MISC (calendar_label), 0, 0.5);
+
+ /* Translators: This is used for permissions for <user> for the folder Tasks. */
+ task_label = gtk_label_new_with_mnemonic (_("_Tasks:"));
+ gtk_widget_show (task_label);
+ gtk_table_attach (GTK_TABLE (folders_table), task_label, 0, 1, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_label_set_justify (GTK_LABEL (task_label), GTK_JUSTIFY_CENTER);
+ gtk_misc_set_alignment (GTK_MISC (task_label), 0, 0.5);
+
+ /* Translators: This is used for permissions for <user> for the folder Inbox. */
+ inbox_label = gtk_label_new_with_mnemonic (_("_Inbox:"));
+ gtk_widget_show (inbox_label);
+ gtk_table_attach (GTK_TABLE (folders_table), inbox_label, 0, 1, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_label_set_justify (GTK_LABEL (inbox_label), GTK_JUSTIFY_CENTER);
+ gtk_misc_set_alignment (GTK_MISC (inbox_label), 0, 0.5);
+
+ /* Translators: This is used for permissions for <user> for the folder Contacts. */
+ contact_label = gtk_label_new_with_mnemonic (_("Co_ntacts:"));
+ gtk_widget_show (contact_label);
+ gtk_table_attach (GTK_TABLE (folders_table), contact_label, 0, 1, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_label_set_justify (GTK_LABEL (contact_label), GTK_JUSTIFY_CENTER);
+ gtk_misc_set_alignment (GTK_MISC (contact_label), 0, 0.5);
+
+ calendar_perms_combobox = gtk_combo_box_new_text ();
+ gtk_widget_show (calendar_perms_combobox);
+ gtk_table_attach (GTK_TABLE (folders_table), calendar_perms_combobox, 1, 2, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ gtk_combo_box_append_text (GTK_COMBO_BOX (calendar_perms_combobox), _("None"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (calendar_perms_combobox), _("Reviewer (read-only)"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (calendar_perms_combobox), _("Author (read, create)"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (calendar_perms_combobox), _("Editor (read, create, edit)"));
+
+ task_perms_combobox = gtk_combo_box_new_text ();
+ gtk_widget_show (task_perms_combobox);
+ gtk_table_attach (GTK_TABLE (folders_table), task_perms_combobox, 1, 2, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ gtk_combo_box_append_text (GTK_COMBO_BOX (task_perms_combobox), _("None"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (task_perms_combobox), _("Reviewer (read-only)"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (task_perms_combobox), _("Author (read, create)"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (task_perms_combobox), _("Editor (read, create, edit)"));
+
+ inbox_perms_combobox = gtk_combo_box_new_text ();
+ gtk_widget_show (inbox_perms_combobox);
+ gtk_table_attach (GTK_TABLE (folders_table), inbox_perms_combobox, 1, 2, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ gtk_combo_box_append_text (GTK_COMBO_BOX (inbox_perms_combobox), _("None"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (inbox_perms_combobox), _("Reviewer (read-only)"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (inbox_perms_combobox), _("Author (read, create)"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (inbox_perms_combobox), _("Editor (read, create, edit)"));
+
+ contact_perms_combobox = gtk_combo_box_new_text ();
+ gtk_widget_show (contact_perms_combobox);
+ gtk_table_attach (GTK_TABLE (folders_table), contact_perms_combobox, 1, 2, 3, 4,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ gtk_combo_box_append_text (GTK_COMBO_BOX (contact_perms_combobox), _("None"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (contact_perms_combobox), _("Reviewer (read-only)"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (contact_perms_combobox), _("Author (read, create)"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (contact_perms_combobox), _("Editor (read, create, edit)"));
+
+ delegate_mail = gtk_check_button_new_with_mnemonic (_("_Summarize permissions"));
+ gtk_widget_show (delegate_mail);
+ gtk_box_pack_start (GTK_BOX (vbox3), delegate_mail, FALSE, FALSE, 0);
+
+ see_private_checkbox = gtk_check_button_new_with_mnemonic (_("_Delegate can see private items"));
+ gtk_widget_show (see_private_checkbox);
+ gtk_box_pack_start (GTK_BOX (vbox3), see_private_checkbox, FALSE, FALSE, 0);
+
+ gtk_box_set_spacing (GTK_BOX (dialog_vbox1), 6);
+
+ title = g_strdup_printf (_("Permissions for %s"), user->display_name);
+ gtk_label_set_text (GTK_LABEL (delegate_label), title);
+ g_free (title);
+
+ comboboxes[0] = calendar_perms_combobox;
+ comboboxes[1] = task_perms_combobox;
+ comboboxes[2] = inbox_perms_combobox;
+ comboboxes[3] = contact_perms_combobox;
+
+ /* Set up the permissions */
+ for (i = 0; i < EXCHANGE_DELEGATES_LAST; i++) {
+ combobox = comboboxes[i];
+ set_perms (combobox, user->role[i]);
+ }
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (see_private_checkbox),
+ user->see_private);
+
+ /* Run the dialog, while watching its parent. */
+ g_object_weak_ref (G_OBJECT (parent_window),
+ parent_window_destroyed, delegate_permissions);
+ g_object_add_weak_pointer (G_OBJECT (parent_window),
+ (gpointer*)&parent_window);
+ button = gtk_dialog_run (GTK_DIALOG (delegate_permissions));
+ if (parent_window) {
+ g_object_remove_weak_pointer (G_OBJECT (parent_window),
+ (gpointer *)&parent_window);
+ g_object_weak_unref (G_OBJECT (parent_window),
+ parent_window_destroyed, delegate_permissions);
+ }
+
+ if (button != GTK_RESPONSE_OK) {
+ gtk_widget_destroy (delegate_permissions);
+ return FALSE;
+ }
+
+ /* And update */
+ modified = FALSE;
+ for (i = 0; i < EXCHANGE_DELEGATES_LAST; i++) {
+ combobox = comboboxes[i];
+ role = e_dialog_combo_box_get (combobox, exchange_perm_map);
+
+ if (is_delegate_role (user->role[i]) &&
+ user->role[i] != role) {
+ user->role[i] = role;
+ modified = TRUE;
+ }
+ }
+
+ /* The following piece of code is used to construct a mail message to be sent to a Delegate
+ summarizing all the permissions set for him on the user's various folders.
+ */
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (delegate_mail)) == TRUE) {
+ if (button == GTK_RESPONSE_OK) {
+
+ EAccount *eaccount;
+ CamelMimeMessage *delegate_mail = camel_mime_message_new ();
+ CamelMultipart *body = camel_multipart_new ();
+ CamelMimePart *part;
+ CamelDataWrapper *delegate_mail_text, *delegate_mail_data;
+ CamelContentType *type;
+ CamelInternetAddress *addr;
+ CamelStream *stream;
+ CamelFolder *out_folder;
+ CamelMessageInfo *info;
+ gchar *self_address, *delegate_mail_subject;
+ gchar *role_name;
+ GString *role_name_final;
+
+ const gchar *recipient_address;
+ const gchar *delegate_exchange_dn;
+ const gchar *msg_part1 = NULL, *msg_part2 = NULL;
+
+ role_name_final = g_string_new ("");
+
+ self_address = g_strdup (exchange_account_get_email_id (account));
+
+ /* Create toplevel container */
+ camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (body),
+ "multipart/alternative;");
+ camel_multipart_set_boundary (body, NULL);
+
+ /* Create textual receipt */
+ delegate_mail_text = camel_data_wrapper_new ();
+ type = camel_content_type_new ("text", "html");
+ camel_content_type_set_param (type, "format", "flowed");
+ camel_data_wrapper_set_mime_type_field (delegate_mail_text, type);
+ camel_content_type_unref (type);
+ stream = camel_stream_mem_new ();
+
+ /* To translators: This is a part of the message to be sent to the delegatee
+ summarizing the permissions assigned to him.
+ */
+ msg_part1 = _("This message was sent automatically by Evolution to inform you that you have been "
+ "designated as a delegate. You can now send messages on my behalf.");
+
+ /* To translators: Another chunk of the same message.
+ */
+ msg_part2 = _("You have been given the following permissions on my folders:");
+
+ camel_stream_printf (stream,
+ "<html><body><p>%s<br><br>%s</p><table border = 0 width=\"40%%\">", msg_part1, msg_part2);
+ for (i = 0; i < EXCHANGE_DELEGATES_LAST; i++) {
+ combobox = comboboxes[i];
+ role = e_dialog_combo_box_get (combobox, exchange_perm_map);
+ role_name = g_strdup (map_to_full_role_name(role));
+ g_string_append_printf (
+ role_name_final,
+ "<tr><td>%s:</td><td>%s</td></tr>",
+ folder_names_for_display[i], role_name);
+ }
+
+ camel_stream_printf (stream, "%s</table>", role_name_final->str);
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (see_private_checkbox)) == TRUE) {
+ /* To translators: This message is included if the delegatee has been given access
+ to the private items.
+ */
+ camel_stream_printf (stream, "<br>%s", _("You are also permitted "
+ "to see my private items."));
+ }
+ else
+ /* To translators: This message is included if the delegatee has not been given access
+ to the private items.
+ */
+ camel_stream_printf (stream, "<br>%s", _("However you are not permitted "
+ "to see my private items."));
+ camel_data_wrapper_construct_from_stream (delegate_mail_text, stream);
+ g_free (role_name);
+ g_string_free (role_name_final, TRUE);
+ camel_object_unref (stream);
+
+ part = camel_mime_part_new ();
+ camel_medium_set_content_object (CAMEL_MEDIUM (part), delegate_mail_text);
+ camel_object_unref (delegate_mail_text);
+ camel_multipart_add_part (body, part);
+ camel_object_unref (part);
+
+ /* Create the machine-readable receipt */
+ delegate_mail_data = camel_data_wrapper_new ();
+ type = camel_content_type_new ("message", "disposition-notification");
+ camel_data_wrapper_set_mime_type_field (delegate_mail_data, type);
+ camel_content_type_unref (type);
+ stream = camel_stream_mem_new ();
+ part = camel_mime_part_new ();
+
+ camel_data_wrapper_construct_from_stream (delegate_mail_data, stream);
+ camel_object_unref (stream);
+ camel_medium_set_content_object (CAMEL_MEDIUM (part), delegate_mail_data);
+ camel_object_unref (delegate_mail_data);
+ camel_multipart_add_part (body, part);
+ camel_object_unref (part);
+
+ /* Finish creating the message */
+ camel_medium_set_content_object (CAMEL_MEDIUM (delegate_mail), CAMEL_DATA_WRAPPER (body));
+ camel_object_unref (body);
+
+ delegate_mail_subject = g_strdup_printf (_("You have been designated "
+ "as a delegate for %s"), exchange_account_get_username (account));
+ camel_mime_message_set_subject (delegate_mail, delegate_mail_subject);
+ g_free (delegate_mail_subject);
+
+ addr = camel_internet_address_new ();
+ camel_address_decode (CAMEL_ADDRESS (addr), self_address);
+ camel_mime_message_set_from (delegate_mail, addr);
+ g_free (self_address);
+ camel_object_unref (addr);
+
+ delegate_exchange_dn = e2k_entryid_to_dn (user->entryid);
+ recipient_address = email_look_up (delegate_exchange_dn,account);
+
+ if (recipient_address) {
+ addr = camel_internet_address_new ();
+ camel_address_decode (CAMEL_ADDRESS (addr), recipient_address);
+ camel_mime_message_set_recipients (delegate_mail, CAMEL_RECIPIENT_TYPE_TO, addr);
+ camel_object_unref (addr);
+ }
+
+ eaccount = exchange_account_fetch (account);
+ if (eaccount) {
+ camel_medium_set_header (CAMEL_MEDIUM (delegate_mail),
+ "X-Evolution-Account", eaccount->uid);
+ camel_medium_set_header (CAMEL_MEDIUM (delegate_mail),
+ "X-Evolution-Transport", eaccount->transport->url);
+ camel_medium_set_header (CAMEL_MEDIUM (delegate_mail),
+ "X-Evolution-Fcc", eaccount->sent_folder_uri);
+ }
+
+ /* Send the permissions summarizing mail */
+ out_folder = e_mail_local_get_folder (E_MAIL_FOLDER_OUTBOX);
+ info = camel_message_info_new (NULL);
+ camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN);
+ mail_append_mail (out_folder, delegate_mail, info, em_utils_delegates_done, NULL);
+
+ }
+
+ }
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (see_private_checkbox)) !=
+ user->see_private) {
+ user->see_private = !user->see_private;
+ modified = TRUE;
+ }
+
+ gtk_widget_destroy (delegate_permissions);
+
+ if (modified)
+ g_signal_emit (user, signals[EDITED], 0);
+
+ return TRUE;
+}
+
+/**
+ * exchange_delegates_user_new:
+ * @display_name: the delegate's (UTF8) display name
+ *
+ * Return value: a new delegate user with default permissions (but
+ * with most of the internal data blank).
+ **/
+ExchangeDelegatesUser *
+exchange_delegates_user_new (const gchar *display_name)
+{
+ ExchangeDelegatesUser *user;
+ gint i;
+
+ user = g_object_new (EXCHANGE_TYPE_DELEGATES_USER, NULL);
+ user->display_name = g_strdup (display_name);
+
+ for (i = 0; i < EXCHANGE_DELEGATES_LAST; i++) {
+ if (i == EXCHANGE_DELEGATES_CALENDAR ||
+ i == EXCHANGE_DELEGATES_TASKS)
+ user->role[i] = E2K_PERMISSIONS_ROLE_EDITOR;
+ else
+ user->role[i] = E2K_PERMISSIONS_ROLE_NONE;
+ }
+
+ return user;
+}
+
+/**
+ * exchange_delegates_user_new_from_gc:
+ * @gc: the global catalog object
+ * @email: email address of the new delegate
+ * @creator_entryid: The value of the PR_CREATOR_ENTRYID property
+ * on the LocalFreebusy file.
+ *
+ * Return value: a new delegate user with default permissions and
+ * internal data filled in from the global catalog.
+ **/
+ExchangeDelegatesUser *
+exchange_delegates_user_new_from_gc (E2kGlobalCatalog *gc,
+ const gchar *email,
+ GByteArray *creator_entryid)
+{
+ E2kGlobalCatalogStatus status;
+ E2kGlobalCatalogEntry *entry;
+ ExchangeDelegatesUser *user;
+ guint8 *p;
+
+ status = e2k_global_catalog_lookup (
+ gc, NULL, /* FIXME: cancellable */
+ E2K_GLOBAL_CATALOG_LOOKUP_BY_EMAIL, email,
+ (E2K_GLOBAL_CATALOG_LOOKUP_SID |
+ E2K_GLOBAL_CATALOG_LOOKUP_LEGACY_EXCHANGE_DN),
+ &entry);
+ if (status != E2K_GLOBAL_CATALOG_OK)
+ return NULL;
+
+ user = exchange_delegates_user_new (e2k_sid_get_display_name (entry->sid));
+ user->dn = g_strdup (entry->dn);
+ user->sid = entry->sid;
+ g_object_ref (user->sid);
+
+ user->entryid = g_byte_array_new ();
+ p = creator_entryid->data + creator_entryid->len - 2;
+ while (p > creator_entryid->data && *p)
+ p--;
+ g_byte_array_append (user->entryid, creator_entryid->data,
+ p - creator_entryid->data + 1);
+ g_byte_array_append (user->entryid, (guint8*)entry->legacy_exchange_dn,
+ strlen (entry->legacy_exchange_dn));
+ g_byte_array_append (user->entryid, (guint8*)"", 1);
+
+ return user;
+}
diff --git a/eplugin/exchange-delegates-user.h b/eplugin/exchange-delegates-user.h
new file mode 100644
index 0000000..3d886d7
--- /dev/null
+++ b/eplugin/exchange-delegates-user.h
@@ -0,0 +1,81 @@
+/*
+ *
+ * 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/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __EXCHANGE_DELEGATES_USER_H__
+#define __EXCHANGE_DELEGATES_USER_H__
+
+#include <exchange-types.h>
+#include <e2k-security-descriptor.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define EXCHANGE_TYPE_DELEGATES_USER (exchange_delegates_user_get_type ())
+#define EXCHANGE_DELEGATES_USER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXCHANGE_TYPE_DELEGATES_USER, ExchangeDelegatesUser))
+#define EXCHANGE_DELEGATES_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EXCHANGE_TYPE_DELEGATES_USER, ExchangeDelegatesUserClass))
+#define EXCHANGE_IS_DELEGATES_USER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXCHANGE_TYPE_DELEGATES_USER))
+#define EXCHANGE_IS_DELEGATES_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EXCHANGE_TYPE_DELEGATES_USER))
+
+
+typedef struct _ExchangeDelegatesUser ExchangeDelegatesUser;
+typedef struct _ExchangeDelegatesUserPrivate ExchangeDelegatesUserPrivate;
+typedef struct _ExchangeDelegatesUserClass ExchangeDelegatesUserClass;
+
+enum {
+ EXCHANGE_DELEGATES_CALENDAR,
+ EXCHANGE_DELEGATES_TASKS,
+ EXCHANGE_DELEGATES_INBOX,
+ EXCHANGE_DELEGATES_CONTACTS,
+ EXCHANGE_DELEGATES_LAST
+};
+
+struct _ExchangeDelegatesUser {
+ GObject parent;
+
+ gchar *display_name, *dn;
+ GByteArray *entryid;
+
+ E2kSid *sid;
+ E2kPermissionsRole role[EXCHANGE_DELEGATES_LAST];
+ gboolean see_private;
+};
+
+struct _ExchangeDelegatesUserClass {
+ GObjectClass parent_class;
+
+ /* signals */
+ void (*edited) (ExchangeDelegatesUser *, gpointer);
+};
+
+
+
+GType exchange_delegates_user_get_type (void);
+
+ExchangeDelegatesUser *exchange_delegates_user_new (const gchar *display_name);
+ExchangeDelegatesUser *exchange_delegates_user_new_from_gc (E2kGlobalCatalog *gc,
+ const gchar *email,
+ GByteArray *creator_entryid);
+
+gboolean exchange_delegates_user_edit (ExchangeAccount *account, ExchangeDelegatesUser *user,
+ GtkWidget *parent_window);
+
+G_END_DECLS
+
+#endif /* __EXCHANGE_DELEGATES_USER_H__ */
diff --git a/eplugin/exchange-delegates.c b/eplugin/exchange-delegates.c
new file mode 100644
index 0000000..89da03e
--- /dev/null
+++ b/eplugin/exchange-delegates.c
@@ -0,0 +1,1027 @@
+/*
+ * 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:
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+/* ExchangeDelegates: Exchange delegate handling.
+ *
+ * FIXME: make this instant-apply
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include "exchange-delegates.h"
+#include "exchange-delegates-user.h"
+#include "exchange-user-dialog.h"
+#include "exchange-operations.h"
+
+#include <exchange-account.h>
+#include <e2k-propnames.h>
+#include <e2k-security-descriptor.h>
+#include <e2k-sid.h>
+#include <e2k-uri.h>
+#include <e2k-utils.h>
+
+#include <e-util/e-dialog-utils.h>
+#include <e-util/e-error.h>
+
+typedef struct {
+ const gchar *uri;
+ E2kSecurityDescriptor *sd;
+ gboolean changed;
+} ExchangeDelegatesFolder;
+
+typedef struct {
+ ExchangeAccount *account;
+ gchar *self_dn;
+
+ GtkWidget *dialog, *parent;
+
+ GtkListStore *model;
+ GtkWidget *table;
+
+ GByteArray *creator_entryid;
+ GPtrArray *users, *added_users, *removed_users;
+ gboolean loaded_folders;
+ ExchangeDelegatesFolder folder[EXCHANGE_DELEGATES_LAST];
+ ExchangeDelegatesFolder freebusy_folder;
+} ExchangeDelegates;
+
+extern const gchar *exchange_delegates_user_folder_names[];
+
+const gchar *exchange_localfreebusy_path = "NON_IPM_SUBTREE/Freebusy%20Data/LocalFreebusy.EML";
+
+static void set_perms_for_user (ExchangeDelegatesUser *user, gpointer user_data);
+
+static void
+set_sd_for_href (ExchangeDelegates *delegates,
+ const gchar *href,
+ E2kSecurityDescriptor *sd)
+{
+ gint i;
+
+ for (i = 0; i < EXCHANGE_DELEGATES_LAST; i++) {
+ if (!delegates->folder[i].uri)
+ continue;
+
+ if (!strcmp (href, delegates->folder[i].uri)) {
+ delegates->folder[i].sd = sd;
+ return;
+ }
+ }
+
+ /* else, it's the freebusy folder */
+ delegates->freebusy_folder.uri = g_strdup (href);
+ delegates->freebusy_folder.sd = sd;
+}
+
+/* Given an array of ExchangeDelegatesUser containing display names
+ * and entryids, and an array of E2kSecurityDescriptors containing
+ * SIDs (which contain display names), add SIDs to the delegates. In
+ * the easy case, we can just match the SIDs up with their
+ * corresponding user by display name. However, there are two things
+ * that can go wrong:
+ *
+ * 1. Some users may have been removed from the SDs
+ * 2. Two users may have the same display name
+ *
+ * In both cases, we fall back to using the GC.
+ */
+static gboolean
+fill_in_sids (ExchangeDelegates *delegates)
+{
+ gint u, u2, sd, needed_sids;
+ ExchangeDelegatesUser *user, *user2;
+ GList *sids, *s;
+ E2kSid *sid;
+ E2kGlobalCatalog *gc;
+ E2kGlobalCatalogStatus status;
+ E2kGlobalCatalogEntry *entry;
+ gboolean ok = TRUE;
+
+ needed_sids = 0;
+
+ /* Mark users with duplicate names and count the number of
+ * non-duplicate names.
+ */
+ for (u = 0; u < delegates->users->len; u++) {
+ user = delegates->users->pdata[u];
+ if (user->sid == (E2kSid *)-1)
+ continue;
+ for (u2 = u + 1; u2 < delegates->users->len; u2++) {
+ user2 = delegates->users->pdata[u2];
+ if (!strcmp (user->display_name, user2->display_name))
+ user->sid = user2->sid = (E2kSid *)-1;
+ }
+ if (!user->sid)
+ needed_sids++;
+ }
+
+ /* Scan security descriptors trying to match SIDs until we're
+ * not expecting to find any more.
+ */
+ for (sd = 0; sd < EXCHANGE_DELEGATES_LAST && needed_sids; sd++) {
+ sids = e2k_security_descriptor_get_sids (delegates->folder[sd].sd);
+ for (s = sids; s && needed_sids; s = s->next) {
+ sid = s->data;
+ for (u = 0; u < delegates->users->len; u++) {
+ user = delegates->users->pdata[u];
+ if (user->sid)
+ continue;
+ if (!strcmp (user->display_name,
+ e2k_sid_get_display_name (sid))) {
+ user->sid = sid;
+ g_object_ref (sid);
+ needed_sids--;
+ }
+ }
+ }
+ g_list_free (sids);
+ }
+
+ /* Now for each user whose SID hasn't yet been found, look it up. */
+ gc = exchange_account_get_global_catalog (delegates->account);
+ for (u = 0; u < delegates->users->len; u++) {
+ user = delegates->users->pdata[u];
+ if (user->sid && user->sid != (E2kSid *)-1)
+ continue;
+
+ status = e2k_global_catalog_lookup (
+ gc, NULL, /* FIXME: cancellable */
+ E2K_GLOBAL_CATALOG_LOOKUP_BY_LEGACY_EXCHANGE_DN,
+ e2k_entryid_to_dn (user->entryid),
+ E2K_GLOBAL_CATALOG_LOOKUP_SID, &entry);
+ if (status != E2K_GLOBAL_CATALOG_OK) {
+ user->sid = NULL;
+ ok = FALSE;
+ continue;
+ }
+ user->sid = entry->sid;
+ g_object_ref (user->sid);
+ e2k_global_catalog_entry_free (gc, entry);
+ }
+
+ return ok;
+}
+
+static const gchar *sd_props[] = {
+ E2K_PR_EXCHANGE_SD_BINARY,
+ E2K_PR_EXCHANGE_SD_XML
+};
+static const gint n_sd_props = sizeof (sd_props) / sizeof (sd_props[0]);
+
+/* Read the folder security descriptors and match them up with the
+ * list of delegates.
+ */
+static gboolean
+get_folder_security (ExchangeDelegates *delegates)
+{
+ GPtrArray *hrefs;
+ E2kContext *ctx;
+ E2kHTTPStatus status;
+ E2kResultIter *iter;
+ E2kResult *result;
+ xmlNode *xml_form;
+ GByteArray *binary_form;
+ ExchangeDelegatesUser *user;
+ guint32 perms;
+ gint i, u;
+
+ /* If we've been here before, just return the success or
+ * failure result from last time.
+ */
+ if (delegates->freebusy_folder.uri)
+ return delegates->loaded_folders;
+
+ if (!exchange_account_get_global_catalog (delegates->account)) {
+ e_error_run (GTK_WINDOW (delegates->table), ERROR_DOMAIN ":delegates-no-gcs-error",
+ NULL);
+ return FALSE;
+ }
+
+ ctx = exchange_account_get_context (delegates->account);
+
+ hrefs = g_ptr_array_new ();
+ for (i = 0; i < EXCHANGE_DELEGATES_LAST; i++) {
+ delegates->folder[i].uri = exchange_account_get_standard_uri (
+ delegates->account, exchange_delegates_user_folder_names[i]);
+ if (delegates->folder[i].uri) {
+ g_ptr_array_add (hrefs, (gchar *)e2k_uri_relative (
+ delegates->account->home_uri,
+ delegates->folder[i].uri));
+ }
+ }
+ g_ptr_array_add (hrefs, (gchar *)exchange_localfreebusy_path);
+
+ iter = e2k_context_bpropfind_start (
+ ctx, NULL, delegates->account->home_uri,
+ (const gchar **)hrefs->pdata, hrefs->len,
+ sd_props, n_sd_props);
+ g_ptr_array_free (hrefs, TRUE);
+
+ while ((result = e2k_result_iter_next (iter))) {
+ xml_form = e2k_properties_get_prop (result->props,
+ E2K_PR_EXCHANGE_SD_XML);
+ binary_form = e2k_properties_get_prop (result->props,
+ E2K_PR_EXCHANGE_SD_BINARY);
+
+ if (xml_form && binary_form) {
+ set_sd_for_href (delegates, result->href,
+ e2k_security_descriptor_new (xml_form, binary_form));
+ }
+ }
+ status = e2k_result_iter_free (iter);
+
+ if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
+ e_error_run (GTK_WINDOW (delegates->table), ERROR_DOMAIN ":delegates-perm-read-error",
+ NULL);
+ return FALSE;
+ }
+
+ if (!fill_in_sids (delegates)) {
+ delegates->loaded_folders = FALSE;
+ e_error_run (GTK_WINDOW (delegates->table), ERROR_DOMAIN ":perm-deter-error", NULL);
+ return FALSE;
+ }
+
+ /* Fill in delegate structures from the security descriptors */
+ for (i = 0; i < EXCHANGE_DELEGATES_LAST; i++) {
+ for (u = 0; u < delegates->users->len; u++) {
+ user = delegates->users->pdata[u];
+ perms = e2k_security_descriptor_get_permissions (
+ delegates->folder[i].sd, user->sid);
+ user->role[i] = e2k_permissions_role_find (perms);
+ }
+ }
+
+ delegates->loaded_folders = TRUE;
+ return TRUE;
+}
+
+static const gchar *delegation_props[] = {
+ PR_DELEGATES_DISPLAY_NAMES,
+ PR_DELEGATES_ENTRYIDS,
+ PR_DELEGATES_SEE_PRIVATE,
+ PR_CREATOR_ENTRYID
+};
+static const gint n_delegation_props = sizeof (delegation_props) / sizeof (delegation_props[0]);
+
+/* Fetch the list of delegates from the freebusy message. */
+static gboolean
+get_user_list (ExchangeDelegates *delegates)
+{
+ E2kContext *ctx;
+ E2kResultIter *iter;
+ E2kResult *result;
+ GPtrArray *display_names, *entryids, *privflags;
+ GByteArray *entryid;
+ ExchangeDelegatesUser *user;
+ gint i;
+
+ ctx = exchange_account_get_context (delegates->account);
+ iter = e2k_context_bpropfind_start (ctx, NULL,
+ delegates->account->home_uri,
+ &exchange_localfreebusy_path, 1,
+ delegation_props, n_delegation_props);
+ result = e2k_result_iter_next (iter);
+ if (!result || !E2K_HTTP_STATUS_IS_SUCCESSFUL (result->status)) {
+ e2k_result_iter_free (iter);
+ return FALSE;
+ }
+
+ delegates->users = g_ptr_array_new ();
+ delegates->added_users = g_ptr_array_new ();
+ delegates->removed_users = g_ptr_array_new ();
+
+ display_names = e2k_properties_get_prop (result->props, PR_DELEGATES_DISPLAY_NAMES);
+ entryids = e2k_properties_get_prop (result->props, PR_DELEGATES_ENTRYIDS);
+ privflags = e2k_properties_get_prop (result->props, PR_DELEGATES_SEE_PRIVATE);
+
+ entryid = e2k_properties_get_prop (result->props, PR_CREATOR_ENTRYID);
+ delegates->creator_entryid = g_byte_array_new ();
+ g_byte_array_append (delegates->creator_entryid, entryid->data, entryid->len);
+
+ if (!display_names || !entryids || !privflags) {
+ e2k_result_iter_free (iter);
+ return TRUE;
+ }
+
+ for (i = 0; i < display_names->len && i < entryids->len && i < privflags->len; i++) {
+ user = exchange_delegates_user_new (display_names->pdata[i]);
+ user->see_private = privflags->pdata[i] && atoi (privflags->pdata[i]);
+ entryid = entryids->pdata[i];
+ user->entryid = g_byte_array_new ();
+ g_byte_array_append (user->entryid, entryid->data, entryid->len);
+
+ g_signal_connect (user, "edited", G_CALLBACK (set_perms_for_user), delegates);
+
+ g_ptr_array_add (delegates->users, user);
+ }
+
+ e2k_result_iter_free (iter);
+ return TRUE;
+}
+
+/* Add or remove a delegate. Everyone must be in one of three states:
+ * 1. only in users (because they started and ended there)
+ * 2. in users and added_users (because they weren't in
+ * users to begin with, but got added)
+ * 3. only in removed_users (because they were in users to
+ * begin with and got removed).
+ * If you're added and then removed, or removed and then added, you have
+ * to end up in state 1. That's what this is for.
+ */
+static void
+add_remove_user (ExchangeDelegatesUser *user,
+ GPtrArray *to_array, GPtrArray *from_array)
+{
+ ExchangeDelegatesUser *match;
+ gint i;
+
+ for (i = 0; i < from_array->len; i++) {
+ match = from_array->pdata[i];
+ if (e2k_sid_binary_sid_equal (e2k_sid_get_binary_sid (match->sid),
+ e2k_sid_get_binary_sid (user->sid))) {
+ g_ptr_array_remove_index_fast (from_array, i);
+ g_object_unref (match);
+ return;
+ }
+ }
+
+ g_ptr_array_add (to_array, user);
+ g_object_ref (user);
+}
+
+static void
+set_perms_for_user (ExchangeDelegatesUser *user, gpointer user_data)
+{
+ ExchangeDelegates *delegates = user_data;
+ gint i, role;
+ guint32 perms;
+
+ for (i = 0; i < EXCHANGE_DELEGATES_LAST; i++) {
+ perms = e2k_permissions_role_get_perms (user->role[i]);
+ e2k_security_descriptor_set_permissions (delegates->folder[i].sd,
+ user->sid, perms);
+ }
+ role = user->role[EXCHANGE_DELEGATES_CALENDAR];
+ if (role == E2K_PERMISSIONS_ROLE_AUTHOR)
+ role = E2K_PERMISSIONS_ROLE_EDITOR;
+ perms = e2k_permissions_role_get_perms (role);
+ e2k_security_descriptor_set_permissions (delegates->freebusy_folder.sd,
+ user->sid, perms);
+}
+
+static void
+add_button_clicked_cb (GtkWidget *widget, gpointer data)
+{
+ ExchangeDelegates *delegates = data;
+ E2kGlobalCatalog *gc;
+ GtkWidget *dialog, *parent_window;
+ const gchar *delegate_exchange_dn;
+ gchar *email;
+ ExchangeDelegatesUser *user, *match;
+ gint response, u;
+ GtkTreeIter iter;
+
+ if (!get_folder_security (delegates))
+ return;
+
+ gc = exchange_account_get_global_catalog (delegates->account);
+
+ parent_window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
+ dialog = e2k_user_dialog_new (parent_window,
+ _("Delegate To:"), _("Delegate To"));
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+ if (response != GTK_RESPONSE_OK) {
+ gtk_widget_destroy (dialog);
+ return;
+ }
+ email = e2k_user_dialog_get_user (E2K_USER_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ if (email == NULL)
+ return;
+
+ user = exchange_delegates_user_new_from_gc (gc, email,
+ delegates->creator_entryid);
+ if (!user) {
+ e_error_run (GTK_WINDOW (parent_window), ERROR_DOMAIN ":delegate-error", email, NULL);
+ g_free (email);
+ return;
+ }
+ g_free (email);
+
+ delegate_exchange_dn = e2k_entryid_to_dn (user->entryid);
+ if (delegate_exchange_dn && !g_ascii_strcasecmp (delegate_exchange_dn, delegates->account->legacy_exchange_dn)) {
+ g_object_unref (user);
+ e_error_run (GTK_WINDOW (parent_window), ERROR_DOMAIN ":delegate-own-error", NULL);
+ return;
+ }
+
+ for (u = 0; u < delegates->users->len; u++) {
+ match = delegates->users->pdata[u];
+ if (e2k_sid_binary_sid_equal (e2k_sid_get_binary_sid (user->sid),
+ e2k_sid_get_binary_sid (match->sid))) {
+ e_error_run (GTK_WINDOW (parent_window), ERROR_DOMAIN ":delegate-existing",
+ user->display_name, NULL);
+ g_object_unref (user);
+ exchange_delegates_user_edit (delegates->account, match, parent_window);
+ return;
+ }
+ }
+
+ if (!exchange_delegates_user_edit (delegates->account, user, parent_window)) {
+ g_object_unref (user);
+ return;
+ }
+ set_perms_for_user (user, delegates);
+ g_signal_connect (user, "edited",
+ G_CALLBACK (set_perms_for_user), delegates);
+
+ add_remove_user (user, delegates->added_users, delegates->removed_users);
+ g_ptr_array_add (delegates->users, user);
+
+ /* Add the user to the table */
+ gtk_list_store_append (delegates->model, &iter);
+ gtk_list_store_set (delegates->model, &iter,
+ 0, user->display_name,
+ -1);
+}
+
+static gint
+get_selected_row (GtkWidget *tree_view, GtkTreeIter *iter)
+{
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ gint *indices, row;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
+ if (!gtk_tree_selection_get_selected (selection, &model, iter))
+ return -1;
+
+ path = gtk_tree_model_get_path (model, iter);
+ indices = gtk_tree_path_get_indices (path);
+ row = indices[0];
+ gtk_tree_path_free (path);
+
+ return row;
+}
+
+static void
+edit_button_clicked_cb (GtkWidget *widget, gpointer data)
+{
+ ExchangeDelegates *delegates = data;
+ GtkWidget *parent_window;
+ GtkTreeIter iter;
+ gint row;
+
+ if (!get_folder_security (delegates))
+ return;
+
+ row = get_selected_row (delegates->table, &iter);
+ g_return_if_fail (row >= 0 && row < delegates->users->len);
+
+ parent_window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
+
+ exchange_delegates_user_edit (delegates->account, delegates->users->pdata[row],
+ parent_window);
+}
+
+const gchar *
+email_look_up (const gchar *delegate_legacy, ExchangeAccount *account)
+{
+ E2kGlobalCatalog *gc;
+ E2kGlobalCatalogEntry *entry;
+ E2kGlobalCatalogStatus status;
+
+ const gchar *email_id;
+
+ gc = exchange_account_get_global_catalog (account);
+
+ if (!gc)
+ return NULL;
+
+ status = e2k_global_catalog_lookup (
+ gc, NULL, E2K_GLOBAL_CATALOG_LOOKUP_BY_LEGACY_EXCHANGE_DN,
+ delegate_legacy, 0, &entry);
+
+ email_id = g_strdup (entry->email);
+ e2k_global_catalog_entry_free (gc, entry);
+ return email_id;
+}
+
+static gboolean
+table_click_cb (GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+ ExchangeDelegates *delegates = data;
+ GtkWidget *parent_window;
+ GtkTreeIter iter;
+ gint row;
+
+ if (event->type != GDK_2BUTTON_PRESS)
+ return FALSE;
+
+ row = get_selected_row (delegates->table, &iter);
+ if (row < 0 || row >= delegates->users->len)
+ return FALSE;
+
+ if (!get_folder_security (delegates))
+ return FALSE;
+
+ parent_window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
+ exchange_delegates_user_edit (delegates->account, delegates->users->pdata[row],
+ parent_window);
+ return TRUE;
+}
+
+static void
+remove_button_clicked_cb (GtkWidget *widget, gpointer data)
+{
+ ExchangeDelegates *delegates = data;
+ ExchangeDelegatesUser *user;
+ GtkWidget *dialog;
+ gint row, btn, i;
+ GtkTreeIter iter;
+
+ if (!get_folder_security (delegates))
+ return;
+
+ row = get_selected_row (delegates->table, &iter);
+ g_return_if_fail (row >= 0 && row < delegates->users->len);
+
+ user = delegates->users->pdata[row];
+
+ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_YES_NO,
+ _("Remove the delegate %s?"),
+ user->display_name);
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (gtk_widget_get_toplevel (widget)));
+
+ btn = gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ if (btn != GTK_RESPONSE_YES)
+ return;
+
+ add_remove_user (user, delegates->removed_users, delegates->added_users);
+
+ for (i = 0; i < EXCHANGE_DELEGATES_LAST; i++) {
+ e2k_security_descriptor_remove_sid (delegates->folder[i].sd,
+ user->sid);
+ }
+ e2k_security_descriptor_remove_sid (delegates->freebusy_folder.sd,
+ user->sid);
+
+ /* Remove the user from the table */
+ gtk_list_store_remove (delegates->model, &iter);
+ g_ptr_array_remove_index (delegates->users, row);
+ g_object_unref (user);
+}
+
+static gboolean
+proppatch_sd (E2kContext *ctx, ExchangeDelegatesFolder *folder)
+{
+ GByteArray *binsd;
+ E2kProperties *props;
+ const gchar *href = "";
+ E2kResultIter *iter;
+ E2kResult *result;
+ E2kHTTPStatus status;
+
+ binsd = e2k_security_descriptor_to_binary (folder->sd);
+ if (!binsd)
+ return FALSE;
+
+ props = e2k_properties_new ();
+ e2k_properties_set_binary (props, E2K_PR_EXCHANGE_SD_BINARY, binsd);
+
+ iter = e2k_context_bproppatch_start (ctx, NULL, folder->uri,
+ &href, 1, props, FALSE);
+ e2k_properties_free (props);
+
+ result = e2k_result_iter_next (iter);
+ if (result) {
+ status = result->status;
+ e2k_result_iter_free (iter);
+ } else
+ status = e2k_result_iter_free (iter);
+
+ return E2K_HTTP_STATUS_IS_SUCCESSFUL (status);
+}
+
+static gboolean
+get_user_dn (E2kGlobalCatalog *gc, ExchangeDelegatesUser *user)
+{
+ E2kGlobalCatalogEntry *entry;
+ E2kGlobalCatalogStatus status;
+ const gchar *exchange_dn;
+
+ exchange_dn = e2k_entryid_to_dn (user->entryid);
+ status = e2k_global_catalog_lookup (
+ gc, NULL, /* FIXME: cancellable */
+ E2K_GLOBAL_CATALOG_LOOKUP_BY_LEGACY_EXCHANGE_DN,
+ exchange_dn, 0, &entry);
+ if (status != E2K_GLOBAL_CATALOG_OK)
+ return FALSE;
+
+ user->dn = g_strdup (entry->dn);
+ e2k_global_catalog_entry_free (gc, entry);
+ return TRUE;
+}
+
+static void
+delegates_apply (ExchangeDelegates *delegates)
+{
+ ExchangeDelegatesUser *user;
+ E2kGlobalCatalog *gc;
+ E2kContext *ctx;
+ GPtrArray *display_names, *entryids, *privflags;
+ GByteArray *entryid_dup;
+ gchar *error = NULL;
+ E2kProperties *props;
+ gint i;
+ E2kGlobalCatalogStatus status;
+
+ if (!delegates->loaded_folders)
+ return;
+
+ /* We can't do this atomically/transactionally, so we need to
+ * make sure that if we fail at any step, things are still in
+ * a semi-consistent state. So we do:
+ *
+ * 1. Remove old delegates from AD
+ * 2. Update LocalFreebusy.EML (the canonical list of delegates)
+ * 3. Add new delegates to AD
+ * 4. Update security descriptors
+ *
+ * If step 1 fails, nothing is changed.
+ *
+ * If step 2 fails, delegates who should have been removed
+ * will have been removed from AD but nothing else, so they
+ * will still show up as being delegates and the user can try
+ * to remove them again later.
+ *
+ * If step 3 fails, delegates who should have been added will
+ * not be in AD, but will be listed as delegates, so the user
+ * can remove them and try adding them again later.
+ *
+ * If step 4 fails, the user can still correct the folder
+ * permissions by hand.
+ */
+
+ gc = exchange_account_get_global_catalog (delegates->account);
+ if (!gc) {
+ error = g_strdup (_("Could not access Active Directory"));
+ goto done;
+ }
+
+ if ((delegates->removed_users || delegates->added_users) && !delegates->self_dn) {
+ E2kGlobalCatalogEntry *entry;
+
+ status = e2k_global_catalog_lookup (
+ gc, NULL, /* FIXME: cancellable */
+ E2K_GLOBAL_CATALOG_LOOKUP_BY_LEGACY_EXCHANGE_DN,
+ delegates->account->legacy_exchange_dn, 0, &entry);
+ if (status != E2K_GLOBAL_CATALOG_OK) {
+ error = g_strdup (_("Could not find self in Active Directory"));
+ goto done;
+ }
+
+ delegates->self_dn = g_strdup (entry->dn);
+ e2k_global_catalog_entry_free (gc, entry);
+ }
+
+ /* 1. Remove old delegates from AD */
+ while (delegates->removed_users && delegates->removed_users->len) {
+ user = delegates->removed_users->pdata[0];
+ if (!user->dn && !get_user_dn (gc, user)) {
+ error = g_strdup_printf (
+ _("Could not find delegate %s in Active Directory"),
+ user->display_name);
+ goto done;
+ }
+
+ /* FIXME: cancellable */
+ status = e2k_global_catalog_remove_delegate (gc, NULL,
+ delegates->self_dn,
+ user->dn);
+ if (status != E2K_GLOBAL_CATALOG_OK &&
+ status != E2K_GLOBAL_CATALOG_NO_DATA) {
+ error = g_strdup_printf (
+ _("Could not remove delegate %s"),
+ user->display_name);
+ goto done;
+ }
+
+ g_object_unref (user);
+ g_ptr_array_remove_index_fast (delegates->removed_users, 0);
+ }
+
+ /* 2. Update LocalFreebusy.EML */
+ ctx = exchange_account_get_context (delegates->account);
+
+ if (delegates->users->len) {
+ display_names = g_ptr_array_new ();
+ entryids = g_ptr_array_new ();
+ privflags = g_ptr_array_new ();
+
+ for (i = 0; i < delegates->users->len; i++) {
+ user = delegates->users->pdata[i];
+ g_ptr_array_add (display_names, g_strdup (user->display_name));
+ entryid_dup = g_byte_array_new ();
+ g_byte_array_append (entryid_dup, user->entryid->data,
+ user->entryid->len);
+ g_ptr_array_add (entryids, entryid_dup);
+ g_ptr_array_add (privflags, g_strdup_printf ("%d", user->see_private));
+ }
+
+ props = e2k_properties_new ();
+ e2k_properties_set_string_array (
+ props, PR_DELEGATES_DISPLAY_NAMES, display_names);
+ e2k_properties_set_binary_array (
+ props, PR_DELEGATES_ENTRYIDS, entryids);
+ e2k_properties_set_int_array (
+ props, PR_DELEGATES_SEE_PRIVATE, privflags);
+ } else if (delegates->removed_users) {
+ props = e2k_properties_new ();
+ e2k_properties_remove (props, PR_DELEGATES_DISPLAY_NAMES);
+ e2k_properties_remove (props, PR_DELEGATES_ENTRYIDS);
+ e2k_properties_remove (props, PR_DELEGATES_SEE_PRIVATE);
+ } else
+ props = NULL;
+
+ if (props) {
+ E2kResultIter *iter;
+ E2kResult *result;
+
+ iter = e2k_context_bproppatch_start (
+ ctx, NULL, delegates->account->home_uri,
+ &exchange_localfreebusy_path, 1,
+ props, FALSE);
+ e2k_properties_free (props);
+
+ result = e2k_result_iter_next (iter);
+ if (result) {
+ status = result->status;
+ e2k_result_iter_free (iter);
+ } else
+ status = e2k_result_iter_free (iter);
+
+ if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
+ error = g_strdup (_("Could not update list of delegates."));
+ goto done;
+ }
+ }
+
+ /* 3. Add new delegates to AD */
+ while (delegates->added_users && delegates->added_users->len) {
+ user = delegates->added_users->pdata[0];
+ /* An added user must have come from the GC so
+ * we know user->dn is set.
+ */
+ /* FIXME: cancellable */
+ status = e2k_global_catalog_add_delegate (gc, NULL,
+ delegates->self_dn,
+ user->dn);
+ if (status != E2K_GLOBAL_CATALOG_OK &&
+ status != E2K_GLOBAL_CATALOG_EXISTS) {
+ error = g_strdup_printf (
+ _("Could not add delegate %s"),
+ user->display_name);
+ goto done;
+ }
+ g_ptr_array_remove_index_fast (delegates->added_users, 0);
+ g_object_unref (user);
+ }
+
+ /* 4. Update security descriptors */
+ for (i = 0; i < EXCHANGE_DELEGATES_LAST; i++)
+ proppatch_sd (ctx, &delegates->folder[i]);
+ proppatch_sd (ctx, &delegates->freebusy_folder);
+
+ done:
+ if (error) {
+ e_error_run (GTK_WINDOW (delegates->table), ERROR_DOMAIN ":delegate-fail-error", error, NULL);
+ g_free (error);
+ }
+}
+
+static void parent_destroyed (gpointer user_data, GObject *ex_parent);
+
+static void
+delegates_destroy (ExchangeDelegates *delegates)
+{
+ gint i;
+
+ g_object_unref (delegates->account);
+
+ if (delegates->parent) {
+ g_object_weak_unref (G_OBJECT (delegates->parent),
+ parent_destroyed, delegates);
+ }
+ if (delegates->dialog)
+ gtk_widget_destroy (delegates->dialog);
+
+ if (delegates->model)
+ g_object_unref (delegates->model);
+
+ if (delegates->self_dn)
+ g_free (delegates->self_dn);
+ if (delegates->creator_entryid)
+ g_byte_array_free (delegates->creator_entryid, TRUE);
+
+ if (delegates->users) {
+ for (i = 0; i < delegates->users->len; i++)
+ g_object_unref (delegates->users->pdata[i]);
+ g_ptr_array_free (delegates->users, TRUE);
+ }
+ if (delegates->added_users) {
+ for (i = 0; i < delegates->added_users->len; i++)
+ g_object_unref (delegates->added_users->pdata[i]);
+ g_ptr_array_free (delegates->added_users, TRUE);
+ }
+ if (delegates->removed_users) {
+ for (i = 0; i < delegates->removed_users->len; i++)
+ g_object_unref (delegates->removed_users->pdata[i]);
+ g_ptr_array_free (delegates->removed_users, TRUE);
+ }
+
+ for (i = 0; i < EXCHANGE_DELEGATES_LAST; i++) {
+ if (delegates->folder[i].sd)
+ g_object_unref (delegates->folder[i].sd);
+ }
+ if (delegates->freebusy_folder.sd)
+ g_object_unref (delegates->freebusy_folder.sd);
+ if (delegates->freebusy_folder.uri)
+ g_free ((gchar *)delegates->freebusy_folder.uri);
+
+ g_free (delegates);
+}
+
+static void
+dialog_response (GtkDialog *dialog, gint response, gpointer user_data)
+{
+ ExchangeDelegates *delegates = user_data;
+
+ if (response == GTK_RESPONSE_OK)
+ delegates_apply (delegates);
+ delegates_destroy (delegates);
+}
+
+static void
+parent_destroyed (gpointer user_data, GObject *ex_parent)
+{
+ ExchangeDelegates *delegates = user_data;
+
+ gtk_widget_destroy (delegates->dialog);
+ delegates_destroy (delegates);
+}
+
+void
+exchange_delegates (ExchangeAccount *account, GtkWidget *parent)
+{
+ GtkWidget *dialog_vbox1;
+ GtkWidget *vbox2;
+ GtkWidget *label3;
+ GtkWidget *delegate_hbox;
+ GtkWidget *delegates_table;
+ GtkWidget *vbuttonbox1;
+ GtkWidget *add_button;
+ GtkWidget *edit_button;
+ GtkWidget *remove_button;
+ ExchangeDelegates *delegates;
+ ExchangeDelegatesUser *user;
+ GtkTreeViewColumn *column;
+ GtkTreeIter iter;
+ gint i;
+
+ g_return_if_fail (GTK_IS_WIDGET (parent));
+ g_return_if_fail (EXCHANGE_IS_ACCOUNT (account));
+
+ delegates = g_new0 (ExchangeDelegates, 1);
+ delegates->account = g_object_ref (account);
+
+ delegates->dialog = gtk_dialog_new_with_buttons (
+ _("Delegates"),
+ NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+
+ dialog_vbox1 = gtk_dialog_get_content_area (GTK_DIALOG (delegates->dialog));
+ gtk_widget_show (dialog_vbox1);
+
+ vbox2 = gtk_vbox_new (FALSE, 6);
+ gtk_widget_show (vbox2);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox1), vbox2, TRUE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox2), 6);
+
+ label3 = gtk_label_new (_("These users will be able to send mail on your behalf\nand access your folders with the permissions you give them."));
+ gtk_widget_show (label3);
+ gtk_box_pack_start (GTK_BOX (vbox2), label3, FALSE, FALSE, 0);
+
+ delegate_hbox = gtk_hbox_new (FALSE, 6);
+ gtk_widget_show (delegate_hbox);
+ gtk_box_pack_start (GTK_BOX (vbox2), delegate_hbox, TRUE, TRUE, 0);
+
+ delegates_table = gtk_tree_view_new ();
+ gtk_widget_show (delegates_table);
+ gtk_box_pack_start (GTK_BOX (delegate_hbox), delegates_table, TRUE, TRUE, 0);
+ gtk_tree_view_set_enable_search (GTK_TREE_VIEW (delegates_table), FALSE);
+
+ vbuttonbox1 = gtk_vbutton_box_new ();
+ gtk_widget_show (vbuttonbox1);
+ gtk_box_pack_end (GTK_BOX (delegate_hbox), vbuttonbox1, FALSE, TRUE, 0);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (vbuttonbox1), GTK_BUTTONBOX_START);
+ gtk_box_set_spacing (GTK_BOX (vbuttonbox1), 6);
+
+ add_button = gtk_button_new_from_stock ("gtk-add");
+ gtk_widget_show (add_button);
+ gtk_container_add (GTK_CONTAINER (vbuttonbox1), add_button);
+ GTK_WIDGET_SET_FLAGS (add_button, GTK_CAN_DEFAULT);
+
+ edit_button = gtk_button_new_with_mnemonic (_("_Edit"));
+ gtk_widget_show (edit_button);
+ gtk_container_add (GTK_CONTAINER (vbuttonbox1), edit_button);
+ GTK_WIDGET_SET_FLAGS (edit_button, GTK_CAN_DEFAULT);
+
+ remove_button = gtk_button_new_from_stock ("gtk-remove");
+ gtk_widget_show (remove_button);
+ gtk_container_add (GTK_CONTAINER (vbuttonbox1), remove_button);
+ GTK_WIDGET_SET_FLAGS (remove_button, GTK_CAN_DEFAULT);
+
+ g_signal_connect (delegates->dialog, "response",
+ G_CALLBACK (dialog_response), delegates);
+
+ if (parent)
+ gtk_window_set_transient_for (GTK_WINDOW (delegates->dialog), GTK_WINDOW (parent));
+ delegates->parent = parent;
+ g_object_weak_ref (G_OBJECT (parent), parent_destroyed, delegates);
+
+ /* Set up the buttons */
+ g_signal_connect (add_button, "clicked",
+ G_CALLBACK (add_button_clicked_cb), delegates);
+ g_signal_connect (edit_button, "clicked",
+ G_CALLBACK (edit_button_clicked_cb), delegates);
+ g_signal_connect (remove_button, "clicked",
+ G_CALLBACK (remove_button_clicked_cb), delegates);
+
+ /* Set up the table */
+ delegates->model = gtk_list_store_new (1, G_TYPE_STRING);
+ delegates->table = delegates_table;
+ column = gtk_tree_view_column_new_with_attributes (
+ _("Name"), gtk_cell_renderer_text_new (), "text", 0, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (delegates->table),
+ column);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (delegates->table),
+ GTK_TREE_MODEL (delegates->model));
+
+ /* Get list of delegate users */
+ if (get_user_list (delegates)) {
+ for (i = 0; i < delegates->users->len; i++) {
+ user = delegates->users->pdata[i];
+
+ gtk_list_store_append (delegates->model, &iter);
+ gtk_list_store_set (delegates->model, &iter,
+ 0, user->display_name,
+ -1);
+ }
+ g_signal_connect (delegates->table,
+ "button_press_event",
+ G_CALLBACK (table_click_cb), delegates);
+ } else {
+ gtk_widget_set_sensitive (add_button, FALSE);
+ gtk_widget_set_sensitive (edit_button, FALSE);
+ gtk_widget_set_sensitive (remove_button, FALSE);
+
+ gtk_list_store_append (delegates->model, &iter);
+ gtk_list_store_set (delegates->model, &iter,
+ 0, _("Error reading delegates list."),
+ -1);
+ }
+
+ gtk_widget_show (delegates->dialog);
+}
diff --git a/eplugin/exchange-delegates.h b/eplugin/exchange-delegates.h
new file mode 100644
index 0000000..ae89047
--- /dev/null
+++ b/eplugin/exchange-delegates.h
@@ -0,0 +1,34 @@
+/*
+ *
+ * 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/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __EXCHANGE_DELEGATES_H__
+#define __EXCHANGE_DELEGATES_H__
+
+#include <exchange-types.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+void exchange_delegates (ExchangeAccount *account, GtkWidget *parent);
+const gchar *email_look_up (const gchar *delegate_legacy, ExchangeAccount *account);
+
+G_END_DECLS
+
+#endif /* __EXCHANGE_DELEGATES_CONTROL_H__ */
diff --git a/eplugin/exchange-folder-permission.c b/eplugin/exchange-folder-permission.c
new file mode 100644
index 0000000..200eea8
--- /dev/null
+++ b/eplugin/exchange-folder-permission.c
@@ -0,0 +1,527 @@
+/*
+ *
+ * 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:
+ * Shakti Sen <shprasad novell com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gconf/gconf-client.h>
+
+#include <libedataserverui/e-source-selector.h>
+#include <libebook/e-book.h>
+#include <camel/camel-url.h>
+
+#include <exchange-account.h>
+
+#include <e-util/e-dialog-utils.h>
+#include <calendar/gui/e-cal-model.h>
+
+#include <shell/e-shell-view.h>
+#include <shell/e-shell-window.h>
+
+#include <mail/em-folder-tree.h>
+#include <mail/em-folder-tree-model.h>
+
+#include "exchange-config-listener.h"
+#include "exchange-folder-subscription.h"
+#include "exchange-operations.h"
+#include "exchange-permissions-dialog.h"
+
+#define d(x)
+
+gboolean eex_ui_mail_init (GtkUIManager *ui_manager, EShellView *shell_view);
+gboolean eex_ui_calendar_permissions (GtkUIManager *ui_manager, EShellView *shell_view);
+gboolean eex_ui_tasks_permissions (GtkUIManager *ui_manager, EShellView *shell_view);
+gboolean eex_ui_addressbook_permissions (GtkUIManager *ui_manager, EShellView *shell_view);
+
+static gboolean
+is_subscribed_folder (const gchar *uri)
+{
+ const gchar *path;
+ ExchangeAccount *account;
+ gint offset;
+
+ g_return_val_if_fail (uri != NULL, FALSE);
+
+ account = exchange_operations_get_exchange_account ();
+ g_return_val_if_fail (account != NULL, FALSE);
+ g_return_val_if_fail (account->account_filename != NULL, FALSE);
+
+ offset = strlen ("exchange://") + strlen (account->account_filename) + strlen ("/;");
+ g_return_val_if_fail (strlen (uri) >= offset, FALSE);
+
+ path = uri + offset;
+
+ return strchr (path, '@') != NULL;
+}
+
+static void
+call_folder_permissions (const gchar *uri)
+{
+ ExchangeAccount *account = NULL;
+ EFolder *folder = NULL;
+
+ g_return_if_fail (uri != NULL);
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account)
+ return;
+
+ folder = exchange_account_get_folder (account, uri);
+ if (folder)
+ exchange_permissions_dialog_new (account, folder, NULL);
+}
+
+static gboolean
+is_eex_folder_selected (EShellView *shell_view, gchar **puri)
+{
+ ExchangeAccount *account = NULL;
+ gint mode;
+ EShellSidebar *shell_sidebar;
+ EMFolderTree *folder_tree = NULL;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model = NULL;
+ GtkTreeIter iter;
+ gboolean is_store = FALSE, res;
+ gchar *uri = NULL;
+
+ g_return_val_if_fail (shell_view != NULL, FALSE);
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account)
+ return FALSE;
+
+ exchange_account_is_offline (account, &mode);
+ if (mode == OFFLINE_MODE)
+ return FALSE;
+
+ shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
+ g_object_get (shell_sidebar, "folder-tree", &folder_tree, NULL);
+ g_return_val_if_fail (folder_tree != NULL, FALSE);
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_tree));
+ g_return_val_if_fail (selection != NULL, FALSE);
+
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ return FALSE;
+
+ gtk_tree_model_get (model, &iter,
+ COL_STRING_URI, &uri,
+ COL_BOOL_IS_STORE, &is_store,
+ -1);
+
+ res = !is_store && uri && g_ascii_strncasecmp (uri, "exchange://", 11) == 0;
+
+ if (res) {
+ const gchar *path;
+
+ path = uri + strlen ("exchange://") + strlen (account->account_filename);
+ res = path && *path;
+
+ if (res) {
+ if (puri)
+ *puri = g_strdup (uri);
+ }
+ }
+
+ g_free (uri);
+
+ return res;
+}
+
+static void
+eex_mail_folder_permissions_cb (GtkAction *action, EShellView *shell_view)
+{
+ gchar *uri = NULL;
+
+ if (is_eex_folder_selected (shell_view, &uri))
+ call_folder_permissions (uri);
+
+ g_free (uri);
+}
+
+static void
+eex_folder_subscribe_cb (GtkAction *action, EShellView *shell_view)
+{
+ const gchar *name;
+
+ name = gtk_action_get_name (action);
+ g_return_if_fail (name != NULL);
+
+ name = strrchr (name, '-');
+ g_return_if_fail (name != NULL && *name == '-');
+
+ call_folder_subscribe (name + 1);
+}
+
+static void
+eex_mail_folder_inbox_unsubscribe_cb (GtkAction *action, EShellView *shell_view)
+{
+ gchar *uri = NULL;
+
+ if (is_eex_folder_selected (shell_view, &uri))
+ call_folder_unsubscribe ("Inbox", uri, NULL);
+
+ g_free (uri);
+}
+
+/* Beware, depends on the order */
+static GtkActionEntry mail_entries[] = {
+ { "eex-mail-folder-permissions",
+ "folder-new",
+ N_("Permissions..."),
+ NULL,
+ N_("Check folder permissions"),
+ G_CALLBACK (eex_mail_folder_permissions_cb) },
+
+ { "eex-folder-subscribe-Inbox",
+ NULL,
+ N_("Subscribe to Other User's Folder..."),
+ NULL,
+ N_("Subscribe to Other User's Folder"),
+ G_CALLBACK (eex_folder_subscribe_cb) },
+
+ { "eex-mail-folder-inbox-unsubscribe",
+ "folder-new",
+ N_("Unsubscribe Folder..."),
+ NULL,
+ NULL,
+ G_CALLBACK (eex_mail_folder_inbox_unsubscribe_cb) }
+};
+
+static void
+update_mail_entries_cb (EShellView *shell_view, gpointer user_data)
+{
+ GtkActionGroup *action_group;
+ EShellWindow *shell_window;
+ GtkAction *action;
+ gboolean is_eex;
+ gchar *uri = NULL;
+ gint i;
+
+ g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
+
+ is_eex = is_eex_folder_selected (shell_view, &uri);
+ shell_window = e_shell_view_get_shell_window (shell_view);
+ action_group = e_shell_window_get_action_group (shell_window, "mail");
+
+ for (i = 0; i < G_N_ELEMENTS (mail_entries); i++) {
+ gboolean visible = is_eex;
+
+ action = gtk_action_group_get_action (action_group, mail_entries[i].name);
+ g_return_if_fail (action != NULL);
+
+ if (visible && i == 2) {
+ /* it's an unsubscribe, check if this is public and show/hide based on that */
+ visible = uri && is_subscribed_folder (uri);
+ }
+
+ gtk_action_set_visible (action, visible);
+ }
+
+ g_free (uri);
+}
+
+gboolean
+eex_ui_mail_init (GtkUIManager *ui_manager, EShellView *shell_view)
+{
+ EShellWindow *shell_window;
+
+ shell_window = e_shell_view_get_shell_window (shell_view);
+
+ gtk_action_group_add_actions (
+ e_shell_window_get_action_group (shell_window, "mail"),
+ mail_entries, G_N_ELEMENTS (mail_entries), shell_view);
+
+ g_signal_connect (shell_view, "update-actions", G_CALLBACK (update_mail_entries_cb), NULL);
+
+ return TRUE;
+}
+
+static gboolean
+is_eex_source_selected (EShellView *shell_view, gchar **puri)
+{
+ gint mode;
+ ExchangeAccount *account = NULL;
+ ESource *source = NULL;
+ gchar *uri = NULL;
+ EShellSidebar *shell_sidebar;
+ ESourceSelector *selector = NULL;
+
+ shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
+ g_return_val_if_fail (shell_sidebar != NULL, FALSE);
+
+ g_object_get (shell_sidebar, "selector", &selector, NULL);
+ g_return_val_if_fail (selector != NULL, FALSE);
+
+ source = e_source_selector_peek_primary_selection (selector);
+ uri = e_source_get_uri (source);
+
+ g_object_unref (selector);
+
+ if (uri && !g_strrstr (uri, "exchange://")) {
+ g_free (uri);
+ return FALSE;
+ }
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account) {
+ g_free (uri);
+ return FALSE;
+ }
+
+ exchange_account_is_offline (account, &mode);
+ if (mode == OFFLINE_MODE) {
+ g_free (uri);
+ return FALSE;
+ }
+
+ if (!exchange_account_get_folder (account, uri)) {
+ g_free (uri);
+ return FALSE;
+ }
+
+ if (puri)
+ *puri = uri;
+ else
+ g_free (uri);
+
+ return TRUE;
+}
+
+#define NUM_ENTRIES 3
+
+static void
+update_source_entries_cb (EShellView *shell_view, GtkActionEntry *entries)
+{
+ GtkActionGroup *action_group;
+ EShellWindow *shell_window;
+ GtkAction *action;
+ const gchar *group;
+ gchar *uri = NULL;
+ gboolean is_eex;
+ gint i;
+
+ g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
+ g_return_if_fail (entries != NULL);
+
+ if (strstr (entries->name, "calendar"))
+ group = "calendar";
+ else if (strstr (entries->name, "tasks"))
+ group = "tasks";
+ else
+ group = "addressbook";
+
+ is_eex = is_eex_source_selected (shell_view, &uri);
+ shell_window = e_shell_view_get_shell_window (shell_view);
+ action_group = e_shell_window_get_action_group (shell_window, group);
+
+ for (i = 0; i < NUM_ENTRIES; i++) {
+ gboolean visible = is_eex;
+
+ action = gtk_action_group_get_action (action_group, entries->name);
+ g_return_if_fail (action != NULL);
+
+ if (visible && i == 2) {
+ /* it's an unsubscribe, check if this is public and show/hide based on that */
+ visible = uri && is_subscribed_folder (uri);
+ }
+
+ gtk_action_set_visible (action, visible);
+
+ }
+
+ g_free (uri);
+}
+
+static void
+setup_source_actions (EShellView *shell_view, GtkActionEntry *entries)
+{
+ EShellWindow *shell_window;
+ const gchar *group;
+
+ g_return_if_fail (shell_view != NULL);
+ g_return_if_fail (entries != NULL);
+
+ if (strstr (entries->name, "calendar"))
+ group = "calendar";
+ else if (strstr (entries->name, "tasks"))
+ group = "tasks";
+ else
+ group = "addressbook";
+
+ shell_window = e_shell_view_get_shell_window (shell_view);
+
+ gtk_action_group_add_actions (
+ e_shell_window_get_action_group (shell_window, group),
+ entries, NUM_ENTRIES, shell_view);
+
+ g_signal_connect (shell_view, "update-actions", G_CALLBACK (update_source_entries_cb), entries);
+}
+
+static void
+source_permissions_cb (GtkAction *action, EShellView *shell_view)
+{
+ gchar *uri = NULL;
+
+ g_return_if_fail (shell_view != NULL);
+
+ if (is_eex_source_selected (shell_view, &uri))
+ call_folder_permissions (uri);
+
+ g_free (uri);
+}
+
+static void
+eex_folder_unsubscribe_cb (GtkAction *action, EShellView *shell_view)
+{
+ gchar *uri = NULL;
+ const gchar *name;
+
+ g_return_if_fail (shell_view != NULL);
+
+ name = gtk_action_get_name (action);
+ g_return_if_fail (name != NULL);
+
+ name = strrchr (name, '-');
+ g_return_if_fail (name != NULL && *name == '-');
+
+ if (is_eex_source_selected (shell_view, &uri)) {
+ EShellSidebar *shell_sidebar;
+ ESourceSelector *selector = NULL;
+
+ shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
+ g_return_if_fail (shell_sidebar != NULL);
+
+ g_object_get (shell_sidebar, "selector", &selector, NULL);
+ g_return_if_fail (selector != NULL);
+
+ call_folder_unsubscribe (name + 1, uri, e_source_selector_peek_primary_selection (selector));
+ }
+
+ g_free (uri);
+}
+
+/* Beware, depends on count and order */
+static GtkActionEntry calendar_entries[] = {
+ { "eex-calendar-permissions",
+ "folder-new",
+ N_("Permissions..."),
+ NULL,
+ N_("Check calendar permissions"),
+ G_CALLBACK (source_permissions_cb) },
+
+ { "eex-folder-subscribe-Calendar",
+ NULL,
+ N_("Subscribe to Other User's Folder..."),
+ NULL,
+ N_("Subscribe to Other User's Folder"),
+ G_CALLBACK (eex_folder_subscribe_cb) },
+
+ { "eex-folder-unsubscribe-Calendar",
+ "folder-new",
+ N_("Unsubscribe Folder..."),
+ NULL,
+ NULL,
+ G_CALLBACK (eex_folder_unsubscribe_cb) }
+};
+
+gboolean
+eex_ui_calendar_permissions (GtkUIManager *ui_manager, EShellView *shell_view)
+{
+ g_return_val_if_fail (G_N_ELEMENTS (calendar_entries) != NUM_ENTRIES, FALSE);
+
+ setup_source_actions (shell_view, calendar_entries);
+
+ return TRUE;
+}
+
+/* Beware, depends on count and order */
+static GtkActionEntry tasks_entries[] = {
+ { "eex-tasks-permissions",
+ "folder-new",
+ N_("Permissions..."),
+ NULL,
+ N_("Check tasks permissions"),
+ G_CALLBACK (source_permissions_cb) },
+
+ { "eex-folder-subscribe-Tasks",
+ NULL,
+ N_("Subscribe to Other User's Folder..."),
+ NULL,
+ N_("Subscribe to Other User's Folder"),
+ G_CALLBACK (eex_folder_subscribe_cb) },
+
+ { "eex-folder-unsubscribe-Tasks",
+ "folder-new",
+ N_("Unsubscribe Folder..."),
+ NULL,
+ NULL,
+ G_CALLBACK (eex_folder_unsubscribe_cb) }
+};
+
+gboolean
+eex_ui_tasks_permissions (GtkUIManager *ui_manager, EShellView *shell_view)
+{
+ g_return_val_if_fail (G_N_ELEMENTS (tasks_entries) != NUM_ENTRIES, FALSE);
+
+ setup_source_actions (shell_view, tasks_entries);
+
+ return TRUE;
+}
+
+/* Beware, depends on count and order */
+static GtkActionEntry addressbook_entries[] = {
+ { "eex-addressbook-permissions",
+ "folder-new",
+ N_("Permissions..."),
+ NULL,
+ N_("Check addressbook permissions"),
+ G_CALLBACK (source_permissions_cb) },
+
+ { "eex-folder-subscribe-Contacts",
+ NULL,
+ N_("Subscribe to Other User's Folder..."),
+ NULL,
+ N_("Subscribe to Other User's Folder"),
+ G_CALLBACK (eex_folder_subscribe_cb) },
+
+ { "eex-folder-unsubscribe-Contacts",
+ "folder-new",
+ N_("Unsubscribe Folder..."),
+ NULL,
+ NULL,
+ G_CALLBACK (eex_folder_unsubscribe_cb) }
+};
+
+gboolean
+eex_ui_addressbook_permissions (GtkUIManager *ui_manager, EShellView *shell_view)
+{
+ g_return_val_if_fail (G_N_ELEMENTS (addressbook_entries) != NUM_ENTRIES, FALSE);
+
+ setup_source_actions (shell_view, addressbook_entries);
+
+ return TRUE;
+}
diff --git a/eplugin/exchange-folder-size-display.c b/eplugin/exchange-folder-size-display.c
new file mode 100644
index 0000000..325483f
--- /dev/null
+++ b/eplugin/exchange-folder-size-display.c
@@ -0,0 +1,170 @@
+/*
+ * 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:
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+/* ExchangeFolderSize: Display the folder tree with the folder sizes */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <e-util/e-dialog-utils.h>
+#include "exchange-folder-size-display.h"
+
+enum {
+ COLUMN_NAME,
+ COLUMN_SIZE,
+ NUM_COLUMNS
+};
+
+static gboolean
+get_folder_size_func (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ GHashTable *info = (GHashTable *) user_data;
+ gdouble folder_size;
+ gchar *folder_name;
+
+ gtk_tree_model_get(model, iter, COLUMN_SIZE, &folder_size, COLUMN_NAME, &folder_name, -1);
+
+ g_hash_table_insert (info, g_strdup (folder_name), g_strdup_printf ("%.2f", folder_size));
+ return FALSE;
+}
+
+gchar *
+exchange_folder_size_get_val (GtkListStore *model, const gchar *folder_name)
+{
+ GHashTable *finfo;
+ gchar *folder_size, *fsize;
+
+ finfo = g_hash_table_new_full (
+ g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
+
+ gtk_tree_model_foreach (GTK_TREE_MODEL (model), get_folder_size_func, finfo);
+
+ if ((fsize = g_hash_table_lookup (finfo, folder_name)) != NULL)
+ folder_size = g_strdup (fsize);
+ else
+ folder_size = g_strdup ("0");
+
+ g_hash_table_destroy (finfo);
+
+ return folder_size;
+}
+
+static void
+format_size_func (GtkTreeViewColumn *col,
+ GtkCellRenderer *renderer,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ GtkCellRendererText *cell = (GtkCellRendererText *)renderer;
+ gdouble folder_size;
+ gchar * new_text;
+
+ gtk_tree_model_get(model, iter, COLUMN_SIZE, &folder_size, -1);
+
+ if (folder_size)
+ new_text = g_strdup_printf ("%.2f", folder_size);
+ else
+ new_text = g_strdup ("0");
+
+ g_object_set (cell, "text", new_text, NULL);
+ g_free (new_text);
+}
+
+void
+exchange_folder_size_display (GtkListStore *model, GtkWidget *parent)
+{
+ GtkTreeViewColumn *column;
+ GtkTreeSortable *sortable;
+ GtkCellRenderer *cell;
+ GtkWidget *folder_tree;
+ GtkWidget *dialog_vbox1;
+ GtkWidget *folder_tree_hbox;
+ GtkWidget *scrolledwindow1;
+ GtkWidget *folder_treeview;
+ GList *l;
+ gchar *col_name;
+
+ g_return_if_fail (GTK_IS_WIDGET (parent));
+
+ folder_tree = gtk_dialog_new_with_buttons (
+ _("Exchange Folder Tree"),
+ NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+ gtk_window_set_position (GTK_WINDOW (folder_tree), GTK_WIN_POS_CENTER_ON_PARENT);
+ gtk_window_set_default_size (GTK_WINDOW (folder_tree), 250, 300);
+ if (parent)
+ gtk_window_set_transient_for (GTK_WINDOW (folder_tree), GTK_WINDOW (parent));
+
+ dialog_vbox1 = gtk_dialog_get_content_area (GTK_DIALOG (folder_tree));
+ gtk_widget_show (dialog_vbox1);
+
+ folder_tree_hbox = gtk_hbox_new (FALSE, 0);
+ gtk_widget_show (folder_tree_hbox);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox1), folder_tree_hbox, TRUE, TRUE, 0);
+
+ scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_show (scrolledwindow1);
+ gtk_box_pack_start (GTK_BOX (folder_tree_hbox), scrolledwindow1, TRUE, TRUE, 0);
+
+ folder_treeview = gtk_tree_view_new ();
+ gtk_widget_show (folder_treeview);
+ gtk_container_add (GTK_CONTAINER (scrolledwindow1), folder_treeview);
+
+ /* fsize->parent = parent; */
+
+ /* Set up the table */
+ sortable = GTK_TREE_SORTABLE (model);
+ gtk_tree_sortable_set_sort_column_id (sortable, COLUMN_SIZE, GTK_SORT_DESCENDING);
+
+ column = gtk_tree_view_column_new_with_attributes (
+ _("Folder Name"), gtk_cell_renderer_text_new (), "text", COLUMN_NAME, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (folder_treeview),
+ column);
+
+ col_name = g_strdup_printf ("%s (KB)", _("Folder Size"));
+ column = gtk_tree_view_column_new_with_attributes (
+ col_name, gtk_cell_renderer_text_new (), "text", COLUMN_SIZE, NULL);
+ g_free (col_name);
+
+ l = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+ cell = (GtkCellRenderer *)l->data;
+ gtk_tree_view_column_set_cell_data_func (column, cell, format_size_func, NULL, NULL );
+ g_list_free (l);
+
+ gtk_tree_view_append_column (GTK_TREE_VIEW (folder_treeview),
+ column);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (folder_treeview),
+ GTK_TREE_MODEL (model));
+ gtk_dialog_run (GTK_DIALOG (folder_tree));
+ gtk_widget_destroy (folder_tree);
+}
diff --git a/eplugin/exchange-folder-size-display.h b/eplugin/exchange-folder-size-display.h
new file mode 100644
index 0000000..13d112c
--- /dev/null
+++ b/eplugin/exchange-folder-size-display.h
@@ -0,0 +1,33 @@
+/*
+ *
+ * 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/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __EXCHANGE_FOLDER_SIZE_DISPLAY_H__
+#define __EXCHANGE_FOLDER_SIZE_DISPLAY_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+void exchange_folder_size_display (GtkListStore *model, GtkWidget *parent);
+gchar * exchange_folder_size_get_val (GtkListStore *model, const gchar *folder_name);
+
+G_END_DECLS
+
+#endif /* __EXCHANGE_FOLDER_SIZE_DISPLAY_H__ */
diff --git a/eplugin/exchange-folder-subscription.c b/eplugin/exchange-folder-subscription.c
new file mode 100644
index 0000000..63d2fb2
--- /dev/null
+++ b/eplugin/exchange-folder-subscription.c
@@ -0,0 +1,380 @@
+/*
+ *
+ * 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:
+ * Shakti Sen <shprasad novell com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gtk/gtk.h>
+#include <e-util/e-error.h>
+#include <e-folder.h>
+#include <exchange-account.h>
+#include <exchange-hierarchy.h>
+#include "exchange-hierarchy-foreign.h"
+#include <e2k-types.h>
+#include <exchange-types.h>
+#include <e2k-propnames.h>
+#include <libedataserverui/e-name-selector.h>
+#include "exchange-config-listener.h"
+#include "exchange-folder-subscription.h"
+#include "exchange-operations.h"
+
+static void
+user_response (ENameSelectorDialog *name_selector_dialog, gint response, gpointer data)
+{
+ gtk_widget_hide (GTK_WIDGET (name_selector_dialog));
+}
+
+static void
+user_clicked (GtkWidget *button, ENameSelector *name_selector)
+{
+ ENameSelectorDialog *name_selector_dialog;
+
+ name_selector_dialog = e_name_selector_peek_dialog (name_selector);
+ gtk_window_set_modal (GTK_WINDOW (name_selector_dialog), TRUE);
+ gtk_widget_show (GTK_WIDGET (name_selector_dialog));
+}
+
+static GtkWidget *
+setup_name_selector (GtkWidget *placeholder, GtkWidget *button_user, ENameSelector **name_selector_ret)
+{
+ ENameSelector *name_selector;
+ ENameSelectorModel *name_selector_model;
+ ENameSelectorDialog *name_selector_dialog;
+ GtkWidget *widget;
+
+ g_assert (GTK_IS_CONTAINER (placeholder));
+
+ name_selector = e_name_selector_new ();
+
+ name_selector_model = e_name_selector_peek_model (name_selector);
+ /* FIXME Limit to one user */
+ e_name_selector_model_add_section (name_selector_model, "User", _("User"), NULL);
+
+ /* Listen for responses whenever the dialog is shown */
+ name_selector_dialog = e_name_selector_peek_dialog (name_selector);
+ g_signal_connect (name_selector_dialog, "response",
+ G_CALLBACK (user_response), name_selector);
+
+ widget = GTK_WIDGET (e_name_selector_peek_section_entry (name_selector, "User"));
+ gtk_widget_show (widget);
+
+ g_signal_connect (button_user, "clicked", G_CALLBACK (user_clicked), name_selector);
+ gtk_box_pack_start (GTK_BOX (placeholder), widget, TRUE, TRUE, 6);
+ *name_selector_ret = name_selector;
+
+ return widget;
+}
+
+static void
+setup_folder_name_combo (GtkWidget *widget, const gchar *fname)
+{
+ GtkComboBox *combo;
+ const gchar *strings[] = {
+ "Calendar",
+ "Inbox",
+ "Contacts",
+ "Tasks",
+ NULL
+ /* FIXME: Should these be translated? */
+ };
+ gint i;
+
+ combo = GTK_COMBO_BOX (widget);
+ g_assert (GTK_IS_COMBO_BOX_ENTRY (combo));
+
+ gtk_list_store_clear (GTK_LIST_STORE (gtk_combo_box_get_model (combo)));
+
+ for (i = 0; strings[i] != NULL; i ++)
+ gtk_combo_box_append_text (combo, strings[i]);
+
+ gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (combo))), fname);
+}
+
+static void
+folder_name_entry_changed_callback (GtkEditable *editable,
+ gpointer data)
+{
+ GtkDialog *dialog = GTK_DIALOG (data);
+ const gchar *folder_name_text = gtk_entry_get_text (GTK_ENTRY (editable));
+
+ if (*folder_name_text == '\0')
+ gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_OK, FALSE);
+ else
+ gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_OK, TRUE);
+}
+
+static void
+user_name_entry_changed_callback (GtkEditable *editable, gpointer data)
+{
+ GtkDialog *dialog = GTK_DIALOG (data);
+ const gchar *user_name_text = gtk_entry_get_text (GTK_ENTRY (editable));
+
+ if (*user_name_text == '\0')
+ gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_OK, FALSE);
+ else
+ gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_OK, TRUE);
+}
+
+static void
+setup_server_combobox (GtkWidget *widget, gchar *mail_account)
+{
+ g_return_if_fail (GTK_IS_COMBO_BOX (widget));
+
+ gtk_list_store_clear (GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (widget))));
+
+ gtk_combo_box_append_text (GTK_COMBO_BOX (widget), mail_account);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
+
+ /* FIXME: Default to the current storage in the shell view. */
+}
+
+typedef struct {
+ ExchangeAccount *account;
+ ENameSelector *name_selector;
+ GtkWidget *name_selector_widget;
+ GtkWidget *folder_name_entry;
+}SubscriptionInfo;
+
+static void
+destroy_subscription_info (SubscriptionInfo *subscription_info)
+{
+ if (subscription_info->name_selector) {
+ g_object_unref (subscription_info->name_selector);
+ subscription_info->name_selector = NULL;
+ }
+ g_free (subscription_info);
+}
+
+static void
+subscribe_to_folder (GtkWidget *dialog, gint response, gpointer data)
+{
+ SubscriptionInfo *subscription_info = data;
+ gchar *user_email_address = NULL, *folder_name = NULL, *path = NULL;
+ gchar *subscriber_email;
+ EFolder *folder = NULL;
+ EDestinationStore *destination_store;
+ GList *destinations;
+ EDestination *destination;
+ ExchangeAccountFolderResult result;
+
+ if (response == GTK_RESPONSE_CANCEL) {
+ gtk_widget_destroy (dialog);
+ destroy_subscription_info (subscription_info);
+ }
+ else if (response == GTK_RESPONSE_OK) {
+ while (TRUE) {
+ destination_store = e_name_selector_entry_peek_destination_store (
+ E_NAME_SELECTOR_ENTRY (GTK_ENTRY (subscription_info->name_selector_widget)));
+ destinations = e_destination_store_list_destinations (destination_store);
+ if (!destinations)
+ break;
+ destination = destinations->data;
+ user_email_address = g_strdup (e_destination_get_email (destination));
+ g_list_free (destinations);
+
+ if (user_email_address != NULL && *user_email_address != '\0')
+ break;
+
+ /* check if user is trying to subscribe to his own folder */
+ subscriber_email = exchange_account_get_email_id (subscription_info->account);
+ if (subscriber_email != NULL && *subscriber_email != '\0') {
+ if (g_str_equal (subscriber_email, user_email_address)) {
+ e_error_run (NULL, ERROR_DOMAIN ":folder-exists-error", NULL);
+ g_free (user_email_address);
+ gtk_widget_destroy (dialog);
+ destroy_subscription_info (subscription_info);
+ return;
+ }
+ }
+
+ /* It would be nice to insensitivize the OK button appropriately
+ instead of doing this, but unfortunately we can't do this for the
+ Bonobo control. */
+ e_error_run (GTK_WINDOW (dialog), ERROR_DOMAIN ":select-user", NULL);
+ }
+
+ folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (subscription_info->folder_name_entry)));
+ if (user_email_address && folder_name) {
+ result = exchange_account_discover_shared_folder (subscription_info->account,
+ user_email_address,
+ folder_name, &folder);
+ g_free (folder_name);
+ gtk_widget_hide (dialog);
+ switch (result) {
+ case EXCHANGE_ACCOUNT_FOLDER_OK:
+ exchange_account_rescan_tree (subscription_info->account);
+ if (!g_ascii_strcasecmp (e_folder_get_type_string (folder), "mail"))
+ e_error_run (NULL, ERROR_DOMAIN ":folder-restart-evo", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_ALREADY_EXISTS:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-exists-error", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-doesnt-exist-error", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_UNKNOWN_TYPE:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-unknown-type", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-perm-error", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_OFFLINE:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-offline-error", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_UNSUPPORTED_OPERATION:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-unsupported-error", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_GC_NOTREACHABLE:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-no-gc-error", NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_NO_SUCH_USER:
+ e_error_run (NULL, ERROR_DOMAIN ":no-user-error", user_email_address, NULL);
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-generic-error", NULL);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!folder) {
+ g_free (user_email_address);
+ gtk_widget_destroy (dialog);
+ return;
+ }
+
+ g_object_unref (folder);
+ path = g_strdup_printf ("/%s", user_email_address);
+ exchange_account_open_folder (subscription_info->account, path);
+ g_free (path);
+ g_free (user_email_address);
+ gtk_widget_destroy (dialog);
+ destroy_subscription_info (subscription_info);
+ }
+}
+
+gboolean
+create_folder_subscription_dialog (ExchangeAccount *account, const gchar *fname)
+{
+ ENameSelector *name_selector;
+ GtkWidget *dialog;
+ GtkWidget *dialog_vbox1;
+ GtkWidget *table1;
+ GtkWidget *label1;
+ GtkWidget *label3;
+ GtkWidget *user_picker_placeholder;
+ GtkWidget *button_user;
+ GtkWidget *folder_name_combo;
+ GtkWidget *server_combobox;
+ SubscriptionInfo *subscription_info;
+ gint mode;
+
+ exchange_account_is_offline (account, &mode);
+ if (mode == OFFLINE_MODE)
+ return FALSE;
+
+ subscription_info = g_new0 (SubscriptionInfo, 1);
+ subscription_info->account = account;
+
+ dialog = gtk_dialog_new_with_buttons (
+ _("Subscribe to Other User's Folder"),
+ NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+
+ dialog_vbox1 = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+ gtk_widget_show (dialog_vbox1);
+
+ table1 = gtk_table_new (3, 2, FALSE);
+ gtk_widget_show (table1);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox1), table1, TRUE, TRUE, 2);
+ gtk_table_set_row_spacings (GTK_TABLE (table1), 3);
+ gtk_table_set_col_spacings (GTK_TABLE (table1), 3);
+
+ label1 = gtk_label_new_with_mnemonic (_("_Account:"));
+ gtk_widget_show (label1);
+ gtk_table_attach (GTK_TABLE (table1), label1, 0, 1, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_label_set_justify (GTK_LABEL (label1), GTK_JUSTIFY_CENTER);
+
+ label3 = gtk_label_new_with_mnemonic (_("_Folder Name:"));
+ gtk_widget_show (label3);
+ gtk_table_attach (GTK_TABLE (table1), label3, 0, 1, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_label_set_justify (GTK_LABEL (label3), GTK_JUSTIFY_CENTER);
+
+ user_picker_placeholder = gtk_hbox_new (FALSE, 0);
+ gtk_widget_show (user_picker_placeholder);
+ gtk_table_attach (GTK_TABLE (table1), user_picker_placeholder, 1, 2, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ button_user = gtk_button_new_with_mnemonic (_("_User:"));
+ gtk_widget_show (button_user);
+ gtk_table_attach (GTK_TABLE (table1), button_user, 0, 1, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+
+ folder_name_combo = gtk_combo_box_entry_new_text ();
+ gtk_widget_show (folder_name_combo);
+ gtk_table_attach (GTK_TABLE (table1), folder_name_combo, 1, 2, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+
+ server_combobox = gtk_combo_box_new_text ();
+ gtk_widget_show (server_combobox);
+ gtk_table_attach (GTK_TABLE (table1), server_combobox, 1, 2, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+
+ gtk_window_set_modal (GTK_WINDOW (dialog), FALSE);
+
+ subscription_info->name_selector_widget = setup_name_selector (user_picker_placeholder, button_user, &name_selector);
+ subscription_info->name_selector = name_selector;
+ gtk_widget_grab_focus (subscription_info->name_selector_widget);
+
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, FALSE);
+ g_signal_connect (subscription_info->name_selector_widget, "changed",
+ G_CALLBACK (user_name_entry_changed_callback), dialog);
+
+ setup_server_combobox (server_combobox, account->account_name);
+ setup_folder_name_combo (folder_name_combo, fname);
+ subscription_info->folder_name_entry = gtk_bin_get_child (GTK_BIN (folder_name_combo));
+ g_signal_connect (dialog, "response", G_CALLBACK (subscribe_to_folder), subscription_info);
+ gtk_widget_show (dialog);
+
+ /* Connect the callback to set the OK button insensitive when there is
+ no text in the folder_name_entry. Notice that we put a value there
+ by default so the OK button is sensitive by default. */
+ g_signal_connect (subscription_info->folder_name_entry, "changed",
+ G_CALLBACK (folder_name_entry_changed_callback), dialog);
+
+ return TRUE;
+}
+
diff --git a/eplugin/exchange-folder-subscription.h b/eplugin/exchange-folder-subscription.h
new file mode 100644
index 0000000..942cc3a
--- /dev/null
+++ b/eplugin/exchange-folder-subscription.h
@@ -0,0 +1,34 @@
+/*
+ *
+ * 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/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __EXCHANGE_FOLDER_SUBSCRIPTION_H__
+#define __EXCHANGE_FOLDER_SUBSCRIPTION_H__
+
+#include <glib.h>
+#include <libedataserver/e-source.h>
+#include <exchange-account.h>
+
+gboolean
+create_folder_subscription_dialog (ExchangeAccount *account, const gchar *fname);
+
+void call_folder_subscribe (const gchar *folder_name);
+void call_folder_unsubscribe (const gchar *folder_type, const gchar *uri, ESource *source);
+
+#endif
diff --git a/eplugin/exchange-folder.c b/eplugin/exchange-folder.c
new file mode 100644
index 0000000..5fe4345
--- /dev/null
+++ b/eplugin/exchange-folder.c
@@ -0,0 +1,420 @@
+/*
+ * 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:
+ * Shakti Sen <shprasad novell com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gconf/gconf-client.h>
+#include <e-folder-exchange.h>
+#include <exchange-hierarchy.h>
+#include <libedataserverui/e-source-selector.h>
+#include <e-util/e-error.h>
+#include <camel/camel-store.h>
+#include <camel/camel-folder.h>
+#include <mail/mail-mt.h>
+#include <mail/mail-ops.h>
+
+#include "exchange-operations.h"
+#include "exchange-folder-subscription.h"
+
+#define CONF_KEY_SELECTED_CAL_SOURCES "/apps/evolution/calendar/display/selected_calendars"
+
+static CamelFolderInfo *
+ex_create_folder_info (CamelStore *store, gchar *name, gchar *uri,
+ gint unread_count, gint flags)
+{
+ CamelFolderInfo *info;
+ const gchar *path;
+
+ path = strstr (uri, "://");
+ if (!path)
+ return NULL;
+ path = strchr (path + 3, '/');
+ if (!path)
+ return NULL;
+
+ info = camel_folder_info_new ();
+ info->name = name;
+ info->uri = uri;
+ info->full_name = g_strdup (path + 1);
+ info->unread = unread_count;
+
+ return info;
+}
+
+static void
+exchange_get_folder (gchar *uri, CamelFolder *folder, gpointer data)
+{
+ CamelStore *store;
+ CamelException ex;
+ CamelFolderInfo *info;
+ gchar *name = NULL;
+ gchar *stored_name = NULL;
+ gchar *target_uri = (gchar *)data;
+ ExchangeAccount *account = NULL;
+
+ account = exchange_operations_get_exchange_account ();
+
+ if (!account)
+ return;
+
+ /* Get the subscribed folder name. */
+ name = target_uri + strlen ("exchange://") + strlen (account->account_filename);
+ stored_name = strrchr (name + 1, '/');
+
+ if (stored_name)
+ name[stored_name - name] = '\0';
+
+ camel_exception_init (&ex);
+ store = camel_folder_get_parent_store (folder);
+
+ /* Construct the CamelFolderInfo */
+ info = ex_create_folder_info (store, name, target_uri, -1, 0);
+ camel_object_trigger_event (CAMEL_OBJECT (store),
+ "folder_unsubscribed", info);
+ g_free (target_uri);
+}
+
+static void
+eex_folder_inbox_unsubscribe (const gchar *uri)
+{
+ ExchangeAccount *account = NULL;
+ gchar *path = NULL;
+ gchar *stored_path = NULL;
+ const gchar *inbox_uri = NULL;
+ const gchar *inbox_physical_uri = NULL;
+ gchar *target_uri = NULL;
+ EFolder *inbox;
+ ExchangeAccountFolderResult result;
+
+ account = exchange_operations_get_exchange_account ();
+
+ if (!account)
+ return;
+
+ target_uri = g_strdup (uri);
+ path = g_strdup (uri + strlen ("exchange://") + strlen (account->account_filename));
+ /* User will be able to unsubscribe by doing a right click on
+ any one of this two-<other user's>Inbox or the
+ <other user's folder> tree.
+ */
+ stored_path = strrchr (path + 1, '/');
+
+ if (stored_path)
+ path[stored_path - path] = '\0';
+
+ result = exchange_account_remove_shared_folder (account, path);
+ g_free (path);
+
+ switch (result) {
+ case EXCHANGE_ACCOUNT_FOLDER_OK:
+ break;
+ case EXCHANGE_ACCOUNT_FOLDER_ALREADY_EXISTS:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-exists-error", NULL);
+ return;
+ case EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-doesnt-exist-error", NULL);
+ return;
+ case EXCHANGE_ACCOUNT_FOLDER_UNKNOWN_TYPE:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-unknown-type", NULL);
+ return;
+ case EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-perm-error", NULL);
+ return;
+ case EXCHANGE_ACCOUNT_FOLDER_OFFLINE:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-offline-error", NULL);
+ return;
+ case EXCHANGE_ACCOUNT_FOLDER_UNSUPPORTED_OPERATION:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-unsupported-error", NULL);
+ return;
+ case EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-generic-error", NULL);
+ return;
+ case EXCHANGE_ACCOUNT_FOLDER_GC_NOTREACHABLE:
+ e_error_run (NULL, ERROR_DOMAIN ":folder-no-gc-error", NULL);
+ return;
+ case EXCHANGE_ACCOUNT_FOLDER_NO_SUCH_USER:
+ e_error_run (NULL, ERROR_DOMAIN ":no-user-error", NULL);
+ return;
+ }
+
+ /* We need to get the physical uri for the Inbox */
+ inbox_uri = exchange_account_get_standard_uri (account, "inbox");
+ inbox = exchange_account_get_folder (account, inbox_uri);
+ inbox_physical_uri = e_folder_get_physical_uri (inbox);
+
+ /* To get the CamelStore/Folder */
+ mail_get_folder (inbox_physical_uri, 0, exchange_get_folder, target_uri, mail_msg_unordered_push);
+}
+
+static void
+unsubscribe_dialog_ab_response (GtkDialog *dialog, gint response, ESource *source)
+{
+
+ if (response == GTK_RESPONSE_OK) {
+ ExchangeAccount *account = NULL;
+ gchar *path = NULL;
+ gchar *uri = NULL;
+ const gchar *source_uid = NULL;
+ ESourceGroup *source_group = NULL;
+
+ g_return_if_fail (source != NULL);
+
+ account = exchange_operations_get_exchange_account ();
+
+ if (!account)
+ return;
+
+ uri = e_source_get_uri (source);
+ path = g_strdup (uri + strlen ("exchange://") + strlen (account->account_filename));
+ source_uid = e_source_peek_uid (source);
+
+ exchange_account_remove_shared_folder (account, path);
+
+ source_group = e_source_peek_group (source);
+ e_source_group_remove_source_by_uid (source_group, source_uid);
+ g_free (path);
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ }
+ if (response == GTK_RESPONSE_CANCEL)
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ if (response == GTK_RESPONSE_DELETE_EVENT)
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
+unsubscribe_dialog_response (GtkDialog *dialog, gint response, ESource *source)
+{
+
+ if (response == GTK_RESPONSE_OK) {
+ GSList *ids, *node_to_be_deleted;
+ ExchangeAccount *account = NULL;
+ gchar *path = NULL;
+ gchar *ruri = NULL;
+ const gchar *source_uid = NULL;
+ GConfClient *client;
+ ESourceGroup *source_group = NULL;
+
+ g_return_if_fail (source != NULL);
+
+ client = gconf_client_get_default ();
+
+ account = exchange_operations_get_exchange_account ();
+
+ if (!account)
+ return;
+
+ ruri = (gchar *) e_source_peek_relative_uri (source);
+ source_uid = e_source_peek_uid (source);
+
+ path = g_strdup (ruri + strlen (account->account_filename));
+ exchange_account_remove_shared_folder (account, path);
+ ids = gconf_client_get_list (client,
+ CONF_KEY_SELECTED_CAL_SOURCES,
+ GCONF_VALUE_STRING, NULL);
+ if (ids) {
+ node_to_be_deleted = g_slist_find_custom (
+ ids,
+ source_uid,
+ (GCompareFunc) strcmp);
+ if (node_to_be_deleted) {
+ g_free (node_to_be_deleted->data);
+ ids = g_slist_delete_link (ids,
+ node_to_be_deleted);
+ gconf_client_set_list (client,
+ CONF_KEY_SELECTED_CAL_SOURCES,
+ GCONF_VALUE_STRING, ids, NULL);
+ }
+ g_slist_foreach (ids, (GFunc) g_free, NULL);
+ g_slist_free (ids);
+ }
+
+ source_group = e_source_peek_group (source);
+ e_source_group_remove_source_by_uid (source_group, source_uid);
+ g_free (path);
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ }
+ if (response == GTK_RESPONSE_CANCEL)
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ if (response == GTK_RESPONSE_DELETE_EVENT)
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
+eex_addresssbook_unsubscribe (ESource *source)
+{
+ GtkWidget *dialog = NULL;
+ ExchangeAccount *account = NULL;
+ gchar *title = NULL;
+ gchar *displayed_folder_name = NULL;
+ gint response;
+ gint mode;
+ ExchangeConfigListenerStatus status;
+
+ g_return_if_fail (source != NULL);
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account)
+ return;
+
+ status = exchange_is_offline (&mode);
+ if (status != CONFIG_LISTENER_STATUS_OK) {
+ g_warning ("Config listener not found");
+ return;
+ } else if (mode == OFFLINE_MODE) {
+ e_error_run (NULL, ERROR_DOMAIN ":account-offline-generic", NULL);
+ return;
+ }
+
+ displayed_folder_name = (gchar *) e_source_peek_name (source);
+ dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ _("Really unsubscribe from folder \"%s\"?"),
+ displayed_folder_name);
+
+ gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_REMOVE, GTK_RESPONSE_OK);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 6);
+
+ gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 6);
+
+ title = g_strdup_printf (_("Unsubscribe from \"%s\""), displayed_folder_name);
+ gtk_window_set_title (GTK_WINDOW (dialog), title);
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+ g_free (title);
+ g_free (displayed_folder_name);
+
+ gtk_widget_show (dialog);
+ unsubscribe_dialog_ab_response (GTK_DIALOG (dialog), response, source);
+}
+
+static void
+eex_calendar_unsubscribe (ESource *source)
+{
+ GtkWidget *dialog = NULL;
+ ExchangeAccount *account = NULL;
+ gchar *title = NULL;
+ const gchar *displayed_folder_name;
+ gint response;
+ gint mode;
+ ExchangeConfigListenerStatus status;
+
+ g_return_if_fail (source != NULL);
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account)
+ return;
+
+ status = exchange_is_offline (&mode);
+
+ if (status != CONFIG_LISTENER_STATUS_OK) {
+ g_warning ("Config listener not found");
+ return;
+ } else if (mode == OFFLINE_MODE) {
+ e_error_run (NULL, ERROR_DOMAIN ":account-offline-generic", NULL);
+ return;
+ }
+
+ displayed_folder_name = e_source_peek_name (source);
+ dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ _("Really unsubscribe from folder \"%s\"?"),
+ displayed_folder_name);
+
+ gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_REMOVE, GTK_RESPONSE_OK);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 6);
+
+ gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 6);
+
+ title = g_strdup_printf (_("Unsubscribe from \"%s\""), displayed_folder_name);
+ gtk_window_set_title (GTK_WINDOW (dialog), title);
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+ g_free (title);
+
+ gtk_widget_show (dialog);
+ unsubscribe_dialog_response (GTK_DIALOG (dialog), response, source);
+}
+
+void
+call_folder_subscribe (const gchar *folder_name)
+{
+ ExchangeAccount *account = NULL;
+ gint mode;
+ ExchangeConfigListenerStatus status;
+
+ g_return_if_fail (folder_name != NULL);
+
+ account = exchange_operations_get_exchange_account ();
+ if (!account)
+ return;
+
+ status = exchange_is_offline (&mode);
+ if (status != CONFIG_LISTENER_STATUS_OK) {
+ g_warning ("Config listener not found");
+ return;
+ } else if (mode == OFFLINE_MODE) {
+ /* Translators: this error code can be used for any operation
+ * (like subscribing to other user's folders, unsubscribing
+ * etc,) which can not be performed in offline mode
+ */
+ e_error_run (NULL, ERROR_DOMAIN ":account-offline-generic", NULL);
+ return;
+ }
+
+ create_folder_subscription_dialog (account, folder_name);
+}
+
+void
+call_folder_unsubscribe (const gchar *folder_type, const gchar *uri, ESource *source)
+{
+ g_return_if_fail (folder_type != NULL);
+ g_return_if_fail (uri != NULL);
+
+ if (g_str_equal (folder_type, N_("Inbox"))) {
+ eex_folder_inbox_unsubscribe (uri);
+ } else if (g_str_equal (folder_type, N_("Calendar"))) {
+ g_return_if_fail (source != NULL);
+ eex_calendar_unsubscribe (source);
+ } else if (g_str_equal (folder_type, N_("Tasks"))) {
+ g_return_if_fail (source != NULL);
+ eex_calendar_unsubscribe (source);
+ } else if (g_str_equal (folder_type, N_("Contacts"))) {
+ g_return_if_fail (source != NULL);
+ eex_addresssbook_unsubscribe (source);
+ } else {
+ g_return_if_reached ();
+ }
+}
diff --git a/eplugin/exchange-mail-send-options.c b/eplugin/exchange-mail-send-options.c
new file mode 100644
index 0000000..04065e4
--- /dev/null
+++ b/eplugin/exchange-mail-send-options.c
@@ -0,0 +1,196 @@
+/*
+ * 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:
+ * R.Raghavendran <raghavguru7 gmail com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <camel/camel-mime-message.h>
+#include <camel/camel-address.h>
+#include "mail/em-event.h"
+
+#include "composer/e-msg-composer.h"
+#include "libedataserver/e-account.h"
+
+#include "exchange-send-options.h"
+
+void org_gnome_exchange_send_options (EPlugin *ep, EMEventTargetComposer *t);
+
+static ExchangeSendOptionsDialog *dialog=NULL;
+
+static void
+append_to_header (ExchangeSendOptionsDialog *dialog, gint state, gpointer data)
+{
+ EMsgComposer *composer;
+ CamelAddress *sender_address;
+ const gchar *sender_id, *recipient_id;
+ struct _camel_header_address *addr;
+ struct _camel_header_address *sender_addr;
+
+ composer = (EMsgComposer *)data;
+ if (state == GTK_RESPONSE_OK) {
+ if (dialog->options->importance) {
+ switch (dialog->options->importance) {
+ case E_IMP_HIGH :
+ e_msg_composer_modify_header (composer, "Importance", "high");
+ break;
+ case E_IMP_LOW :
+ e_msg_composer_modify_header (composer, "Importance", "low");
+ break;
+ default :
+ g_print ("\nNo importance set");
+ break;
+ }
+ }
+ else
+ e_msg_composer_remove_header (composer, "Importance");
+
+ if (dialog->options->sensitivity) {
+ switch (dialog->options->sensitivity) {
+ case E_SENSITIVITY_CONFIDENTIAL :
+ e_msg_composer_modify_header (composer, "Sensitivity", "Company-Confidential");
+ break;
+ case E_SENSITIVITY_PERSONAL :
+ e_msg_composer_modify_header (composer, "Sensitivity", "Personal");
+ break;
+ case E_SENSITIVITY_PRIVATE :
+ e_msg_composer_modify_header (composer, "Sensitivity", "Private");
+ break;
+ default :
+ g_print ("\nNo importance set");
+ break;
+ }
+ }
+ else
+ e_msg_composer_remove_header (composer, "Sensitivity");
+
+ sender_address = (CamelAddress *) e_msg_composer_get_from (composer);
+ sender_id = (const gchar *) camel_address_encode (sender_address);
+
+ addr = camel_header_address_decode (dialog->options->delegate_address, NULL);
+ sender_addr = camel_header_address_decode (sender_id, NULL);
+
+ if (dialog->options->send_as_del_enabled &&
+ dialog->options->delegate_address &&
+ g_ascii_strcasecmp(addr->v.addr, sender_addr->v.addr)) {
+
+ e_msg_composer_modify_header (composer, "Sender" , sender_id);
+
+ /* This block handles the case wherein the address to be added
+ * in the "From" field has no name associated with it.
+ * So for cases where there is no name we append the address
+ * (only email) within angular braces.
+ */
+ if (!g_ascii_strcasecmp (addr->name, "")) {
+ recipient_id = g_strdup_printf ("<%s>",
+ dialog->options->delegate_address);
+ e_msg_composer_add_header (composer, "From", recipient_id);
+ }
+
+ else
+ e_msg_composer_add_header (composer, "From",
+ dialog->options->delegate_address);
+ }
+
+ else {
+ e_msg_composer_remove_header (composer, "Sender");
+ e_msg_composer_add_header (composer, "From", sender_id);
+ }
+
+ if (dialog->options->delivery_enabled) {
+ EComposerHeaderTable *table;
+ EAccount *account;
+ gchar *mdn_address;
+
+ table = e_msg_composer_get_header_table (composer);
+ account = e_composer_header_table_get_account (table);
+ mdn_address = account->id->reply_to;
+ if (!mdn_address || !*mdn_address)
+ mdn_address = account->id->address;
+ e_msg_composer_modify_header (composer, "Return-Receipt-To", mdn_address);
+ }
+ else
+ e_msg_composer_remove_header (composer, "Return-Receipt-To");
+
+ if (dialog->options->read_enabled) {
+ EComposerHeaderTable *table;
+ EAccount *account;
+ gchar *mdn_address;
+
+ table = e_msg_composer_get_header_table (composer);
+ account = e_composer_header_table_get_account (table);
+ mdn_address = account->id->reply_to;
+ if (!mdn_address || !*mdn_address)
+ mdn_address = account->id->address;
+
+ e_msg_composer_modify_header (composer, "Disposition-Notification-To", mdn_address);
+ }
+ else
+ e_msg_composer_remove_header (composer, "Disposition-Notification-To");
+ }
+}
+
+static void
+send_options_commit (EMsgComposer *comp, gpointer user_data)
+{
+ if (!user_data && !EXCHANGE_IS_SENDOPTIONS_DIALOG (user_data))
+ return;
+
+ if (dialog) {
+ g_print ("\nDialog getting unreferenced ");
+ g_object_unref (dialog);
+ dialog = NULL;
+ }
+}
+
+void
+org_gnome_exchange_send_options (EPlugin *ep, EMEventTargetComposer *target)
+{
+ EMsgComposer *composer = target->composer;
+ EComposerHeaderTable *table;
+ EAccount *account = NULL;
+ gchar *temp = NULL;
+
+ table = e_msg_composer_get_header_table (composer);
+ account = e_composer_header_table_get_account (table);
+ if (!account)
+ return;
+
+ temp = strstr (account->transport->url, "exchange");
+ if (!temp) {
+ return;
+ }
+ e_msg_composer_set_send_options (composer, TRUE);
+ /*disply the send options dialog*/
+ if (!dialog) {
+ g_print ("New dialog\n\n");
+ dialog = exchange_sendoptions_dialog_new ();
+ }
+ exchange_sendoptions_dialog_run (dialog, GTK_WIDGET (composer));
+ g_signal_connect (dialog, "sod_response", G_CALLBACK (append_to_header), GTK_WIDGET (composer));
+
+ g_signal_connect (GTK_WIDGET (composer), "destroy",
+ G_CALLBACK (send_options_commit), dialog);
+
+}
diff --git a/eplugin/exchange-operations.c b/eplugin/exchange-operations.c
new file mode 100644
index 0000000..35ed781
--- /dev/null
+++ b/eplugin/exchange-operations.c
@@ -0,0 +1,305 @@
+/*
+ * 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:
+ * Praveen Kumar <kpraveen novell com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include <string.h>
+#include <glib/gi18n.h>
+
+#include "exchange-operations.h"
+#include <e-folder-exchange.h>
+#include <exchange-hierarchy.h>
+#include <e-util/e-error.h>
+
+ExchangeConfigListener *exchange_global_config_listener=NULL;
+
+static const gchar *error_ids[] = {
+ "config-error",
+ "password-weak-error",
+ "password-change-error",
+ "password-change-success",
+ "account-offline",
+ "password-incorrect",
+ "account-domain-error",
+ "account-mailbox-na",
+ "account-version-error",
+ "account-wss-error",
+ "account-no-mailbox",
+ "account-resolve-error",
+ "account-connect-error",
+ "password-expired",
+ "account-unknown-error",
+ "account-quota-error",
+ "account-quota-send-error",
+ "account-quota-warn"
+};
+
+static void
+free_exchange_listener (void)
+{
+ g_object_unref (exchange_global_config_listener);
+}
+
+gint
+e_plugin_lib_enable (EPlugin *eplib, gint enable)
+{
+ if (!exchange_global_config_listener) {
+ exchange_global_config_listener = exchange_config_listener_new ();
+ g_atexit (free_exchange_listener);
+ }
+ return 0;
+}
+
+ExchangeConfigListenerStatus
+exchange_is_offline (gint *mode)
+{
+ return exchange_config_listener_get_offline_status (exchange_global_config_listener, mode);
+}
+
+/* FIXME: See if a GLib variant of this function available */
+gboolean
+exchange_operations_tokenize_string (gchar **string, gchar *token, gchar delimit, guint maxsize)
+{
+ guint i=0;
+ gchar *str=*string;
+ while (*str!=delimit && *str!='\0' && i<maxsize-1) {
+ token[i++]=*str++;
+ }
+ while (*str==delimit)
+ str++;
+ token[i]='\0';
+ *string = str;
+ if (i==0)
+ return FALSE;
+ return TRUE;
+}
+
+gboolean
+exchange_operations_cta_add_node_to_tree (GtkTreeStore *store, GtkTreeIter *parent, const gchar *ruri)
+{
+ GtkTreeIter iter;
+ gchar *luri=(gchar *)ruri;
+ gchar nodename[80];
+ gchar *uri;
+ gboolean status, found;
+
+ exchange_operations_tokenize_string (&luri, nodename, '/', sizeof(nodename));
+
+ if (!nodename[0]) {
+ return TRUE;
+ }
+
+ if (!parent) {
+ uri = g_strdup (nodename);
+ }
+ else {
+ gchar *tmpuri;
+ gtk_tree_model_get (GTK_TREE_MODEL (store), parent, 1, &tmpuri, -1);
+ uri = g_strconcat (tmpuri, "/", nodename, NULL);
+ g_free (tmpuri);
+ }
+
+ if (!strcmp (nodename, "personal") && !parent) {
+ /* FIXME: Don't hardcode this */
+ strcpy (nodename, _("Personal Folders"));
+ }
+
+ found = FALSE;
+ status = gtk_tree_model_iter_children (GTK_TREE_MODEL (store), &iter, parent);
+ while (status) {
+ gchar *readname;
+ gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, 0, &readname, -1);
+ if (!strcmp (nodename, readname)) {
+ found = TRUE;
+ exchange_operations_cta_add_node_to_tree (store, &iter, luri);
+ g_free (readname);
+ break;
+ }
+ status = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
+ }
+
+ if (!found) {
+ gtk_tree_store_append (store, &iter, parent);
+ gtk_tree_store_set (store, &iter, 0, nodename, 1, uri, -1);
+ exchange_operations_cta_add_node_to_tree (store, &iter, luri);
+ }
+
+ g_free (uri);
+ return TRUE;
+}
+
+void
+exchange_operations_cta_select_node_from_tree (GtkTreeStore *store, GtkTreeIter *parent, const gchar *nuri, const gchar *ruri, GtkTreeSelection *selection)
+{
+ gchar *luri=(gchar *)nuri;
+ gchar nodename[80];
+ GtkTreeIter iter;
+ gboolean status;
+
+ if (!luri)
+ return;
+
+ exchange_operations_tokenize_string (&luri, nodename, '/', sizeof(nodename));
+ if (!nodename[0]) {
+ return;
+ }
+
+ if (!strcmp (nodename, "personal") && !parent) {
+ /* FIXME: Don't hardcode this */
+ strcpy (nodename, _("Personal Folders"));
+ }
+
+ status = gtk_tree_model_iter_children (GTK_TREE_MODEL (store), &iter, parent);
+ while (status) {
+ gchar *readname;
+ gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, 0, &readname, -1);
+ if (!strcmp (nodename, readname)) {
+ gchar *readruri;
+ gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, 1, &readruri, -1);
+ if (!strcmp (ruri, readruri)) {
+ gtk_tree_selection_select_iter (selection, &iter);
+ return;
+ }
+ g_free (readname);
+ g_free (readruri);
+ exchange_operations_cta_select_node_from_tree (store, &iter, luri, ruri, selection);
+ break;
+ }
+ status = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
+ }
+ return;
+}
+
+ExchangeAccount *
+exchange_operations_get_exchange_account (void)
+{
+ ExchangeAccount *account = NULL;
+ ExchangeAccountResult result;
+ GSList *acclist;
+ gint mode;
+
+ acclist = exchange_config_listener_get_accounts (exchange_global_config_listener);
+ /* FIXME: Need to be changed for handling multiple accounts */
+ if (acclist) {
+ account = acclist->data;
+
+ exchange_config_listener_get_offline_status (exchange_global_config_listener,
+ &mode);
+
+ if (mode == OFFLINE_MODE) {
+ return account;
+ }
+ else if (exchange_account_get_context (account)) {
+ return account;
+ } else {
+ /* Try authenticating */
+ result = exchange_config_listener_authenticate(exchange_global_config_listener, account);
+ if (result != EXCHANGE_ACCOUNT_CONNECT_SUCCESS) {
+ exchange_operations_report_error (account, result);
+ return NULL;
+ }
+ if (exchange_account_get_context (account))
+ return account;
+ }
+ }
+
+ return NULL;
+}
+
+void
+exchange_operations_report_error (ExchangeAccount *account, ExchangeAccountResult result)
+{
+ gchar *error_string;
+ gchar *quota_value;
+ GtkWidget *widget;
+
+ g_return_if_fail (account != NULL);
+
+ if (result == EXCHANGE_ACCOUNT_CONNECT_SUCCESS)
+ return;
+
+ error_string = g_strconcat ("org-gnome-exchange-operations:", error_ids[result], NULL);
+
+ switch (result) {
+ case EXCHANGE_ACCOUNT_MAILBOX_NA:
+ widget = e_error_new (NULL, error_string, exchange_account_get_username (account), NULL);
+ break;
+ case EXCHANGE_ACCOUNT_NO_MAILBOX:
+ widget = e_error_new (NULL, error_string, exchange_account_get_username (account),
+ account->exchange_server, NULL);
+ break;
+ case EXCHANGE_ACCOUNT_RESOLVE_ERROR:
+ case EXCHANGE_ACCOUNT_CONNECT_ERROR:
+ case EXCHANGE_ACCOUNT_UNKNOWN_ERROR:
+ widget = e_error_new (NULL, error_string, account->exchange_server, NULL);
+ break;
+ case EXCHANGE_ACCOUNT_QUOTA_RECIEVE_ERROR:
+ case EXCHANGE_ACCOUNT_QUOTA_SEND_ERROR:
+ case EXCHANGE_ACCOUNT_QUOTA_WARN:
+ quota_value = g_strdup_printf ("%.2f", account->mbox_size);
+ widget = e_error_new (NULL, error_string, quota_value, NULL);
+ g_free (quota_value);
+ break;
+ default:
+ widget = e_error_new (NULL, error_string, NULL);
+ }
+ g_signal_connect ((GtkDialog *)widget, "response", G_CALLBACK (gtk_widget_destroy), widget);
+ gtk_widget_show (widget);
+ g_free (error_string);
+}
+
+void exchange_operations_update_child_esources (ESource *source, const gchar *old_path, const gchar *new_path)
+{
+ ESourceGroup *group;
+ GSList *sources, *tsource;
+ group = e_source_peek_group (source);
+ sources = e_source_group_peek_sources (group);
+ for (tsource = sources; tsource != NULL; tsource = tsource->next) {
+ gchar *ruri;
+ ruri = (gchar *) e_source_peek_relative_uri (tsource->data);
+ if (ruri && g_strrstr (ruri, old_path)) {
+ /* This ESource points to one of the child folders */
+ gchar **tmpv, *truri;
+ /* A nasty search and replace */
+ tmpv = g_strsplit (ruri, old_path, -1);
+ truri = g_strjoinv (new_path, tmpv);
+ e_source_set_relative_uri (tsource->data, truri);
+ g_strfreev (tmpv);
+ g_free (truri);
+ }
+ }
+}
+
+gboolean
+is_exchange_personal_folder (ExchangeAccount *account, gchar *uri)
+{
+ ExchangeHierarchy *hier;
+ EFolder *folder;
+
+ folder = exchange_account_get_folder (account, uri);
+ if (folder) {
+ hier = e_folder_exchange_get_hierarchy (folder);
+ if (hier->type != EXCHANGE_HIERARCHY_PERSONAL)
+ return FALSE;
+ else
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/eplugin/exchange-operations.h b/eplugin/exchange-operations.h
new file mode 100644
index 0000000..60c2f20
--- /dev/null
+++ b/eplugin/exchange-operations.h
@@ -0,0 +1,56 @@
+/*
+ * 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:
+ * Praveen Kumar <kpraveen novell com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __EXCHANGE_OPERATIONS_H__
+#define __EXCHANGE_OPERATIONS_H__
+
+#include <gtk/gtk.h>
+
+#include "e-util/e-plugin.h"
+#include "exchange-config-listener.h"
+#include <exchange-account.h>
+
+G_BEGIN_DECLS
+
+#define ERROR_DOMAIN "org-gnome-exchange-operations"
+
+extern ExchangeConfigListener *exchange_global_config_listener;
+
+gint e_plugin_lib_enable (EPlugin *eplib, gint enable);
+
+ExchangeAccount *exchange_operations_get_exchange_account (void);
+ExchangeConfigListenerStatus exchange_is_offline (gint *mode);
+
+gboolean exchange_operations_tokenize_string (gchar **string, gchar *token, gchar delimit, guint maxsize);
+
+gboolean exchange_operations_cta_add_node_to_tree (GtkTreeStore *store, GtkTreeIter *parent, const gchar *nuri);
+void exchange_operations_cta_select_node_from_tree (GtkTreeStore *store, GtkTreeIter *parent, const gchar *nuri, const gchar *ruri, GtkTreeSelection *selection);
+
+void exchange_operations_report_error (ExchangeAccount *account, ExchangeAccountResult result);
+
+void exchange_operations_update_child_esources (ESource *source, const gchar *old_path, const gchar *new_path);
+
+gboolean is_exchange_personal_folder (ExchangeAccount *account, gchar *uri);
+
+G_END_DECLS
+
+#endif
diff --git a/eplugin/exchange-permissions-dialog.c b/eplugin/exchange-permissions-dialog.c
new file mode 100644
index 0000000..20af66e
--- /dev/null
+++ b/eplugin/exchange-permissions-dialog.c
@@ -0,0 +1,984 @@
+/*
+ * 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:
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "exchange-permissions-dialog.h"
+#include "exchange-hierarchy.h"
+#include "exchange-user-dialog.h"
+
+#include "e2k-context.h"
+#include "e2k-global-catalog.h"
+#include "e2k-propnames.h"
+#include "e2k-sid.h"
+#include "e2k-security-descriptor.h"
+
+#include "e2k-uri.h"
+#include "e2k-utils.h"
+#include "e-folder-exchange.h"
+#include "exchange-account.h"
+#include "exchange-operations.h"
+
+#include <e-util/e-dialog-utils.h>
+#include <e-util/e-error.h>
+
+struct _ExchangePermissionsDialogPrivate {
+ ExchangeAccount *account;
+ gchar *base_uri, *folder_path;
+ E2kSecurityDescriptor *sd;
+ gboolean changed;
+ gboolean frozen;
+
+ /* The user list */
+ GtkTreeView *list_view;
+ GtkListStore *list_store;
+ GtkTreeSelection *list_selection;
+ E2kSid *selected_sid;
+
+ /* The Role menu */
+ GtkComboBox *role_optionmenu;
+
+ /* Custom label is added or not */
+ gboolean custom_added;
+
+ GtkWidget *separator, *custom;
+ E2kPermissionsRole selected_role;
+
+ /* The toggles */
+ GtkToggleButton *read_items_check, *create_items_check;
+ GtkToggleButton *create_subfolders_check, *folder_visible_check;
+ GtkToggleButton *folder_owner_check, *folder_contact_check;
+ GtkToggleButton *edit_none_radio, *edit_own_radio, *edit_all_radio;
+ GtkToggleButton *delete_none_radio, *delete_own_radio, *delete_all_radio;
+ guint32 selected_perms;
+};
+
+enum {
+ EXCHANGE_PERMISSIONS_DIALOG_NAME_COLUMN,
+ EXCHANGE_PERMISSIONS_DIALOG_ROLE_COLUMN,
+ EXCHANGE_PERMISSIONS_DIALOG_SID_COLUMN,
+
+ EXCHANGE_PERMISSIONS_DIALOG_NUM_COLUMNS
+};
+
+#define PARENT_TYPE GTK_TYPE_DIALOG
+static GtkDialogClass *parent_class = NULL;
+
+static void
+finalize (GObject *object)
+{
+ ExchangePermissionsDialog *dialog =
+ EXCHANGE_PERMISSIONS_DIALOG (object);
+
+ g_free (dialog->priv->base_uri);
+ g_free (dialog->priv->folder_path);
+
+ if (dialog->priv->sd)
+ g_object_unref (dialog->priv->sd);
+
+ g_free (dialog->priv);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+class_init (GObjectClass *object_class)
+{
+ parent_class = g_type_class_ref (PARENT_TYPE);
+
+ /* virtual method override */
+ object_class->finalize = finalize;
+}
+
+static void
+init (GObject *object)
+{
+ ExchangePermissionsDialog *dialog =
+ EXCHANGE_PERMISSIONS_DIALOG (object);
+
+ dialog->priv = g_new0 (ExchangePermissionsDialogPrivate, 1);
+}
+
+E2K_MAKE_TYPE (exchange_permissions_dialog, ExchangePermissionsDialog, class_init, init, PARENT_TYPE)
+
+static GtkWidget *create_permissions_vbox (ExchangePermissionsDialog *dialog);
+static void setup_user_list (ExchangePermissionsDialog *dialog);
+static void display_permissions (ExchangePermissionsDialog *dialog);
+static void dialog_response (ExchangePermissionsDialog *dialog,
+ gint response, gpointer user_data);
+
+static const gchar *sd_props[] = {
+ E2K_PR_EXCHANGE_SD_BINARY,
+ E2K_PR_EXCHANGE_SD_XML
+};
+static const gint n_sd_props = sizeof (sd_props) / sizeof (sd_props[0]);
+
+/**
+ * exchange_permissions_dialog_new:
+ * @account: an account
+ * @folder: the folder whose permissions are to be editted
+ * @parent: a widget in the dialog's parent window
+ *
+ * Creates and displays a modeless permissions editor dialog for @folder.
+ **/
+void
+exchange_permissions_dialog_new (ExchangeAccount *account,
+ EFolder *folder,
+ GtkWidget *parent)
+{
+ ExchangePermissionsDialog *dialog;
+ const gchar *base_uri, *folder_uri, *folder_path;
+ E2kContext *ctx;
+ ExchangeHierarchy *hier;
+ GtkWidget *box;
+ gchar *title;
+ E2kHTTPStatus status;
+ E2kResult *results;
+ gint nresults = 0;
+ xmlNode *xml_form;
+ GByteArray *binary_form;
+
+ g_return_if_fail (folder);
+
+ ctx = exchange_account_get_context (account);
+ g_return_if_fail (ctx);
+
+ /* Create the dialog */
+ dialog = g_object_new (EXCHANGE_TYPE_PERMISSIONS_DIALOG, NULL);
+
+ title = g_strdup_printf (_("Permissions for %s"),
+ e_folder_get_name (folder));
+ gtk_window_set_title (GTK_WINDOW (dialog), title);
+ g_free (title);
+
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (dialog_response), NULL);
+
+ dialog->priv->changed = FALSE;
+
+ box = create_permissions_vbox (dialog);
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+ box, TRUE, TRUE, 0);
+
+ dialog->priv->account = account;
+ g_object_ref (account);
+
+ hier = e_folder_exchange_get_hierarchy (folder);
+ base_uri = e_folder_exchange_get_internal_uri (hier->toplevel);
+ dialog->priv->base_uri = g_strdup (base_uri);
+ folder_uri = e_folder_exchange_get_internal_uri (folder);
+ folder_path = e2k_uri_relative (dialog->priv->base_uri, folder_uri);
+ dialog->priv->folder_path = g_strdup (folder_path);
+
+ /* And fetch the security descriptor */
+ status = e2k_context_propfind (ctx, NULL, folder_uri,
+ sd_props, n_sd_props,
+ &results, &nresults);
+ if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status) || nresults < 1) {
+ lose:
+ e_error_run (GTK_WINDOW (parent), ERROR_DOMAIN ":perm-read-error", NULL);
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ if (nresults)
+ e2k_results_free (results, nresults);
+ return;
+ }
+
+ xml_form = e2k_properties_get_prop (results[0].props,
+ E2K_PR_EXCHANGE_SD_XML);
+ binary_form = e2k_properties_get_prop (results[0].props,
+ E2K_PR_EXCHANGE_SD_BINARY);
+ if (!xml_form || !binary_form)
+ goto lose;
+
+ dialog->priv->sd = e2k_security_descriptor_new (xml_form, binary_form);
+ if (!dialog->priv->sd)
+ goto lose;
+
+ setup_user_list (dialog);
+ gtk_widget_show (GTK_WIDGET (dialog));
+ if (nresults)
+ e2k_results_free (results, nresults);
+}
+
+static void
+dialog_response (ExchangePermissionsDialog *dialog, gint response,
+ gpointer user_data)
+{
+ E2kContext *ctx;
+ GByteArray *binsd;
+ E2kProperties *props;
+ E2kResultIter *iter;
+ E2kResult *result;
+ E2kHTTPStatus status;
+
+ if (response != GTK_RESPONSE_OK || !dialog->priv->changed) {
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ return;
+ }
+
+ ctx = exchange_account_get_context (dialog->priv->account);
+ g_return_if_fail (ctx != NULL);
+
+ binsd = e2k_security_descriptor_to_binary (dialog->priv->sd);
+ if (!binsd) {
+ e_error_run (GTK_WINDOW (dialog), ERROR_DOMAIN ":perm-update-error", "", NULL);
+ return;
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog), FALSE);
+
+ props = e2k_properties_new ();
+ e2k_properties_set_binary (props, E2K_PR_EXCHANGE_SD_BINARY, binsd);
+
+ /* We use BPROPPATCH here instead of PROPPATCH, because
+ * PROPPATCH seems to mysteriously fail in someone else's
+ * folder hierarchy. #29726
+ */
+ iter = e2k_context_bproppatch_start (ctx, NULL, dialog->priv->base_uri,
+ (const gchar **)&dialog->priv->folder_path, 1,
+ props, FALSE);
+ e2k_properties_free (props);
+
+ result = e2k_result_iter_next (iter);
+ if (result) {
+ status = result->status;
+ e2k_result_iter_free (iter);
+ } else
+ status = e2k_result_iter_free (iter);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog), TRUE);
+
+ if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
+ e_error_run (GTK_WINDOW (dialog), ERROR_DOMAIN ":perm-update-error",
+ status == E2K_HTTP_UNAUTHORIZED ?
+ _("(Permission denied.)") : "", NULL);
+ return;
+ }
+
+ if (response == GTK_RESPONSE_OK)
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
+set_permissions (ExchangePermissionsDialog *dialog, guint32 perms)
+{
+ dialog->priv->selected_perms = perms;
+ dialog->priv->selected_role = e2k_permissions_role_find (perms);
+ e2k_security_descriptor_set_permissions (dialog->priv->sd,
+ dialog->priv->selected_sid,
+ dialog->priv->selected_perms);
+
+ dialog->priv->changed = TRUE;
+}
+
+/* User list functions */
+
+static void
+list_view_selection_changed (GtkTreeSelection *selection, gpointer user_data)
+{
+ ExchangePermissionsDialog *dialog = user_data;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ E2kSid *sid;
+
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter))
+ return;
+ gtk_tree_model_get (model, &iter,
+ EXCHANGE_PERMISSIONS_DIALOG_SID_COLUMN, &sid,
+ -1);
+
+ dialog->priv->selected_sid = sid;
+ dialog->priv->selected_perms =
+ e2k_security_descriptor_get_permissions (dialog->priv->sd, sid);
+ dialog->priv->selected_role =
+ e2k_permissions_role_find (dialog->priv->selected_perms);
+
+ /* "Default" or "Anonymous" can't be a Folder contact, but any
+ * real person can.
+ */
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog->priv->folder_contact_check),
+ e2k_sid_get_sid_type (sid) != E2K_SID_TYPE_WELL_KNOWN_GROUP);
+
+ /* Update role menu and permissions checkboxes */
+ display_permissions (dialog);
+}
+
+static void
+add_user_to_list (ExchangePermissionsDialog *dialog, E2kSid *sid, gboolean select)
+{
+ guint32 perms;
+ E2kPermissionsRole role;
+ GtkTreeIter iter;
+
+ perms = e2k_security_descriptor_get_permissions (dialog->priv->sd,
+ sid);
+ role = e2k_permissions_role_find (perms);
+
+ if (e2k_sid_get_sid_type (sid) == E2K_SID_TYPE_WELL_KNOWN_GROUP)
+ gtk_list_store_insert (dialog->priv->list_store, &iter, 1);
+ else
+ gtk_list_store_append (dialog->priv->list_store, &iter);
+
+ gtk_list_store_set (dialog->priv->list_store, &iter,
+ EXCHANGE_PERMISSIONS_DIALOG_NAME_COLUMN,
+ e2k_sid_get_display_name (sid),
+ EXCHANGE_PERMISSIONS_DIALOG_ROLE_COLUMN,
+ e2k_permissions_role_get_name (role),
+ EXCHANGE_PERMISSIONS_DIALOG_SID_COLUMN,
+ sid,
+ -1);
+
+ if (select)
+ gtk_tree_selection_select_iter (dialog->priv->list_selection, &iter);
+}
+
+static void
+add_clicked (GtkButton *button, gpointer user_data)
+{
+ ExchangePermissionsDialog *dialog = user_data;
+ E2kGlobalCatalog *gc;
+ E2kGlobalCatalogStatus status;
+ E2kGlobalCatalogEntry *entry;
+ E2kSid *sid2;
+ GtkTreeIter iter;
+ GtkWidget *user_dialog;
+ const guint8 *bsid, *bsid2;
+ GList *email_list = NULL;
+ GList *l = NULL;
+ gchar *email = NULL;
+ gboolean valid;
+ gint result;
+
+ gc = exchange_account_get_global_catalog (dialog->priv->account);
+
+ if (!gc) {
+ e_error_run (GTK_WINDOW (dialog), ERROR_DOMAIN ":acl-no-gcs-error",
+ NULL);
+ return;
+ }
+
+ user_dialog = e2k_user_dialog_new (GTK_WIDGET (dialog), _("Add User:"), _("Add User"));
+ result = gtk_dialog_run (GTK_DIALOG (user_dialog));
+
+ if (result == GTK_RESPONSE_OK)
+ email_list = e2k_user_dialog_get_user_list (E2K_USER_DIALOG (user_dialog));
+ gtk_widget_destroy (user_dialog);
+
+ if (email_list == NULL)
+ return;
+
+ for (l = email_list; l; l = g_list_next (l)) {
+ email = l->data;
+ status = e2k_global_catalog_lookup (
+ gc, NULL, /* FIXME: cancellable */
+ E2K_GLOBAL_CATALOG_LOOKUP_BY_EMAIL, email,
+ E2K_GLOBAL_CATALOG_LOOKUP_SID, &entry);
+ switch (status) {
+ case E2K_GLOBAL_CATALOG_OK:
+ break;
+ case E2K_GLOBAL_CATALOG_NO_SUCH_USER:
+ e_error_run (GTK_WINDOW (dialog), ERROR_DOMAIN ":no-user-error", email, NULL);
+ break;
+ case E2K_GLOBAL_CATALOG_NO_DATA:
+ e_error_run (GTK_WINDOW (dialog), ERROR_DOMAIN ":acl-add-error", email, NULL);
+ break;
+ default:
+ e_error_run (GTK_WINDOW (dialog), ERROR_DOMAIN ":perm-unknown-error", email, NULL);
+ break;
+ }
+ if (status != E2K_GLOBAL_CATALOG_OK)
+ return;
+
+ /* Make sure the user isn't already there. */
+ bsid = e2k_sid_get_binary_sid (entry->sid);
+ valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (dialog->priv->list_store), &iter);
+ while (valid) {
+ gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->list_store), &iter,
+ EXCHANGE_PERMISSIONS_DIALOG_SID_COLUMN, &sid2,
+ -1);
+ bsid2 = e2k_sid_get_binary_sid (sid2);
+ if (e2k_sid_binary_sid_equal (bsid, bsid2)) {
+ e_error_run (GTK_WINDOW (dialog), ERROR_DOMAIN ":perm-existing-error",
+ entry->display_name, NULL);
+ e2k_global_catalog_entry_free (gc, entry);
+ gtk_tree_selection_select_iter (dialog->priv->list_selection, &iter);
+ return;
+ }
+
+ valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (dialog->priv->list_store), &iter);
+ }
+
+ add_user_to_list (dialog, entry->sid, TRUE);
+
+ /* Calling set_permissions will cause the sd to take a
+ * ref on the sid, allowing us to unref it.
+ */
+ set_permissions (dialog, 0);
+ e2k_global_catalog_entry_free (gc, entry);
+ }
+ g_list_free (email_list);
+}
+
+static void
+remove_clicked (GtkButton *button, gpointer user_data)
+{
+ ExchangePermissionsDialog *dialog = user_data;
+ E2kSid *sid;
+ GdkModifierType modifiers;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ if (!gtk_tree_selection_get_selected (dialog->priv->list_selection,
+ &model, &iter))
+ return;
+ gtk_tree_model_get (model, &iter,
+ EXCHANGE_PERMISSIONS_DIALOG_SID_COLUMN, &sid,
+ -1);
+ gdk_window_get_pointer (NULL, NULL, NULL, &modifiers);
+
+ if (e2k_sid_get_sid_type (sid) == E2K_SID_TYPE_WELL_KNOWN_GROUP &&
+ !(modifiers & GDK_SHIFT_MASK)) {
+ /* You shouldn't normally delete "Default" or "Anonymous". */
+ set_permissions (dialog, 0);
+ } else {
+ gtk_list_store_remove (dialog->priv->list_store, &iter);
+ e2k_security_descriptor_remove_sid (dialog->priv->sd, sid);
+
+ if (!gtk_list_store_iter_is_valid (dialog->priv->list_store, &iter)) {
+ /* Select the new last row. Love that API... */
+ gtk_tree_model_iter_nth_child (model, &iter, NULL,
+ gtk_tree_model_iter_n_children (model, NULL) - 1);
+ }
+ gtk_tree_selection_select_iter (dialog->priv->list_selection, &iter);
+
+ dialog->priv->changed = TRUE;
+ }
+}
+
+static void
+setup_user_list (ExchangePermissionsDialog *dialog)
+{
+ E2kSecurityDescriptor *sd = dialog->priv->sd;
+ E2kSid *default_entry;
+ GList *sids;
+
+ /* Always put "Default" first. */
+ default_entry = e2k_security_descriptor_get_default (sd);
+ add_user_to_list (dialog, default_entry, TRUE);
+
+ sids = e2k_security_descriptor_get_sids (sd);
+ while (sids) {
+ if (sids->data != default_entry)
+ add_user_to_list (dialog, sids->data, FALSE);
+ sids = sids->next;
+ }
+ g_list_free (sids);
+}
+
+/* Role option menu functions */
+
+static void
+role_changed (GtkWidget *role_combo, gpointer user_data)
+{
+ ExchangePermissionsDialog *dialog = user_data;
+ gint role;
+
+ if (dialog->priv->frozen)
+ return;
+
+ role = gtk_combo_box_get_active (GTK_COMBO_BOX (role_combo));
+ if (role == dialog->priv->selected_role)
+ return;
+ if (role >= E2K_PERMISSIONS_ROLE_NUM_ROLES) {
+ /* The user selected "Custom". Since "Custom" will
+ * only be there to select when it's already
+ * selected, this is a no-op.
+ */
+ return;
+ }
+
+ set_permissions (dialog, e2k_permissions_role_get_perms (role));
+ display_permissions (dialog);
+}
+
+static void
+display_role (ExchangePermissionsDialog *dialog)
+{
+ gint role = dialog->priv->selected_role;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ if (!gtk_tree_selection_get_selected (dialog->priv->list_selection,
+ &model, &iter))
+ return;
+ gtk_list_store_set (dialog->priv->list_store, &iter,
+ EXCHANGE_PERMISSIONS_DIALOG_ROLE_COLUMN,
+ e2k_permissions_role_get_name (role),
+ -1);
+
+ if (role == E2K_PERMISSIONS_ROLE_CUSTOM) {
+ if (dialog->priv->custom_added == FALSE) {
+ gtk_combo_box_append_text (GTK_COMBO_BOX (dialog->priv->role_optionmenu), _("Custom"));
+ dialog->priv->custom_added = TRUE;
+ }
+ role = E2K_PERMISSIONS_ROLE_NUM_ROLES;
+ }
+ else {
+ if (dialog->priv->custom_added) {
+ gtk_combo_box_remove_text (GTK_COMBO_BOX (dialog->priv->role_optionmenu), E2K_PERMISSIONS_ROLE_NUM_ROLES);
+ dialog->priv->custom_added = FALSE;
+ }
+ }
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->priv->role_optionmenu), role);
+}
+
+/* Toggle buttons */
+static void
+check_toggled (GtkToggleButton *toggle, gpointer user_data)
+{
+ ExchangePermissionsDialog *dialog = user_data;
+ ExchangePermissionsDialogPrivate *priv = dialog->priv;
+ guint32 new_perms, value;
+
+ if (dialog->priv->frozen)
+ return;
+
+ value = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (toggle), "mapi_permission"));
+
+ if (gtk_toggle_button_get_active (toggle))
+ new_perms = priv->selected_perms | value;
+ else
+ new_perms = priv->selected_perms & ~value;
+
+ if (new_perms == priv->selected_perms)
+ return;
+
+ set_permissions (dialog, new_perms);
+ display_role (dialog);
+}
+
+static void
+radio_toggled (GtkToggleButton *toggle, gpointer user_data)
+{
+ ExchangePermissionsDialog *dialog = user_data;
+ ExchangePermissionsDialogPrivate *priv = dialog->priv;
+ guint32 new_perms, value, mask;
+
+ if (dialog->priv->frozen || !gtk_toggle_button_get_active (toggle))
+ return;
+
+ value = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (toggle), "mapi_permission"));
+ mask = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (toggle), "mapi_mask"));
+
+ new_perms = (priv->selected_perms & ~mask) | value;
+ if (new_perms == priv->selected_perms)
+ return;
+
+ set_permissions (dialog, new_perms);
+ display_role (dialog);
+}
+
+static void
+rv_toggle (GtkToggleButton *toggled, gpointer user_data)
+{
+ ExchangePermissionsDialog *dialog = user_data;
+ GtkToggleButton *visible = dialog->priv->folder_visible_check;
+ GtkToggleButton *read = dialog->priv->read_items_check;
+
+ if (dialog->priv->frozen)
+ return;
+
+ /* If you turn off "Folder visible", then "Read items" turns
+ * off too. Contrariwise, if you turn on "Read items", then
+ * "Folder visible" turns on too.
+ */
+ if (toggled == visible && !gtk_toggle_button_get_active (toggled))
+ gtk_toggle_button_set_active (read, FALSE);
+ else if (toggled == read && gtk_toggle_button_get_active (toggled))
+ gtk_toggle_button_set_active (visible, TRUE);
+}
+
+static void
+display_permissions (ExchangePermissionsDialog *dialog)
+{
+ GtkToggleButton *radio;
+ guint32 perms = dialog->priv->selected_perms;
+
+ dialog->priv->frozen = TRUE;
+
+ /* Set up check boxes */
+ gtk_toggle_button_set_active (dialog->priv->read_items_check,
+ perms & E2K_PERMISSION_READ_ANY);
+ gtk_toggle_button_set_active (dialog->priv->create_items_check,
+ perms & E2K_PERMISSION_CREATE);
+ gtk_toggle_button_set_active (dialog->priv->create_subfolders_check,
+ perms & E2K_PERMISSION_CREATE_SUBFOLDER);
+ gtk_toggle_button_set_active (dialog->priv->folder_owner_check,
+ perms & E2K_PERMISSION_OWNER);
+ gtk_toggle_button_set_active (dialog->priv->folder_contact_check,
+ (perms & E2K_PERMISSION_CONTACT) &&
+ GTK_WIDGET_SENSITIVE (dialog->priv->folder_contact_check));
+ gtk_toggle_button_set_active (dialog->priv->folder_visible_check,
+ perms & E2K_PERMISSION_FOLDER_VISIBLE);
+
+ /* Set up radio buttons */
+ if (perms & E2K_PERMISSION_EDIT_ANY)
+ radio = dialog->priv->edit_all_radio;
+ else if (perms & E2K_PERMISSION_EDIT_OWNED)
+ radio = dialog->priv->edit_own_radio;
+ else
+ radio = dialog->priv->edit_none_radio;
+ gtk_toggle_button_set_active (radio, TRUE);
+
+ if (perms & E2K_PERMISSION_DELETE_ANY)
+ radio = dialog->priv->delete_all_radio;
+ else if (perms & E2K_PERMISSION_DELETE_OWNED)
+ radio = dialog->priv->delete_own_radio;
+ else
+ radio = dialog->priv->delete_none_radio;
+ gtk_toggle_button_set_active (radio, TRUE);
+
+ /* And role menu */
+ display_role (dialog);
+
+ dialog->priv->frozen = FALSE;
+}
+
+static GtkWidget *
+exchange_permissions_role_optionmenu_new (void)
+{
+ GtkWidget *menu;
+ const gchar **roles;
+ gint role;
+
+ menu = gtk_combo_box_new_text ();
+ roles = g_new (const gchar *, E2K_PERMISSIONS_ROLE_NUM_ROLES + 1);
+ for (role = 0; role < E2K_PERMISSIONS_ROLE_NUM_ROLES; role++) {
+ roles[role] = e2k_permissions_role_get_name (role);
+ gtk_combo_box_append_text (GTK_COMBO_BOX (menu), roles[role]);
+ }
+
+ roles[role] = NULL;
+
+ g_free (roles);
+
+ gtk_widget_show (menu);
+ return menu;
+}
+
+static GtkWidget *
+create_permissions_vbox (ExchangePermissionsDialog *dialog)
+{
+ GtkWidget *permissions_vbox;
+ GtkWidget *hbox1;
+ GtkWidget *scrolledwindow1;
+ GtkWidget *list_view;
+ GtkWidget *vbuttonbox1;
+ GtkWidget *add_button;
+ GtkWidget *remove_button;
+ GtkWidget *table2;
+ GtkWidget *label6;
+ GtkWidget *label7;
+ GtkWidget *label3;
+ GtkWidget *hbox3;
+ GtkWidget *label4;
+ GtkWidget *role_optionmenu;
+ GtkWidget *hbox2;
+ GtkWidget *vbox6;
+ GtkWidget *vbox8;
+ GtkWidget *create_items_check;
+ GtkWidget *read_items_check;
+ GtkWidget *create_subfolders_check;
+ GtkWidget *vbox9;
+ GtkWidget *edit_none_radio;
+ GSList *edit_none_radio_group = NULL;
+ GtkWidget *edit_own_radio;
+ GtkWidget *edit_all_radio;
+ GtkWidget *vbox7;
+ GtkWidget *vbox10;
+ GtkWidget *folder_owner_check;
+ GtkWidget *folder_contact_check;
+ GtkWidget *folder_visible_check;
+ GtkWidget *vbox11;
+ GtkWidget *delete_none_radio;
+ GSList *delete_none_radio_group = NULL;
+ GtkWidget *delete_own_radio;
+ GtkWidget *delete_all_radio;
+ gchar *tmp_str;
+ GtkTreeViewColumn *column;
+
+ permissions_vbox = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (permissions_vbox);
+ gtk_container_set_border_width (GTK_CONTAINER (permissions_vbox), 6);
+
+ hbox1 = gtk_hbox_new (FALSE, 6);
+ gtk_widget_show (hbox1);
+ gtk_box_pack_start (GTK_BOX (permissions_vbox), hbox1, TRUE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox1), 6);
+
+ scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_show (scrolledwindow1);
+ gtk_box_pack_start (GTK_BOX (hbox1), scrolledwindow1, TRUE, TRUE, 0);
+ GTK_WIDGET_UNSET_FLAGS (scrolledwindow1, GTK_CAN_FOCUS);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_SHADOW_IN);
+
+ list_view = gtk_tree_view_new ();
+ gtk_widget_show (list_view);
+ gtk_container_add (GTK_CONTAINER (scrolledwindow1), list_view);
+
+ vbuttonbox1 = gtk_vbutton_box_new ();
+ gtk_widget_show (vbuttonbox1);
+ gtk_box_pack_start (GTK_BOX (hbox1), vbuttonbox1, FALSE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (vbuttonbox1), 4);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (vbuttonbox1), GTK_BUTTONBOX_SPREAD);
+ gtk_box_set_spacing (GTK_BOX (vbuttonbox1), 10);
+
+ add_button = gtk_button_new_from_stock ("gtk-add");
+ gtk_widget_show (add_button);
+ gtk_container_add (GTK_CONTAINER (vbuttonbox1), add_button);
+ GTK_WIDGET_SET_FLAGS (add_button, GTK_CAN_DEFAULT);
+
+ remove_button = gtk_button_new_from_stock ("gtk-remove");
+ gtk_widget_show (remove_button);
+ gtk_container_add (GTK_CONTAINER (vbuttonbox1), remove_button);
+ GTK_WIDGET_SET_FLAGS (remove_button, GTK_CAN_DEFAULT);
+
+ table2 = gtk_table_new (3, 2, FALSE);
+ gtk_widget_show (table2);
+ gtk_box_pack_start (GTK_BOX (permissions_vbox), table2, FALSE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (table2), 6);
+ gtk_table_set_row_spacings (GTK_TABLE (table2), 6);
+
+ label6 = gtk_label_new (" ");
+ gtk_widget_show (label6);
+ gtk_table_attach (GTK_TABLE (table2), label6, 0, 1, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label6), 0, 0.5);
+
+ label7 = gtk_label_new (" ");
+ gtk_widget_show (label7);
+ gtk_table_attach (GTK_TABLE (table2), label7, 0, 1, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (label7), 0, 0.5);
+
+ tmp_str = g_strconcat ("<b>", _("Permissions"), "</b>", NULL);
+ label3 = gtk_label_new (tmp_str);
+ g_free (tmp_str);
+ gtk_widget_show (label3);
+ gtk_table_attach (GTK_TABLE (table2), label3, 0, 2, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_label_set_use_markup (GTK_LABEL (label3), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label3), 0, 0.5);
+
+ hbox3 = gtk_hbox_new (FALSE, 6);
+ gtk_widget_show (hbox3);
+ gtk_table_attach (GTK_TABLE (table2), hbox3, 1, 2, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox3), 6);
+
+ label4 = gtk_label_new (_("Role: "));
+ gtk_widget_show (label4);
+ gtk_box_pack_start (GTK_BOX (hbox3), label4, FALSE, FALSE, 0);
+ gtk_label_set_justify (GTK_LABEL (label4), GTK_JUSTIFY_CENTER);
+
+ role_optionmenu = exchange_permissions_role_optionmenu_new ();
+ gtk_widget_show (role_optionmenu);
+ gtk_box_pack_start (GTK_BOX (hbox3), role_optionmenu, TRUE, TRUE, 0);
+ GTK_WIDGET_UNSET_FLAGS (role_optionmenu, GTK_CAN_FOCUS);
+ GTK_WIDGET_UNSET_FLAGS (role_optionmenu, GTK_CAN_DEFAULT);
+
+ hbox2 = gtk_hbox_new (TRUE, 6);
+ gtk_widget_show (hbox2);
+ gtk_table_attach (GTK_TABLE (table2), hbox2, 1, 2, 2, 3,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox2), 6);
+
+ vbox6 = gtk_vbox_new (FALSE, 12);
+ gtk_widget_show (vbox6);
+ gtk_box_pack_start (GTK_BOX (hbox2), vbox6, TRUE, TRUE, 0);
+
+ vbox8 = gtk_vbox_new (FALSE, 6);
+ gtk_widget_show (vbox8);
+ gtk_box_pack_start (GTK_BOX (vbox6), vbox8, TRUE, TRUE, 0);
+
+ create_items_check = gtk_check_button_new_with_mnemonic (_("Create items"));
+ gtk_widget_show (create_items_check);
+ gtk_box_pack_start (GTK_BOX (vbox8), create_items_check, FALSE, FALSE, 0);
+
+ read_items_check = gtk_check_button_new_with_mnemonic (_("Read items"));
+ gtk_widget_show (read_items_check);
+ gtk_box_pack_start (GTK_BOX (vbox8), read_items_check, FALSE, FALSE, 0);
+
+ create_subfolders_check = gtk_check_button_new_with_mnemonic (_("Create subfolders"));
+ gtk_widget_show (create_subfolders_check);
+ gtk_box_pack_start (GTK_BOX (vbox8), create_subfolders_check, FALSE, FALSE, 0);
+
+ vbox9 = gtk_vbox_new (FALSE, 6);
+ gtk_widget_show (vbox9);
+ gtk_box_pack_start (GTK_BOX (vbox6), vbox9, TRUE, TRUE, 0);
+
+ edit_none_radio = gtk_radio_button_new_with_mnemonic (NULL, _("Cannot Edit"));
+ gtk_widget_show (edit_none_radio);
+ gtk_box_pack_start (GTK_BOX (vbox9), edit_none_radio, FALSE, FALSE, 0);
+ gtk_radio_button_set_group (GTK_RADIO_BUTTON (edit_none_radio), edit_none_radio_group);
+ edit_none_radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (edit_none_radio));
+
+ edit_own_radio = gtk_radio_button_new_with_mnemonic (NULL, _("Edit Own Items"));
+ gtk_widget_show (edit_own_radio);
+ gtk_box_pack_start (GTK_BOX (vbox9), edit_own_radio, FALSE, FALSE, 0);
+ gtk_radio_button_set_group (GTK_RADIO_BUTTON (edit_own_radio), edit_none_radio_group);
+ edit_none_radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (edit_own_radio));
+
+ edit_all_radio = gtk_radio_button_new_with_mnemonic (NULL, _("Edit Any Items"));
+ gtk_widget_show (edit_all_radio);
+ gtk_box_pack_start (GTK_BOX (vbox9), edit_all_radio, FALSE, FALSE, 0);
+ gtk_radio_button_set_group (GTK_RADIO_BUTTON (edit_all_radio), edit_none_radio_group);
+ edit_none_radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (edit_all_radio));
+
+ vbox7 = gtk_vbox_new (FALSE, 12);
+ gtk_widget_show (vbox7);
+ gtk_box_pack_start (GTK_BOX (hbox2), vbox7, TRUE, TRUE, 0);
+
+ vbox10 = gtk_vbox_new (FALSE, 6);
+ gtk_widget_show (vbox10);
+ gtk_box_pack_start (GTK_BOX (vbox7), vbox10, TRUE, TRUE, 0);
+
+ folder_owner_check = gtk_check_button_new_with_mnemonic (_("Folder owner"));
+ gtk_widget_show (folder_owner_check);
+ gtk_box_pack_start (GTK_BOX (vbox10), folder_owner_check, FALSE, FALSE, 0);
+
+ folder_contact_check = gtk_check_button_new_with_mnemonic (_("Folder contact"));
+ gtk_widget_show (folder_contact_check);
+ gtk_box_pack_start (GTK_BOX (vbox10), folder_contact_check, FALSE, FALSE, 0);
+
+ folder_visible_check = gtk_check_button_new_with_mnemonic (_("Folder visible"));
+ gtk_widget_show (folder_visible_check);
+ gtk_box_pack_start (GTK_BOX (vbox10), folder_visible_check, FALSE, FALSE, 0);
+
+ vbox11 = gtk_vbox_new (FALSE, 6);
+ gtk_widget_show (vbox11);
+ gtk_box_pack_start (GTK_BOX (vbox7), vbox11, TRUE, TRUE, 0);
+
+ delete_none_radio = gtk_radio_button_new_with_mnemonic (NULL, _("Cannot Delete"));
+ gtk_widget_show (delete_none_radio);
+ gtk_box_pack_start (GTK_BOX (vbox11), delete_none_radio, FALSE, FALSE, 0);
+ gtk_radio_button_set_group (GTK_RADIO_BUTTON (delete_none_radio), delete_none_radio_group);
+ delete_none_radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (delete_none_radio));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (delete_none_radio), TRUE);
+
+ delete_own_radio = gtk_radio_button_new_with_mnemonic (NULL, _("Delete Own Items"));
+ gtk_widget_show (delete_own_radio);
+ gtk_box_pack_start (GTK_BOX (vbox11), delete_own_radio, FALSE, FALSE, 0);
+ gtk_radio_button_set_group (GTK_RADIO_BUTTON (delete_own_radio), delete_none_radio_group);
+ delete_none_radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (delete_own_radio));
+
+ delete_all_radio = gtk_radio_button_new_with_mnemonic (NULL, _("Delete Any Items"));
+ gtk_widget_show (delete_all_radio);
+ gtk_box_pack_start (GTK_BOX (vbox11), delete_all_radio, FALSE, FALSE, 0);
+ gtk_radio_button_set_group (GTK_RADIO_BUTTON (delete_all_radio), delete_none_radio_group);
+ delete_none_radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (delete_all_radio));
+
+#define GET_WIDGET(name, type) dialog->priv->name = type (name)
+
+ GET_WIDGET (list_view, GTK_TREE_VIEW);
+ column = gtk_tree_view_column_new_with_attributes (
+ _("Name"), gtk_cell_renderer_text_new (),
+ "text", EXCHANGE_PERMISSIONS_DIALOG_NAME_COLUMN, NULL);
+ gtk_tree_view_append_column (dialog->priv->list_view, column);
+ column = gtk_tree_view_column_new_with_attributes (
+ _("Role"), gtk_cell_renderer_text_new (),
+ "text", EXCHANGE_PERMISSIONS_DIALOG_ROLE_COLUMN, NULL);
+ gtk_tree_view_append_column (dialog->priv->list_view, column);
+
+ dialog->priv->list_selection = gtk_tree_view_get_selection (dialog->priv->list_view);
+ gtk_tree_selection_set_mode (dialog->priv->list_selection,
+ GTK_SELECTION_SINGLE);
+ g_signal_connect (dialog->priv->list_selection, "changed",
+ G_CALLBACK (list_view_selection_changed), dialog);
+
+ dialog->priv->list_store = gtk_list_store_new (
+ EXCHANGE_PERMISSIONS_DIALOG_NUM_COLUMNS,
+ G_TYPE_STRING, G_TYPE_STRING, E2K_TYPE_SID);
+ gtk_tree_view_set_model (dialog->priv->list_view,
+ GTK_TREE_MODEL (dialog->priv->list_store));
+
+ g_signal_connect (add_button, "clicked",
+ G_CALLBACK (add_clicked), dialog);
+ g_signal_connect (remove_button, "clicked",
+ G_CALLBACK (remove_clicked), dialog);
+
+ GET_WIDGET (role_optionmenu, GTK_COMBO_BOX);
+ g_signal_connect (dialog->priv->role_optionmenu, "changed",
+ G_CALLBACK (role_changed), dialog);
+
+ dialog->priv->custom_added = FALSE;
+
+#define GET_TOGGLE(name, value, callback) \
+ GET_WIDGET (name, GTK_TOGGLE_BUTTON); \
+ g_object_set_data (G_OBJECT (dialog->priv->name), \
+ "mapi_permission", \
+ GUINT_TO_POINTER (value)); \
+ g_signal_connect (dialog->priv->name, "toggled", \
+ G_CALLBACK (callback), dialog)
+
+#define GET_CHECK(name, value) \
+ GET_TOGGLE (name, value, check_toggled)
+
+#define GET_RADIO(name, value, mask) \
+ GET_TOGGLE (name, value, radio_toggled); \
+ g_object_set_data (G_OBJECT (dialog->priv->name), \
+ "mapi_mask", \
+ GUINT_TO_POINTER (mask))
+
+ GET_CHECK (read_items_check, E2K_PERMISSION_READ_ANY);
+ GET_CHECK (create_items_check, E2K_PERMISSION_CREATE);
+ GET_RADIO (edit_none_radio, 0, E2K_PERMISSION_EDIT_MASK);
+ GET_RADIO (delete_none_radio, 0, E2K_PERMISSION_DELETE_MASK);
+ GET_RADIO (edit_own_radio, E2K_PERMISSION_EDIT_OWNED, E2K_PERMISSION_EDIT_MASK);
+ GET_RADIO (delete_own_radio, E2K_PERMISSION_DELETE_OWNED, E2K_PERMISSION_DELETE_MASK);
+ GET_RADIO (edit_all_radio, (E2K_PERMISSION_EDIT_ANY | E2K_PERMISSION_EDIT_OWNED), E2K_PERMISSION_EDIT_MASK);
+ GET_RADIO (delete_all_radio, (E2K_PERMISSION_DELETE_ANY | E2K_PERMISSION_DELETE_OWNED), E2K_PERMISSION_DELETE_MASK);
+ GET_CHECK (create_subfolders_check, E2K_PERMISSION_CREATE_SUBFOLDER);
+ GET_CHECK (folder_owner_check, E2K_PERMISSION_OWNER);
+ GET_CHECK (folder_contact_check, E2K_PERMISSION_CONTACT);
+ GET_CHECK (folder_visible_check, E2K_PERMISSION_FOLDER_VISIBLE);
+
+ g_signal_connect (dialog->priv->folder_visible_check,
+ "toggled", G_CALLBACK (rv_toggle), dialog);
+ g_signal_connect (dialog->priv->read_items_check,
+ "toggled", G_CALLBACK (rv_toggle), dialog);
+
+ return permissions_vbox;
+}
diff --git a/eplugin/exchange-permissions-dialog.h b/eplugin/exchange-permissions-dialog.h
new file mode 100644
index 0000000..ad2f47d
--- /dev/null
+++ b/eplugin/exchange-permissions-dialog.h
@@ -0,0 +1,56 @@
+/*
+ * 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:
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __EXCHANGE_PERMISSIONS_DIALOG_H__
+#define __EXCHANGE_PERMISSIONS_DIALOG_H__
+
+#include <gtk/gtk.h>
+#include "e-folder.h"
+#include "exchange-types.h"
+
+G_BEGIN_DECLS
+
+#define EXCHANGE_TYPE_PERMISSIONS_DIALOG (exchange_permissions_dialog_get_type ())
+#define EXCHANGE_PERMISSIONS_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXCHANGE_TYPE_PERMISSIONS_DIALOG, ExchangePermissionsDialog))
+#define EXCHANGE_PERMISSIONS_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EXCHANGE_TYPE_PERMISSIONS_DIALOG, ExchangePermissionsDialogClass))
+#define EXCHANGE_IS_PERMISSIONS_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXCHANGE_TYPE_PERMISSIONS_DIALOG))
+#define EXCHANGE_IS_PERMISSIONS_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EXCHANGE_TYPE_PERMISSIONS_DIALOG))
+
+struct _ExchangePermissionsDialog {
+ GtkDialog parent;
+
+ ExchangePermissionsDialogPrivate *priv;
+};
+
+struct _ExchangePermissionsDialogClass {
+ GtkDialogClass parent_class;
+
+};
+
+GType exchange_permissions_dialog_get_type (void);
+
+void exchange_permissions_dialog_new (ExchangeAccount *account,
+ EFolder *folder,
+ GtkWidget *parent);
+
+G_END_DECLS
+
+#endif /* __EXCHANGE_PERMISSIONS_DIALOG_H__ */
diff --git a/eplugin/exchange-send-options.c b/eplugin/exchange-send-options.c
new file mode 100644
index 0000000..0b8722b
--- /dev/null
+++ b/eplugin/exchange-send-options.c
@@ -0,0 +1,621 @@
+/*
+ * 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:
+ * R.Raghavendran <raghavguru7 gmail com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <libedataserverui/e-name-selector.h>
+#include <libedataserverui/e-contact-store.h>
+#include "exchange-operations.h"
+#include <e-util/e-util.h>
+#include <e-util/e-error.h>
+
+#include "exchange-send-options.h"
+
+struct _ExchangeSendOptionsDialogPrivate {
+ /*Widgets*/
+ GtkWidget *main;
+
+ /*name selector dialog*/
+ ENameSelector *proxy_name_selector;
+
+ /*Importance*/
+ GtkWidget *importance;
+
+ /*Sensitivity*/
+ GtkWidget *sensitivity;
+
+ /*Send_as_delegate_enabled*/
+ GtkWidget *delegate_enabled;
+
+ /*Read Receipt*/
+ GtkWidget *read_receipt;
+
+ /*Delivery Receipt*/
+ GtkWidget *delivery_receipt;
+
+ /*User button*/
+ GtkWidget *button_user;
+
+ /*Label Widgets*/
+ GtkWidget *importance_label;
+ GtkWidget *sensitivity_label;
+ gchar *help_section;
+};
+
+static void exchange_sendoptions_dialog_class_init (GObjectClass *object_class);
+static void exchange_sendoptions_dialog_finalize (GObject *object);
+static void exchange_sendoptions_dialog_init (GObject *object);
+static void exchange_sendoptions_dialog_dispose (GObject *object);
+
+static GObjectClass *parent_class = NULL;
+enum {
+ SOD_RESPONSE,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+/* exchange_send_options_get_widgets_data(ExchangeSendOptionsDialog *sod)
+ Return Value:This function returns a -1 if an error occurs. In case of error-free operation a 1 is returned.
+*/
+static gint
+exchange_send_options_get_widgets_data (ExchangeSendOptionsDialog *sod)
+{
+ ExchangeSendOptionsDialogPrivate *priv;
+ ExchangeSendOptions *options;
+ const gchar *address, *email, *name;
+
+ guint count=0;
+ ENameSelectorEntry *name_selector_entry;
+ EDestinationStore *destination_store;
+ GList *destinations, *tmp;
+
+ priv = sod->priv;
+ options = sod->options;
+
+ /* This block helps us fetch the address of the delegator(s). If no delegator is selected or more
+ than one delegatee has been selected then an info dialog is popped up to help the user.
+ */
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->delegate_enabled))) {
+
+ name_selector_entry = e_name_selector_peek_section_entry (priv->proxy_name_selector, "Add User");
+ destination_store = e_name_selector_entry_peek_destination_store (E_NAME_SELECTOR_ENTRY (name_selector_entry));
+ destinations = e_destination_store_list_destinations (destination_store);
+ tmp = destinations;
+
+ email = NULL;
+
+ /* The temporary variables address, email, and name are needed to fetch the list items.
+ Only the valid one is then copied into the storage variables. The "count" variable
+ helps us keep a count of the exact number of items in the list. The g_list_length(GList *)
+ produced ambiguous results. Hence count is used :)
+ */
+ for (; tmp != NULL; tmp = g_list_next (tmp)) {
+ address = g_strdup ((gchar *) e_destination_get_address (tmp->data));
+ email = g_strdup ((gchar *) e_destination_get_email (tmp->data));
+ name = g_strdup (e_destination_get_name (tmp->data));
+ if (g_str_equal (email, ""))
+ continue;
+ count++;
+
+ options->delegate_address = address;
+ options->delegate_name = name;
+ options->delegate_email = email;
+ }
+
+ if (count == 0) {
+ e_error_run ((GtkWindow *) priv->main,
+ "org-gnome-exchange-operations:no-delegate-selected", NULL, NULL);
+ gtk_widget_grab_focus ((GtkWidget *) name_selector_entry);
+ options->delegate_address = NULL;
+ options->delegate_name = NULL;
+ options->delegate_email = NULL;
+ return -1;
+ }
+
+ if (count > 1) {
+ e_error_run ((GtkWindow *)priv->main,
+ "org-gnome-exchange-operations:more-delegates-selected", NULL, NULL);
+ gtk_widget_grab_focus ((GtkWidget *) name_selector_entry);
+ options->delegate_address = NULL;
+ options->delegate_name = NULL;
+ options->delegate_email = NULL;
+ return -1;
+ }
+ }
+
+ options->importance = gtk_combo_box_get_active ((GtkComboBox *)priv->importance);
+ options->sensitivity = gtk_combo_box_get_active ((GtkComboBox *)priv->sensitivity);
+
+ options->send_as_del_enabled = gtk_toggle_button_get_active (
+ GTK_TOGGLE_BUTTON (priv->delegate_enabled));
+
+ options->delivery_enabled = gtk_toggle_button_get_active (
+ GTK_TOGGLE_BUTTON (priv->delivery_receipt));
+
+ options->read_enabled = gtk_toggle_button_get_active (
+ GTK_TOGGLE_BUTTON (priv->read_receipt));
+
+ return 1;
+}
+
+static void
+exchange_send_options_fill_widgets_with_data (ExchangeSendOptionsDialog *sod)
+{
+ ExchangeSendOptionsDialogPrivate *priv;
+ ExchangeSendOptions *options;
+ ENameSelectorEntry *name_selector_entry;
+
+ priv = sod->priv;
+ options = sod->options;
+
+ priv->help_section = g_strdup ("usage-mail");
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (priv->importance_label), priv->importance);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (priv->sensitivity_label), priv->sensitivity);
+
+ gtk_combo_box_set_active ((GtkComboBox *) priv->importance, options->importance);
+ gtk_combo_box_set_active ((GtkComboBox *) priv->sensitivity, options->sensitivity);
+
+ name_selector_entry = e_name_selector_peek_section_entry (priv->proxy_name_selector, "Add User");
+
+ if (options->send_as_del_enabled) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->delegate_enabled), TRUE);
+ gtk_widget_set_sensitive ((GtkWidget *)name_selector_entry, TRUE);
+ gtk_widget_set_sensitive ((GtkWidget *)priv->button_user, TRUE);
+ }
+
+ else {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->delegate_enabled), FALSE);
+ gtk_widget_set_sensitive ((GtkWidget *)name_selector_entry, FALSE);
+ gtk_widget_set_sensitive ((GtkWidget *)priv->button_user, FALSE);
+ }
+
+ if (options->read_enabled)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->read_receipt), TRUE);
+ else
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->read_receipt), FALSE);
+
+ if (options->delivery_enabled)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->delivery_receipt), TRUE);
+ else
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->delivery_receipt), FALSE);
+}
+
+ExchangeSendOptionsDialog *
+exchange_sendoptions_dialog_new (void) {
+ ExchangeSendOptionsDialog *sod;
+
+ sod = g_object_new (EXCHANGE_TYPE_SENDOPTIONS_DIALOG, NULL);
+
+ return sod;
+}
+
+GType exchange_sendoptions_dialog_get_type (void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info = {
+ sizeof (ExchangeSendOptionsDialogClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) exchange_sendoptions_dialog_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (ExchangeSendOptionsDialog),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) exchange_sendoptions_dialog_init,
+ NULL /* instance_init */
+ };
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "ExchangeSendOptionsDialogType",
+ &info, 0);
+ }
+ return type;
+}
+
+static void exchange_send_options_cb (GtkDialog *dialog, gint state, gpointer func_data)
+{
+ ExchangeSendOptionsDialogPrivate *priv;
+ ExchangeSendOptionsDialog *sod;
+
+ sod = func_data;
+ priv = sod->priv;
+
+ switch (state) {
+ case GTK_RESPONSE_OK:
+ if (exchange_send_options_get_widgets_data (sod) < 0)
+ return;
+ case GTK_RESPONSE_CANCEL:
+ gtk_widget_hide (priv->main);
+ gtk_widget_destroy (priv->main);
+ break;
+ case GTK_RESPONSE_HELP:
+ e_display_help (
+ GTK_WINDOW (priv->main),
+ priv->help_section);
+ break;
+ }
+ g_signal_emit (G_OBJECT (func_data), signals[SOD_RESPONSE], 0, state);
+
+}
+
+/* This function acts as a listener for the toggling of "send_as_a_delegate" button. This is needed to
+ sensitize the name_selector_entry and the User Button
+*/
+static void
+delegate_option_toggled (GtkCheckButton *button, gpointer func_data)
+{
+ ExchangeSendOptionsDialogPrivate *priv;
+ ExchangeSendOptionsDialog *sod;
+ ENameSelectorEntry *name_selector_entry;
+ ExchangeSendOptions *options;
+
+ sod=func_data;
+ priv=sod->priv;
+ options=sod->options;
+
+ name_selector_entry = e_name_selector_peek_section_entry (priv->proxy_name_selector, "Add User");
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->delegate_enabled))) {
+ gtk_widget_set_sensitive ((GtkWidget *) name_selector_entry, TRUE);
+ gtk_widget_set_sensitive ((GtkWidget *) priv->button_user, TRUE);
+ }
+
+ else {
+ gtk_widget_set_sensitive ((GtkWidget *) name_selector_entry, FALSE);
+ gtk_widget_set_sensitive ((GtkWidget *) priv->button_user, FALSE);
+ }
+
+}
+
+static void
+addressbook_dialog_response (ENameSelectorDialog *name_selector_dialog, gint response, gpointer user_data)
+{
+ gtk_widget_hide (GTK_WIDGET (name_selector_dialog));
+}
+
+static void
+addressbook_entry_changed (GtkWidget *entry, gpointer user_data)
+{
+}
+
+/* This function invokes the name selector dialog
+*/
+static void
+address_button_clicked (GtkButton *button, gpointer func_data)
+{
+
+ ExchangeSendOptionsDialogPrivate *priv;
+ ExchangeSendOptionsDialog *sod;
+ ENameSelectorDialog *name_selector_dialog;
+
+ sod=func_data;
+ priv=sod->priv;
+
+ name_selector_dialog = e_name_selector_peek_dialog (priv->proxy_name_selector);
+ gtk_widget_show (GTK_WIDGET (name_selector_dialog));
+}
+
+gboolean
+exchange_sendoptions_dialog_run (ExchangeSendOptionsDialog *sod, GtkWidget *parent)
+{
+ ExchangeSendOptionsDialogPrivate *priv;
+ ExchangeSendOptions *options;
+
+ EDestinationStore *destination_store;
+ ENameSelectorDialog *name_selector_dialog;
+ ENameSelectorModel *name_selector_model;
+ ENameSelectorEntry *name_selector_entry;
+ EDestination *des;
+ GtkWidget *send_options;
+ GtkWidget *send_options_vbox;
+ GtkWidget *options_vbox;
+ GtkWidget *message_settings_vbox;
+ GtkWidget *msg_settings_label;
+ GtkWidget *msg_settings_table;
+ GtkWidget *importance_label;
+ GtkWidget *sensitivity_label;
+ GtkWidget *sensitivity_combo_box;
+ GtkWidget *imp_combo_box;
+ GtkWidget *del_enabled_check;
+ GtkWidget *hbox1;
+ GtkWidget *hbox2;
+ GtkWidget *del_name_box;
+ GtkWidget *button_user;
+ GtkWidget *track_option_vbox;
+ GtkWidget *track_options_label;
+ GtkWidget *delivery_check_button;
+ GtkWidget *read_check_button;
+ gchar *tmp_str;
+
+ g_return_val_if_fail (sod != NULL || EXCHANGE_IS_SENDOPTIONS_DIALOG (sod), FALSE);
+
+ priv = sod->priv;
+ options = sod->options;
+
+ send_options = gtk_dialog_new_with_buttons (
+ _("Exchange - Send Options"),
+ NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
+ GTK_STOCK_HELP, GTK_RESPONSE_HELP,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+ gtk_window_set_type_hint (GTK_WINDOW (send_options), GDK_WINDOW_TYPE_HINT_DIALOG);
+
+ send_options_vbox = gtk_dialog_get_content_area (GTK_DIALOG (send_options));
+ gtk_widget_show (send_options_vbox);
+
+ options_vbox = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (options_vbox);
+ gtk_box_pack_start (GTK_BOX (send_options_vbox), options_vbox, TRUE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (options_vbox), 6);
+
+ message_settings_vbox = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (message_settings_vbox);
+ gtk_box_pack_start (GTK_BOX (options_vbox), message_settings_vbox, FALSE, FALSE, 0);
+
+ tmp_str = g_strconcat ("<b>", _("Message Settings"), "</b>", NULL);
+ msg_settings_label = gtk_label_new (tmp_str);
+ g_free (tmp_str);
+ gtk_widget_show (msg_settings_label);
+ gtk_box_pack_start (GTK_BOX (message_settings_vbox), msg_settings_label, FALSE, FALSE, 0);
+ gtk_label_set_use_markup (GTK_LABEL (msg_settings_label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (msg_settings_label), 0, 0.49);
+
+ msg_settings_table = gtk_table_new (2, 2, FALSE);
+ gtk_widget_show (msg_settings_table);
+ gtk_box_pack_start (GTK_BOX (message_settings_vbox), msg_settings_table, FALSE, FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (msg_settings_table), 6);
+ gtk_table_set_row_spacings (GTK_TABLE (msg_settings_table), 6);
+
+ importance_label = gtk_label_new_with_mnemonic (_("I_mportance: "));
+ gtk_widget_show (importance_label);
+ gtk_table_attach (GTK_TABLE (msg_settings_table), importance_label, 0, 1, 0, 1,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (importance_label), 0, 0.49);
+
+ sensitivity_label = gtk_label_new_with_mnemonic (_("_Sensitivity: "));
+ gtk_widget_show (sensitivity_label);
+ gtk_table_attach (GTK_TABLE (msg_settings_table), sensitivity_label, 0, 1, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (0), 0, 0);
+ gtk_misc_set_alignment (GTK_MISC (sensitivity_label), 0, 0.5);
+
+ sensitivity_combo_box = gtk_combo_box_new_text ();
+ gtk_widget_show (sensitivity_combo_box);
+ gtk_table_attach (GTK_TABLE (msg_settings_table), sensitivity_combo_box, 1, 2, 1, 2,
+ (GtkAttachOptions) (GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ gtk_combo_box_append_text (GTK_COMBO_BOX (sensitivity_combo_box), _("Normal"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (sensitivity_combo_box), _("Personal"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (sensitivity_combo_box), _("Private"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (sensitivity_combo_box), _("Confidential"));
+
+ imp_combo_box = gtk_combo_box_new_text ();
+ gtk_widget_show (imp_combo_box);
+ gtk_table_attach (GTK_TABLE (msg_settings_table), imp_combo_box, 1, 2, 0, 1,
+ (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+ (GtkAttachOptions) (GTK_FILL), 0, 0);
+ gtk_combo_box_append_text (GTK_COMBO_BOX (imp_combo_box), _("Normal"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (imp_combo_box), _("High"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (imp_combo_box), _("Low"));
+
+ del_enabled_check = gtk_check_button_new_with_mnemonic (_("Send as Delegate"));
+ gtk_widget_show (del_enabled_check);
+ gtk_box_pack_start (GTK_BOX (options_vbox), del_enabled_check, FALSE, FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (del_enabled_check), 6);
+
+ hbox1 = gtk_hbox_new (FALSE, 0);
+ gtk_widget_show (hbox1);
+ gtk_box_pack_start (GTK_BOX (options_vbox), hbox1, TRUE, TRUE, 0);
+
+ hbox2 = gtk_hbox_new (FALSE, 0);
+ gtk_widget_show (hbox2);
+ gtk_box_pack_start (GTK_BOX (hbox1), hbox2, TRUE, TRUE, 0);
+
+ del_name_box = gtk_hbox_new (FALSE, 0);
+ gtk_widget_show (del_name_box);
+ gtk_box_pack_start (GTK_BOX (hbox2), del_name_box, TRUE, TRUE, 0);
+
+ button_user = gtk_button_new_with_mnemonic (_("_User"));
+ gtk_widget_show (button_user);
+ gtk_box_pack_start (GTK_BOX (hbox1), button_user, FALSE, FALSE, 0);
+
+ track_option_vbox = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (track_option_vbox);
+ gtk_box_pack_start (GTK_BOX (options_vbox), track_option_vbox, TRUE, TRUE, 0);
+
+ tmp_str = g_strconcat ("<b>", _("Tracking Options"), "</b>", NULL);
+ track_options_label = gtk_label_new (tmp_str);
+ g_free (tmp_str);
+ gtk_widget_show (track_options_label);
+ gtk_box_pack_start (GTK_BOX (track_option_vbox), track_options_label, FALSE, FALSE, 6);
+ gtk_label_set_use_markup (GTK_LABEL (track_options_label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (track_options_label), 0, 0.5);
+
+ delivery_check_button = gtk_check_button_new_with_mnemonic (_("Request a _delivery receipt for this message"));
+ gtk_widget_show (delivery_check_button);
+ gtk_box_pack_start (GTK_BOX (track_option_vbox), delivery_check_button, FALSE, FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (delivery_check_button), 6);
+
+ read_check_button = gtk_check_button_new_with_mnemonic (_("Request a _read receipt for this message"));
+ gtk_widget_show (read_check_button);
+ gtk_box_pack_start (GTK_BOX (track_option_vbox), read_check_button, FALSE, FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (read_check_button), 6);
+
+ priv->main = send_options;
+ priv->importance = imp_combo_box;
+ priv->sensitivity = sensitivity_combo_box;
+ priv->button_user = button_user;
+ priv->delegate_enabled = del_enabled_check;
+ priv->read_receipt = read_check_button;
+ priv->delivery_receipt = delivery_check_button;
+ priv->importance_label = importance_label;
+ priv->sensitivity_label = sensitivity_label;
+
+ send_options = gtk_widget_get_toplevel (priv->main);
+ if (parent)
+ gtk_window_set_transient_for (GTK_WINDOW (send_options),
+ GTK_WINDOW (parent));
+
+ priv->proxy_name_selector = e_name_selector_new ();
+ name_selector_dialog = e_name_selector_peek_dialog (priv->proxy_name_selector);
+
+ name_selector_model = e_name_selector_peek_model (priv->proxy_name_selector);
+ e_name_selector_model_add_section (name_selector_model, "Add User", _("Add User"), NULL);
+
+ exchange_send_options_fill_widgets_with_data (sod);
+
+ if (options->delegate_address) {
+ e_name_selector_model_peek_section (name_selector_model, "Add User", NULL, &destination_store);
+ des = e_destination_new ();
+ e_destination_set_email (des, options->delegate_email);
+ e_destination_set_name (des, options->delegate_name);
+ e_destination_store_append_destination (destination_store, des);
+ g_object_unref (des);
+ }
+
+ g_signal_connect ((GtkButton *) priv->button_user, "clicked",
+ G_CALLBACK (address_button_clicked), sod);
+ g_signal_connect (name_selector_dialog, "response",
+ G_CALLBACK (addressbook_dialog_response), sod);
+ g_signal_connect (GTK_DIALOG (priv->main), "response",
+ G_CALLBACK(exchange_send_options_cb), sod);
+ g_signal_connect ((GtkCheckButton *) priv->delegate_enabled, "toggled",
+ G_CALLBACK(delegate_option_toggled), sod);
+
+ name_selector_entry = e_name_selector_peek_section_entry (priv->proxy_name_selector,
+ "Add User");
+ g_signal_connect (name_selector_entry, "changed", G_CALLBACK (addressbook_entry_changed), sod);
+
+ /* The name box is just a container. The name_selector_entry is added to it. This Widget
+ is created dynamically*/
+ gtk_container_add ((GtkContainer *) del_name_box, (GtkWidget *) name_selector_entry);
+ gtk_widget_show ((GtkWidget *) name_selector_entry);
+ gtk_widget_grab_focus ((GtkWidget *) name_selector_entry);
+
+ gtk_window_set_modal ((GtkWindow *) priv->main, TRUE);
+ gtk_widget_show (priv->main);
+
+ return TRUE;
+}
+
+static void
+exchange_sendoptions_dialog_class_init (GObjectClass *object)
+{
+ ExchangeSendOptionsDialogClass *klass;
+ GObjectClass *object_class;
+
+ klass = EXCHANGE_SENDOPTIONS_DIALOG_CLASS (object);
+ parent_class = g_type_class_peek_parent (klass);
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = exchange_sendoptions_dialog_finalize;
+ object_class->dispose = exchange_sendoptions_dialog_dispose;
+ signals[SOD_RESPONSE] = g_signal_new ("sod_response",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (ExchangeSendOptionsDialogClass, esod_response),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE, 1,
+ G_TYPE_INT);
+
+}
+
+static void
+exchange_sendoptions_dialog_init (GObject *object)
+{
+
+ ExchangeSendOptionsDialog *sod;
+ ExchangeSendOptionsDialogPrivate *priv;
+ ExchangeSendOptions *new;
+
+ sod = EXCHANGE_SENDOPTIONS_DIALOG (object);
+ new = g_new0 (ExchangeSendOptions, 1);
+
+ priv = g_new0 (ExchangeSendOptionsDialogPrivate, 1);
+
+ sod->priv = priv;
+ sod->options = new;
+ sod->options->send_as_del_enabled = FALSE;
+ sod->options->delivery_enabled = FALSE;
+ sod->options->read_enabled = FALSE;
+ sod->options->importance = E_IMP_NORMAL;
+ sod->options->sensitivity = E_SENSITIVITY_NORMAL;
+
+ priv->main = NULL;
+ priv->importance = NULL;
+ priv->sensitivity = NULL;
+ priv->sensitivity_label = NULL;
+ priv->importance_label = NULL;
+ priv->button_user = NULL;
+ priv->proxy_name_selector = NULL;
+ priv->read_receipt = NULL;
+ priv->delivery_receipt = NULL;
+
+}
+
+static void
+exchange_sendoptions_dialog_finalize (GObject *object)
+{
+ ExchangeSendOptionsDialog *sod = (ExchangeSendOptionsDialog *)object;
+ ExchangeSendOptionsDialogPrivate *priv;
+
+ g_return_if_fail (EXCHANGE_IS_SENDOPTIONS_DIALOG (sod));
+ priv = sod->priv;
+
+ g_free (priv->help_section);
+
+ if (sod->options) {
+ g_free (sod->options);
+ sod->options = NULL;
+ }
+
+ if (sod->priv) {
+ g_free (sod->priv);
+ sod->priv = NULL;
+ }
+
+ if (parent_class->finalize)
+ (* parent_class->finalize) (object);
+
+}
+
+static void
+exchange_sendoptions_dialog_dispose (GObject *object)
+{
+ ExchangeSendOptionsDialog *sod = (ExchangeSendOptionsDialog *) object;
+
+ g_return_if_fail (EXCHANGE_IS_SENDOPTIONS_DIALOG (sod));
+
+ if (parent_class->dispose)
+ (* parent_class->dispose) (object);
+
+}
+
diff --git a/eplugin/exchange-send-options.h b/eplugin/exchange-send-options.h
new file mode 100644
index 0000000..131fee0
--- /dev/null
+++ b/eplugin/exchange-send-options.h
@@ -0,0 +1,83 @@
+/*
+ *
+ * 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:
+ * Raghavendran R <raghavguru7 gmail com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __EXCHANGE_SENDOPTIONS_DIALOG_H__
+#define __EXCHANGE_SENDOPTIONS_DIALOG_H__
+
+#include <gtk/gtk.h>
+
+#define EXCHANGE_TYPE_SENDOPTIONS_DIALOG (exchange_sendoptions_dialog_get_type ())
+#define EXCHANGE_SENDOPTIONS_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXCHANGE_TYPE_SENDOPTIONS_DIALOG, ExchangeSendOptionsDialog))
+#define EXCHANGE_SENDOPTIONS_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EXCHANGE_TYPE_SENDOPTIONS_DIALOG, ExchangeSendOptionsDialogClass))
+#define EXCHANGE_IS_SENDOPTIONS_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXCHANGE_TYPE_SENDOPTIONS_DIALOG))
+#define EXCHANGE_IS_SENDOPTIONS_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EXCHANGE_TYPE_SENDOPTIONS_DIALOG))
+
+typedef struct _ExchangeSendOptionsDialog ExchangeSendOptionsDialog;
+typedef struct _ExchangeSendOptionsDialogClass ExchangeSendOptionsDialogClass;
+typedef struct _ExchangeSendOptionsDialogPrivate ExchangeSendOptionsDialogPrivate;
+
+typedef enum {
+ E_IMP_NORMAL,
+ E_IMP_HIGH,
+ E_IMP_LOW
+} ExchangeSendOptionsImp;
+
+typedef enum {
+ E_SENSITIVITY_NORMAL,
+ E_SENSITIVITY_PERSONAL,
+ E_SENSITIVITY_PRIVATE,
+ E_SENSITIVITY_CONFIDENTIAL
+} ExchangeSendOptionsSensitivity;
+
+/* We require the delegate_email and delegate_name to store the address of the delegator selected into
+ the destination store.
+*/
+typedef struct {
+ ExchangeSendOptionsImp importance;
+ ExchangeSendOptionsSensitivity sensitivity;
+ gboolean send_as_del_enabled;
+ gboolean delivery_enabled;
+ gboolean read_enabled;
+ const gchar *delegate_name;
+ const gchar *delegate_email;
+ const gchar *delegate_address;
+} ExchangeSendOptions;
+
+struct _ExchangeSendOptionsDialog {
+ GObject object;
+
+ ExchangeSendOptions *options;
+ /* Private data */
+ ExchangeSendOptionsDialogPrivate *priv;
+};
+
+struct _ExchangeSendOptionsDialogClass {
+ GObjectClass parent_class;
+ void (* esod_response) (ExchangeSendOptionsDialog *esd, gint status);
+};
+
+GType exchange_sendoptions_dialog_get_type (void);
+ExchangeSendOptionsDialog *exchange_sendoptions_dialog_new (void);
+gboolean exchange_sendoptions_dialog_run (ExchangeSendOptionsDialog *sod, GtkWidget *parent);
+#endif
+
diff --git a/eplugin/exchange-user-dialog.c b/eplugin/exchange-user-dialog.c
new file mode 100644
index 0000000..908ffd3
--- /dev/null
+++ b/eplugin/exchange-user-dialog.c
@@ -0,0 +1,285 @@
+/*
+ * 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/>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "exchange-user-dialog.h"
+#include "e2k-types.h"
+
+#include <e-util/e-dialog-utils.h>
+#include <libedataserverui/e-name-selector.h>
+#include "e2k-xml-utils.h"
+
+struct _E2kUserDialogPrivate {
+ gchar *section_name;
+ ENameSelector *name_selector;
+ GtkWidget *entry, *parent_window;
+};
+
+#define PARENT_TYPE GTK_TYPE_DIALOG
+static GtkDialogClass *parent_class;
+
+static void parent_window_destroyed (gpointer dialog, GObject *where_parent_window_was);
+
+static void
+finalize (GObject *object)
+{
+ E2kUserDialog *dialog = E2K_USER_DIALOG (object);
+
+ g_free (dialog->priv->section_name);
+ g_free (dialog->priv);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+ E2kUserDialog *dialog = E2K_USER_DIALOG (object);
+
+ if (dialog->priv->name_selector != NULL) {
+ g_object_unref (dialog->priv->name_selector);
+ dialog->priv->name_selector = NULL;
+ }
+
+ if (dialog->priv->parent_window) {
+ g_object_weak_unref (G_OBJECT (dialog->priv->parent_window),
+ parent_window_destroyed, dialog);
+ dialog->priv->parent_window = NULL;
+ }
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+class_init (E2kUserDialogClass *class)
+{
+ GObjectClass *object_class = (GObjectClass *) class;
+
+ parent_class = g_type_class_ref (GTK_TYPE_DIALOG);
+
+ object_class->dispose = dispose;
+ object_class->finalize = finalize;
+}
+
+static void
+init (E2kUserDialog *dialog)
+{
+ dialog->priv = g_new0 (E2kUserDialogPrivate, 1);
+
+ gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 6);
+}
+
+E2K_MAKE_TYPE (e2k_user_dialog, E2kUserDialog, class_init, init, PARENT_TYPE)
+
+static void
+parent_window_destroyed (gpointer user_data, GObject *where_parent_window_was)
+{
+ E2kUserDialog *dialog = user_data;
+
+ dialog->priv->parent_window = NULL;
+ gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
+}
+
+static void
+addressbook_dialog_response (ENameSelectorDialog *name_selector_dialog, gint response, gpointer data)
+{
+ gtk_widget_hide (GTK_WIDGET (name_selector_dialog));
+}
+
+static void
+addressbook_clicked_cb (GtkWidget *widget, gpointer data)
+{
+ E2kUserDialog *dialog = data;
+ E2kUserDialogPrivate *priv;
+ ENameSelectorDialog *name_selector_dialog;
+
+ priv = dialog->priv;
+
+ name_selector_dialog = e_name_selector_peek_dialog (priv->name_selector);
+ gtk_window_set_modal (GTK_WINDOW (dialog), FALSE);
+ gtk_widget_show (GTK_WIDGET (name_selector_dialog));
+}
+
+static gboolean
+e2k_user_dialog_construct (E2kUserDialog *dialog,
+ GtkWidget *parent_window,
+ const gchar *label_text,
+ const gchar *section_name)
+{
+ E2kUserDialogPrivate *priv;
+ GtkWidget *hbox, *vbox, *label, *button;
+ ENameSelectorModel *name_selector_model;
+ ENameSelectorDialog *name_selector_dialog;
+
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Select User"));
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+
+ if (parent_window)
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent_window));
+
+ priv = dialog->priv;
+ priv->section_name = g_strdup (section_name);
+
+ priv->parent_window = parent_window;
+ g_object_weak_ref (G_OBJECT (parent_window),
+ parent_window_destroyed, dialog);
+
+ /* Set up the actual select names bits */
+ priv->name_selector = e_name_selector_new ();
+
+ /* Listen for responses whenever the dialog is shown */
+ name_selector_dialog = e_name_selector_peek_dialog (priv->name_selector);
+ g_signal_connect (name_selector_dialog, "response",
+ G_CALLBACK (addressbook_dialog_response), dialog);
+
+ name_selector_model = e_name_selector_peek_model (priv->name_selector);
+ /* FIXME Limit to one user */
+ e_name_selector_model_add_section (name_selector_model, section_name, section_name, NULL);
+
+ hbox = gtk_hbox_new (FALSE, 6);
+
+ label = gtk_label_new (label_text);
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 6);
+
+ /* The vbox is a workaround for bug 43315 */
+ vbox = gtk_vbox_new (FALSE, 0);
+ priv->entry = GTK_WIDGET (e_name_selector_peek_section_entry (priv->name_selector, section_name));
+ gtk_box_pack_start (GTK_BOX (vbox), priv->entry, TRUE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 6);
+
+ button = gtk_button_new_with_label (_("Address Book..."));
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (addressbook_clicked_cb),
+ dialog);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 6);
+
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox,
+ TRUE, TRUE, 6);
+ gtk_widget_show_all (hbox);
+
+ return TRUE;
+}
+
+/**
+ * e2k_user_dialog_new:
+ * @parent_window: The window invoking the dialog.
+ * @label_text: Text to label the entry in the initial dialog with
+ * @section_name: The section name for the select-names dialog
+ *
+ * Creates a new user selection dialog.
+ *
+ * Return value: A newly-created user selection dialog, or %NULL if
+ * the dialog could not be created.
+ **/
+GtkWidget *
+e2k_user_dialog_new (GtkWidget *parent_window,
+ const gchar *label_text, const gchar *section_name)
+{
+ E2kUserDialog *dialog;
+
+ g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL);
+ g_return_val_if_fail (label_text != NULL, NULL);
+ g_return_val_if_fail (section_name != NULL, NULL);
+
+ dialog = g_object_new (E2K_TYPE_USER_DIALOG, NULL);
+ if (!e2k_user_dialog_construct (dialog, parent_window,
+ label_text, section_name)) {
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ return NULL;
+ }
+
+ return GTK_WIDGET (dialog);
+}
+
+/**
+ * e2k_user_dialog_get_user_list:
+ * @dialog: the dialog
+ *
+ * Gets the email addresses of the selected user from the dialog.
+ *
+ * Return value: the email addresses.
+ **/
+GList *
+e2k_user_dialog_get_user_list (E2kUserDialog *dialog)
+{
+ E2kUserDialogPrivate *priv;
+ EDestinationStore *destination_store;
+ GList *destinations;
+ GList *l;
+ GList *email_list = NULL;
+ EDestination *destination;
+
+ g_return_val_if_fail (E2K_IS_USER_DIALOG (dialog), NULL);
+
+ priv = dialog->priv;
+
+ destination_store = e_name_selector_entry_peek_destination_store (E_NAME_SELECTOR_ENTRY (priv->entry));
+ destinations = e_destination_store_list_destinations (destination_store);
+ if (!destinations)
+ return NULL;
+
+ for (l = destinations; l; l = g_list_next (l)) {
+ const gchar *mail;
+ destination = l->data;
+
+ mail = e_destination_get_email (destination);
+ if (mail && *mail)
+ email_list = g_list_prepend (email_list, g_strdup (mail));
+ }
+ g_list_free (destinations);
+
+ return email_list;
+}
+
+/**
+ * e2k_user_dialog_get_user:
+ * @dialog: the dialog
+ *
+ * Gets the email address of the selected user from the dialog.
+ *
+ * Return value: the email address, which must be freed with g_free().
+ **/
+gchar *
+e2k_user_dialog_get_user (E2kUserDialog *dialog)
+{
+ E2kUserDialogPrivate *priv;
+ EDestinationStore *destination_store;
+ GList *destinations;
+ EDestination *destination;
+ gchar *result = NULL;
+
+ g_return_val_if_fail (E2K_IS_USER_DIALOG (dialog), NULL);
+
+ priv = dialog->priv;
+
+ destination_store = e_name_selector_entry_peek_destination_store (E_NAME_SELECTOR_ENTRY (priv->entry));
+ destinations = e_destination_store_list_destinations (destination_store);
+ if (!destinations)
+ return NULL;
+
+ destination = destinations->data;
+ result = g_strdup (e_destination_get_email (destination));
+ g_list_free (destinations);
+
+ return result;
+}
diff --git a/eplugin/exchange-user-dialog.h b/eplugin/exchange-user-dialog.h
new file mode 100644
index 0000000..8b6134b
--- /dev/null
+++ b/eplugin/exchange-user-dialog.h
@@ -0,0 +1,56 @@
+/*
+ * 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:
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef __E2K_USER_DIALOG_H__
+#define __E2K_USER_DIALOG_H__
+
+#include <gtk/gtk.h>
+
+#define E2K_TYPE_USER_DIALOG (e2k_user_dialog_get_type ())
+#define E2K_USER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E2K_TYPE_USER_DIALOG, E2kUserDialog))
+#define E2K_USER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E2K_TYPE_USER_DIALOG, \
+ E2kUserDialogClass))
+#define E2K_IS_USER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E2K_TYPE_USER_DIALOG))
+#define E2K_IS_USER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E2K_TYPE_USER_DIALOG))
+
+typedef struct _E2kUserDialog E2kUserDialog;
+typedef struct _E2kUserDialogClass E2kUserDialogClass;
+typedef struct _E2kUserDialogPrivate E2kUserDialogPrivate;
+
+struct _E2kUserDialog {
+ GtkDialog parent;
+
+ /* Private data */
+ E2kUserDialogPrivate *priv;
+};
+
+struct _E2kUserDialogClass {
+ GtkDialogClass parent_class;
+};
+
+GType e2k_user_dialog_get_type (void);
+GtkWidget *e2k_user_dialog_new (GtkWidget *parent_window,
+ const gchar *label_text,
+ const gchar *section_name);
+gchar *e2k_user_dialog_get_user (E2kUserDialog *dialog);
+GList *e2k_user_dialog_get_user_list (E2kUserDialog *dialog);
+
+#endif /* __E2K_USER_DIALOG_H__ */
diff --git a/eplugin/org-gnome-exchange-operations.eplug b/eplugin/org-gnome-exchange-operations.eplug
new file mode 100644
index 0000000..a1a9485
--- /dev/null
+++ b/eplugin/org-gnome-exchange-operations.eplug
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<e-plugin-list>
+ <e-plugin type="shlib" system_plugin="true" location="/build/local/lib/evolution/2.30/plugins/liborg-gnome-exchange-operations" load-on-startup="true" id="org.gnome.evolution.plugin.exchange-operations" name="Exchange Operations">
+ <author name="Sushma Rai" email="rsushma novell com"/>
+ <author name="Praveen Kumar" email="kpraveen novell com"/>
+ <author name="Shakti Sen" email="shprasad novell com"/>
+ <author name="Raghavendran R" email="raghavguru7 gmail com"/>
+ <description>Activates the Evolution-Exchange extension package.</description>
+
+ <hook class="org.gnome.evolution.mail.config:1.0">
+ <group target="account" id="org.gnome.evolution.mail.config.accountEditor" commit="org_gnome_exchange_commit" check="org_gnome_exchange_check_options">
+ <item type="page" path="40.oof" factory="org_gnome_exchange_settings" label="Exchange Settings"></item>
+ <item type="item_table" path="10.receive/10.config/20.owa" factory="org_gnome_exchange_owa_url"/>
+ <item type="section" path="10.receive/30.auth/00.exchange_auth" factory="org_gnome_exchange_auth_section"/>
+ </group>
+
+ <group target="account" id="org.gnome.evolution.mail.config.accountAssistant" check="org_gnome_exchange_check_options">
+ <item type="item_table" path="10.receive/10.config/20.owa" factory="org_gnome_exchange_owa_url"/>
+ <item type="section" path="10.receive/30.auth/00.exchange_auth" factory="org_gnome_exchange_auth_section"/>
+ </group>
+
+ <group target="account" id="org.gnome.evolution.mail.config.accountWizard" check="org_gnome_exchange_check_options">
+ <item type="item_table" path="10.receive/10.config/20.owa" factory="org_gnome_exchange_owa_url"/>
+ </group>
+
+ <group target="folder" id="org.gnome.evolution.mail.folderConfig" check="exchange_show_folder_size_check">
+ <item type="page" path="10.size" factory="org_gnome_exchange_show_folder_size_factory" label="Size"></item>
+ </group>
+ </hook>
+
+ <hook class="org.gnome.evolution.calendar.config:1.0">
+ <group target="source" id="org.gnome.evolution.calendar.calendarProperties" commit="e_exchange_calendar_commit" check="e_exchange_calendar_check">
+ <item type="item_table" path="00.general/00.source/40.pcalendar" factory="e_exchange_calendar_pcalendar"/>
+ </group>
+ </hook>
+
+ <hook class="org.gnome.evolution.addressbook.config:1.0">
+ <group target="source" id="com.novell.evolution.addressbook.config.accountEditor" commit="e_exchange_contacts_commit" check="e_exchange_contacts_check">
+ <item type="item" path="00.general/10.display/40.pcontacts" factory="e_exchange_contacts_pcontacts"/>
+ </group>
+ </hook>
+
+ <hook class="org.gnome.evolution.mail.events:1.0">
+ <event target="composer" id="composer.selectsendoption" handle="org_gnome_exchange_send_options" enable="sendoption"/>
+ </hook>
+
+ <hook class="org.gnome.evolution.ui:1.0">
+ <ui-manager id="org.gnome.evolution.mail" callback="eex_ui_mail_init">
+ <popup name="mail-folder-popup">
+ <placeholder name="mail-folder-popup-actions">
+ <menuitem action="eex-mail-folder-permissions"/>
+ <menuitem action="eex-mail-folder-inbox-unsubscribe"/>
+ </placeholder>
+ </popup>
+ <menubar name="main-menu">
+ <menu action="file-menu">
+ <placeholder name="file-actions">
+ <menuitem action="eex-mail-folder-permissions"/>
+ <menuitem action="eex-folder-subscribe-Inbox"/>
+ </placeholder>
+ </menu>
+ </menubar>
+ </ui-manager>
+ <ui-manager id="org.gnome.evolution.calendar" callback="eex_ui_calendar_permissions">
+ <popup name="calendar-popup">
+ <placeholder name="calendar-popup-actions">
+ <menuitem action="eex-calendar-permissions"/>
+ <menuitem action="eex-folder-unsubscribe-Calendar"/>
+ </placeholder>
+ </popup>
+ <menubar name="main-menu">
+ <menu action="file-menu">
+ <placeholder name="file-actions">
+ <menuitem action="eex-calendar-permissions"/>
+ <menuitem action="eex-folder-subscribe-Calendar"/>
+ </placeholder>
+ </menu>
+ </menubar>
+ </ui-manager>
+ <ui-manager id="org.gnome.evolution.task" callback="eex_ui_tasks_permissions">
+ <popup name="task-list-popup">
+ <placeholder name="task-list-popup-actions">
+ <menuitem action="eex-tasks-permissions"/>
+ <menuitem action="eex-folder-unsubscribe-Tasks"/>
+ </placeholder>
+ </popup>
+ <menubar name="main-menu">
+ <menu action="file-menu">
+ <placeholder name="file-actions">
+ <menuitem action="eex-tasks-permissions"/>
+ <menuitem action="eex-folder-subscribe-Tasks"/>
+ </placeholder>
+ </menu>
+ </menubar>
+ </ui-manager>
+ <ui-manager id="org.gnome.evolution.addressbook" callback="eex_ui_addressbook_permissions">
+ <popup name="address-book-popup">
+ <placeholder name="address-book-popup-actions">
+ <menuitem action="eex-addressbook-permissions"/>
+ <menuitem action="eex-folder-unsubscribe-Contacts"/>
+ </placeholder>
+ </popup>
+ <menubar name="main-menu">
+ <menu action="file-menu">
+ <placeholder name="file-actions">
+ <menuitem action="eex-addressbook-permissions"/>
+ <menuitem action="eex-folder-subscribe-Contacts"/>
+ </placeholder>
+ </menu>
+ </menubar>
+ </ui-manager>
+ </hook>
+ </e-plugin>
+</e-plugin-list>
\ No newline at end of file
diff --git a/eplugin/org-gnome-exchange-operations.eplug.xml b/eplugin/org-gnome-exchange-operations.eplug.xml
new file mode 100644
index 0000000..fcd6ff0
--- /dev/null
+++ b/eplugin/org-gnome-exchange-operations.eplug.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+<e-plugin-list>
+ <e-plugin
+ type="shlib"
+ id="org.gnome.evolution.plugin.exchange-operations"
+ location="@PLUGINDIR@/liborg-gnome-exchange-operations SOEXT@"
+ load-on-startup="true"
+ _name="Exchange Operations"
+ system_plugin="true">
+ <author name="Sushma Rai" email="rsushma novell com"/>
+ <author name="Praveen Kumar" email="kpraveen novell com"/>
+ <author name="Shakti Sen" email="shprasad novell com"/>
+ <author name="Raghavendran R" email="raghavguru7 gmail com"/>
+ <_description>Activates the Evolution-Exchange extension package.</_description>
+
+ <hook class="org.gnome.evolution.mail.config:1.0">
+ <group target="account" id="org.gnome.evolution.mail.config.accountEditor" check="org_gnome_exchange_check_options" commit="org_gnome_exchange_commit">
+ <item type="page" path="40.oof" _label="Exchange Settings" factory="org_gnome_exchange_settings"/>
+ <item type="item_table" path="10.receive/10.config/20.owa" factory="org_gnome_exchange_owa_url"/>
+ <item type="section" path="10.receive/30.auth/00.exchange_auth" factory="org_gnome_exchange_auth_section"/>
+ </group>
+
+ <group target="account" id="org.gnome.evolution.mail.config.accountAssistant" check="org_gnome_exchange_check_options">
+ <item type="item_table" path="10.receive/10.config/20.owa" factory="org_gnome_exchange_owa_url"/>
+ <item type="section" path="10.receive/30.auth/00.exchange_auth" factory="org_gnome_exchange_auth_section"/>
+ </group>
+
+ <group target="account" id="org.gnome.evolution.mail.config.accountWizard" check="org_gnome_exchange_check_options">
+ <item type="item_table" path="10.receive/10.config/20.owa" factory="org_gnome_exchange_owa_url"/>
+ </group>
+
+ <group id="org.gnome.evolution.mail.folderConfig" target="folder" check= "exchange_show_folder_size_check">
+ <item type="page" path="10.size" _label="Size" factory="org_gnome_exchange_show_folder_size_factory"/>
+ </group>
+ </hook>
+
+ <hook class="org.gnome.evolution.calendar.config:1.0">
+ <group target="source" id="org.gnome.evolution.calendar.calendarProperties" check="e_exchange_calendar_check" commit="e_exchange_calendar_commit">
+ <item type="item_table" path="00.general/00.source/40.pcalendar" factory="e_exchange_calendar_pcalendar"/>
+ </group>
+ </hook>
+
+ <hook class="org.gnome.evolution.addressbook.config:1.0">
+ <group target="source" id="com.novell.evolution.addressbook.config.accountEditor" check="e_exchange_contacts_check" commit="e_exchange_contacts_commit">
+ <item type="item" path="00.general/10.display/40.pcontacts" factory="e_exchange_contacts_pcontacts"/>
+ </group>
+ </hook>
+
+ <hook class="org.gnome.evolution.mail.events:1.0">
+ <event id="composer.selectsendoption" handle="org_gnome_exchange_send_options" target="composer" enable="sendoption"/>
+ </hook>
+
+ <hook class="org.gnome.evolution.ui:1.0">
+ <ui-manager id="org.gnome.evolution.mail" callback="eex_ui_mail_init">
+ <popup name="mail-folder-popup">
+ <placeholder name="mail-folder-popup-actions">
+ <menuitem action="eex-mail-folder-permissions"/>
+ <menuitem action="eex-mail-folder-inbox-unsubscribe"/>
+ </placeholder>
+ </popup>
+ <menubar name="main-menu">
+ <menu action="file-menu">
+ <placeholder name="file-actions">
+ <menuitem action="eex-mail-folder-permissions"/>
+ <menuitem action="eex-folder-subscribe-Inbox"/>
+ </placeholder>
+ </menu>
+ </menubar>
+ </ui-manager>
+ <ui-manager id="org.gnome.evolution.calendar" callback="eex_ui_calendar_permissions">
+ <popup name="calendar-popup">
+ <placeholder name="calendar-popup-actions">
+ <menuitem action="eex-calendar-permissions"/>
+ <menuitem action="eex-folder-unsubscribe-Calendar"/>
+ </placeholder>
+ </popup>
+ <menubar name="main-menu">
+ <menu action="file-menu">
+ <placeholder name="file-actions">
+ <menuitem action="eex-calendar-permissions"/>
+ <menuitem action="eex-folder-subscribe-Calendar"/>
+ </placeholder>
+ </menu>
+ </menubar>
+ </ui-manager>
+ <ui-manager id="org.gnome.evolution.task" callback="eex_ui_tasks_permissions">
+ <popup name="task-list-popup">
+ <placeholder name="task-list-popup-actions">
+ <menuitem action="eex-tasks-permissions"/>
+ <menuitem action="eex-folder-unsubscribe-Tasks"/>
+ </placeholder>
+ </popup>
+ <menubar name="main-menu">
+ <menu action="file-menu">
+ <placeholder name="file-actions">
+ <menuitem action="eex-tasks-permissions"/>
+ <menuitem action="eex-folder-subscribe-Tasks"/>
+ </placeholder>
+ </menu>
+ </menubar>
+ </ui-manager>
+ <ui-manager id="org.gnome.evolution.addressbook" callback="eex_ui_addressbook_permissions">
+ <popup name="address-book-popup">
+ <placeholder name="address-book-popup-actions">
+ <menuitem action="eex-addressbook-permissions"/>
+ <menuitem action="eex-folder-unsubscribe-Contacts"/>
+ </placeholder>
+ </popup>
+ <menubar name="main-menu">
+ <menu action="file-menu">
+ <placeholder name="file-actions">
+ <menuitem action="eex-addressbook-permissions"/>
+ <menuitem action="eex-folder-subscribe-Contacts"/>
+ </placeholder>
+ </menu>
+ </menubar>
+ </ui-manager>
+ </hook>
+ </e-plugin>
+</e-plugin-list>
diff --git a/eplugin/org-gnome-exchange-operations.error b/eplugin/org-gnome-exchange-operations.error
new file mode 100644
index 0000000..c26973c
--- /dev/null
+++ b/eplugin/org-gnome-exchange-operations.error
@@ -0,0 +1,262 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<error-list domain="org-gnome-exchange-operations">
+
+ <error type="error" id="single-account-error">
+ <primary>You may only configure a single Exchange account.</primary>
+ </error>
+
+ <error type="info" id="apply-restart">
+ <primary>Please restart Evolution for changes to take effect</primary>
+ <secondary>Changes to options for Exchange account "{0}" will only take effect after restarting Evolution.</secondary>
+ </error>
+
+ <error type="info" id="remove-quit">
+ <primary>The Exchange account will be removed when you quit Evolution</primary>
+ </error>
+
+ <error type="info" id="disable-quit">
+ <primary>The Exchange account will be disabled when you quit Evolution</primary>
+ </error>
+
+ <error type="error" id="state-read-error">
+ <primary>Could not read out-of-office state</primary>
+ </error>
+
+ <error type="error" id="state-update-error">
+ <primary>Could not update out-of-office state</primary>
+ </error>
+
+ <error type="error" id="config-error">
+ <primary>Cannot change password due to configuration problems.</primary>
+ </error>
+
+ <error type="error" id="password-weak-error">
+ <primary>Server rejected password because it is too weak.</primary>
+ <secondary>Try again with a different password.</secondary>
+ </error>
+
+ <error type="error" id="password-change-error">
+ <primary>Could not change password.</primary>
+ </error>
+
+ <error type="info" id="password-change-success">
+ <primary>Password successfully changed.</primary>
+ </error>
+
+ <error type="info" id="account-offline">
+ <primary>Exchange Account is offline.</primary>
+ <secondary>Cannot display folders.</secondary>
+ </error>
+
+ <error type="info" id="exchange-settings-offline">
+ <primary>Exchange Account is offline.</primary>
+ <secondary>Cannot access the "Exchange settings" tab in offline mode.</secondary>
+ </error>
+
+ <error type="info" id="account-offline-generic">
+ <primary>Exchange Account is offline.</primary>
+ <secondary>Cannot perform the operation.</secondary>
+ </error>
+
+ <error type="error" id="password-incorrect">
+ <primary>Could not authenticate to server.</primary>
+ <secondary>Make sure the username and password are correct and try again.</secondary>
+ </error>
+
+ <error type="error" id="account-domain-error">
+ <primary>Could not authenticate to server.</primary>
+ <secondary xml:space="preserve">This probably means that your server requires
+you to specify the Windows domain name
+as part of your username (eg, "DOMAIN\user").
+
+Or you might have just typed your password wrong.</secondary>
+ </error>
+
+ <error type="error" id="account-mailbox-na">
+ <primary>Mailbox for {0} is not on this server.</primary>
+ </error>
+
+ <error type="error" id="account-version-error">
+ <primary>The Exchange server is not compatible with Exchange Connector.</primary>
+ <secondary xml:space="preserve">The server is running Exchange 5.5. Exchange Connector
+supports Microsoft Exchange 2000 and 2003 only.</secondary>
+ </error>
+
+ <error type="error" id="account-wss-error">
+ <primary>Could not find Exchange Web Storage System.</primary>
+ <secondary>If OWA is running on a different path, you must specify that in the account configuration dialog.</secondary>
+ </error>
+
+ <error type="info" id="account-no-mailbox">
+ <primary>No mailbox for user {0} on {1}.</primary>
+ </error>
+
+ <error type="error" id="account-resolve-error">
+ <primary>Could not locate server {0}.</primary>
+ <secondary>Make sure the server name is spelled correctly and try again.</secondary>
+ </error>
+
+ <error type="error" id="account-connect-error">
+ <primary>Could not connect to server {0}.</primary>
+ <secondary>Make sure the URL is correct and try again.</secondary>
+ </error>
+
+ <error type="error" id="password-expired">
+ <primary>Your password has expired.</primary>
+ </error>
+
+ <error type="error" id="account-unknown-error">
+ <primary>Could not connect to server {0}.</primary>
+ <secondary>Unknown error.</secondary>
+ </error>
+
+ <error type="error" id="account-quota-error">
+ <primary>You have exceeded your quota for storing mail on this server.</primary>
+ <secondary>Your current usage is: {0} KB. You will not be able to either send or receive mail now.</secondary>
+ </error>
+
+ <error type="warning" id="account-quota-send-error">
+ <primary>You are nearing your quota available for storing mail on this server.</primary>
+ <secondary>Your current usage is: {0} KB. You will not be able to send mail until you clear up some space by deleting some mail.</secondary>
+ </error>
+
+ <error type="warning" id="account-quota-warn">
+ <primary>You are nearing your quota available for storing mail on this server.</primary>
+ <secondary>Your current usage is: {0} KB. Try to clear up some space by deleting some mail.</secondary>
+ </error>
+
+ <error type="error" id="connect-exchange-error">
+ <primary>Could not connect to Exchange server.</primary>
+ <secondary xml:space="preserve">Exchange Connector requires access to certain
+functionality on the Exchange Server that appears
+to be disabled or blocked. (This is usually
+unintentional.) Your Exchange Administrator will
+need to enable this functionality in order for
+you to be able to use Evolution Exchange Connector.
+
+For information to provide to your Exchange
+administrator, please follow the link below:
+
+{0}
+ </secondary>
+ </error>
+
+ <error type="error" id="configure-error">
+ <secondary xml:space="preserve">Could not configure Exchange account because
+an unknown error occurred. Check the URL,
+username, and password, and try again.</secondary>
+ </error>
+
+ <error type="error" id="delegates-no-gcs-error">
+ <primary>No Global Catalog server configured for this account.</primary>
+ <secondary>Unable to edit delegates.</secondary>
+ </error>
+
+ <error type="error" id="acl-no-gcs-error">
+ <primary>Unable to add user to access control list:</primary>
+ <secondary>No Global Catalog server configured for this account.</secondary>
+ </error>
+
+ <error type="error" id="delegates-perm-read-error">
+ <primary>Could not read folder permissions.</primary>
+ <secondary>Unable to edit delegates.</secondary>
+ </error>
+
+ <error type="error" id="perm-read-error">
+ <primary>Could not read folder permissions</primary>
+ </error>
+
+ <error type="error" id="perm-deter-error">
+ <primary>Unable to edit delegates.</primary>
+ <secondary>Could not determine folder permissions for delegates.</secondary>
+ </error>
+
+ <error type="error" id="delegate-error">
+ <primary>Could not make {0} a delegate</primary>
+ </error>
+
+ <error type="error" id="delegate-own-error">
+ <primary>You cannot make yourself your own delegate</primary>
+ </error>
+
+ <error type="info" id="delegate-existing">
+ <primary>{0} is already a delegate</primary>
+ </error>
+
+ <error type="error" id="delegate-fail-error">
+ <primary>Failed to update delegates:</primary>
+ <secondary>{0}</secondary>
+ </error>
+
+<error type="info" id="no-delegate-selected">
+ <primary>Please enter a Delegate's ID or deselect the Send as a Delegate option.</primary>
+ </error>
+
+<error type="info" id="more-delegates-selected">
+ <primary>You are permitted to send a message on behalf of only one delegator at a time.</primary>
+ </error>
+
+
+ <error type="info" id="select-user">
+ <primary>Please select a user.</primary>
+ </error>
+
+ <error type="error" id="perm-update-error">
+ <primary>Could not update folder permissions.</primary>
+ <secondary>{0}</secondary>
+ </error>
+
+ <error type="error" id="no-user-error">
+ <primary>No such user {0}</primary>
+ </error>
+
+ <error type="error" id="acl-add-error">
+ <primary>{0} cannot be added to an access control list</primary>
+ </error>
+
+ <error type="error" id="perm-unknown-error">
+ <primary>Unknown error looking up {0}</primary>
+ </error>
+
+ <error type="error" id="perm-existing-error">
+ <primary>{0} is already in the list</primary>
+ </error>
+
+ <error type="error" id="folder-exists-error">
+ <primary>Folder already exists</primary>
+ </error>
+
+ <error type="error" id="folder-restart-evo">
+ <primary>Evolution requires a restart to load the subscribed user's mailbox</primary>
+ </error>
+
+ <error type="error" id="folder-doesnt-exist-error">
+ <primary>Folder does not exist</primary>
+ </error>
+
+ <error type="error" id="folder-perm-error">
+ <primary>Permission denied</primary>
+ </error>
+
+ <error type="error" id="folder-unknown-type">
+ <primary>Unknown type</primary>
+ </error>
+
+ <error type="error" id="folder-offline-error">
+ <primary>Folder offline</primary>
+ </error>
+
+ <error type="error" id="folder-unsupported-error">
+ <primary>Unsupported operation</primary>
+ </error>
+
+ <error type="error" id="folder-no-gc-error">
+ <primary>Global Catalog Server is not reachable</primary>
+ <secondary>Please make sure the Global Catalog Server name is correct.</secondary>
+ </error>
+
+ <error type="error" id="folder-generic-error">
+ <primary>Generic error</primary>
+ </error>
+
+</error-list>
\ No newline at end of file
diff --git a/eplugin/org-gnome-exchange-operations.error.xml b/eplugin/org-gnome-exchange-operations.error.xml
new file mode 100644
index 0000000..37ed0aa
--- /dev/null
+++ b/eplugin/org-gnome-exchange-operations.error.xml
@@ -0,0 +1,263 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<error-list domain="org-gnome-exchange-operations">
+
+ <error id="single-account-error" type="error">
+ <_primary>You may only configure a single Exchange account.</_primary>
+ </error>
+
+ <error id="apply-restart" type="info">
+ <_primary>Please restart Evolution for changes to take effect</_primary>
+ <_secondary>Changes to options for Exchange account "{0}" will only take effect after restarting Evolution.</_secondary>
+ </error>
+
+ <error id="remove-quit" type="info">
+ <_primary>The Exchange account will be removed when you quit Evolution</_primary>
+ </error>
+
+ <error id="disable-quit" type="info">
+ <_primary>The Exchange account will be disabled when you quit Evolution</_primary>
+ </error>
+
+ <error id="state-read-error" type="error">
+ <_primary>Could not read out-of-office state</_primary>
+ </error>
+
+ <error id="state-update-error" type="error">
+ <_primary>Could not update out-of-office state</_primary>
+ </error>
+
+ <error id="config-error" type="error">
+ <_primary>Cannot change password due to configuration problems.</_primary>
+ </error>
+
+ <error id="password-weak-error" type="error">
+ <_primary>Server rejected password because it is too weak.</_primary>
+ <_secondary>Try again with a different password.</_secondary>
+ </error>
+
+ <error id="password-change-error" type="error">
+ <_primary>Could not change password.</_primary>
+ </error>
+
+ <error id="password-change-success" type="info">
+ <_primary>Password successfully changed.</_primary>
+ </error>
+
+ <error id="account-offline" type="info">
+ <_primary>Exchange Account is offline.</_primary>
+ <_secondary>Cannot display folders.</_secondary>
+ </error>
+
+ <error id="exchange-settings-offline" type="info">
+ <_primary>Exchange Account is offline.</_primary>
+ <_secondary>Cannot access the "Exchange settings" tab in offline mode.</_secondary>
+ </error>
+
+ <error id="account-offline-generic" type="info">
+ <_primary>Exchange Account is offline.</_primary>
+ <_secondary>Cannot perform the operation.</_secondary>
+ </error>
+
+ <error id="password-incorrect" type="error">
+ <_primary>Could not authenticate to server.</_primary>
+ <_secondary>Make sure the username and password are correct and try again.</_secondary>
+ </error>
+
+ <error id="account-domain-error" type="error">
+ <_primary>Could not authenticate to server.</_primary>
+ <_secondary xml:space="preserve">This probably means that your server requires
+you to specify the Windows domain name
+as part of your username (eg, "DOMAIN\user").
+
+Or you might have just typed your password wrong.</_secondary>
+ </error>
+
+ <error id="account-mailbox-na" type="error">
+ <_primary>Mailbox for {0} is not on this server.</_primary>
+ </error>
+
+ <error id="account-version-error" type="error">
+ <_primary>The Exchange server is not compatible with Exchange Connector.</_primary>
+ <_secondary xml:space="preserve">The server is running Exchange 5.5. Exchange Connector
+supports Microsoft Exchange 2000 and 2003 only.</_secondary>
+ </error>
+
+ <error id="account-wss-error" type="error">
+ <_primary>Could not find Exchange Web Storage System.</_primary>
+ <_secondary>If OWA is running on a different path, you must specify that in the account configuration dialog.</_secondary>
+ </error>
+
+ <error id="account-no-mailbox" type="info">
+ <_primary>No mailbox for user {0} on {1}.</_primary>
+ </error>
+
+ <error id="account-resolve-error" type="error">
+ <_primary>Could not locate server {0}.</_primary>
+ <_secondary>Make sure the server name is spelled correctly and try again.</_secondary>
+ </error>
+
+ <error id="account-connect-error" type="error">
+ <_primary>Could not connect to server {0}.</_primary>
+ <_secondary>Make sure the URL is correct and try again.</_secondary>
+ </error>
+
+ <error id="password-expired" type="error">
+ <_primary>Your password has expired.</_primary>
+ </error>
+
+ <error id="account-unknown-error" type="error">
+ <_primary>Could not connect to server {0}.</_primary>
+ <_secondary>Unknown error.</_secondary>
+ </error>
+
+ <error id="account-quota-error" type="error">
+ <_primary>You have exceeded your quota for storing mail on this server.</_primary>
+ <_secondary>Your current usage is: {0} KB. You will not be able to either send or receive mail now.</_secondary>
+ </error>
+
+ <error id="account-quota-send-error" type="warning">
+ <_primary>You are nearing your quota available for storing mail on this server.</_primary>
+ <_secondary>Your current usage is: {0} KB. You will not be able to send mail until you clear up some space by deleting some mail.</_secondary>
+ </error>
+
+ <error id="account-quota-warn" type="warning">
+ <_primary>You are nearing your quota available for storing mail on this server.</_primary>
+ <_secondary>Your current usage is: {0} KB. Try to clear up some space by deleting some mail.</_secondary>
+ </error>
+
+ <error id="connect-exchange-error" type="error">
+ <_primary>Could not connect to Exchange server.</_primary>
+ <_secondary xml:space="preserve">Exchange Connector requires access to certain
+functionality on the Exchange Server that appears
+to be disabled or blocked. (This is usually
+unintentional.) Your Exchange Administrator will
+need to enable this functionality in order for
+you to be able to use Evolution Exchange Connector.
+
+For information to provide to your Exchange
+administrator, please follow the link below:
+
+{0}
+ </_secondary>
+ </error>
+
+ <error id="configure-error" type="error">
+ <_secondary xml:space="preserve">Could not configure Exchange account because
+an unknown error occurred. Check the URL,
+username, and password, and try again.</_secondary>
+ </error>
+
+ <error id="delegates-no-gcs-error" type="error">
+ <_primary>No Global Catalog server configured for this account.</_primary>
+ <_secondary>Unable to edit delegates.</_secondary>
+ </error>
+
+ <error id="acl-no-gcs-error" type="error">
+ <_primary>Unable to add user to access control list:</_primary>
+ <_secondary>No Global Catalog server configured for this account.</_secondary>
+ </error>
+
+ <error id="delegates-perm-read-error" type="error">
+ <_primary>Could not read folder permissions.</_primary>
+ <_secondary>Unable to edit delegates.</_secondary>
+ </error>
+
+ <error id="perm-read-error" type="error">
+ <_primary>Could not read folder permissions</_primary>
+ </error>
+
+ <error id="perm-deter-error" type="error">
+ <_primary>Unable to edit delegates.</_primary>
+ <_secondary>Could not determine folder permissions for delegates.</_secondary>
+ </error>
+
+ <error id="delegate-error" type="error">
+ <_primary>Could not make {0} a delegate</_primary>
+ </error>
+
+ <error id="delegate-own-error" type="error">
+ <_primary>You cannot make yourself your own delegate</_primary>
+ </error>
+
+ <error id="delegate-existing" type="info">
+ <_primary>{0} is already a delegate</_primary>
+ </error>
+
+ <error id="delegate-fail-error" type="error">
+ <_primary>Failed to update delegates:</_primary>
+ <_secondary>{0}</_secondary>
+ </error>
+
+<error id="no-delegate-selected" type="info">
+ <_primary>Please enter a Delegate's ID or deselect the Send as a Delegate option.</_primary>
+ </error>
+
+<error id="more-delegates-selected" type="info">
+ <_primary>You are permitted to send a message on behalf of only one delegator at a time.</_primary>
+ </error>
+
+
+ <error id="select-user" type="info">
+ <_primary>Please select a user.</_primary>
+ </error>
+
+ <error id="perm-update-error" type="error">
+ <_primary>Could not update folder permissions.</_primary>
+ <_secondary>{0}</_secondary>
+ </error>
+
+ <error id="no-user-error" type="error">
+ <_primary>No such user {0}</_primary>
+ </error>
+
+ <error id="acl-add-error" type="error">
+ <_primary>{0} cannot be added to an access control list</_primary>
+ </error>
+
+ <error id="perm-unknown-error" type="error">
+ <_primary>Unknown error looking up {0}</_primary>
+ </error>
+
+ <error id="perm-existing-error" type="error">
+ <_primary>{0} is already in the list</_primary>
+ </error>
+
+ <error id="folder-exists-error" type="error">
+ <_primary>Folder already exists</_primary>
+ </error>
+
+ <error id="folder-restart-evo" type="error">
+ <_primary>Evolution requires a restart to load the subscribed user's mailbox</_primary>
+ </error>
+
+ <error id="folder-doesnt-exist-error" type="error">
+ <_primary>Folder does not exist</_primary>
+ </error>
+
+ <error id="folder-perm-error" type="error">
+ <_primary>Permission denied</_primary>
+ </error>
+
+ <error id="folder-unknown-type" type="error">
+ <_primary>Unknown type</_primary>
+ </error>
+
+ <error id="folder-offline-error" type="error">
+ <_primary>Folder offline</_primary>
+ </error>
+
+ <error id="folder-unsupported-error" type="error">
+ <_primary>Unsupported operation</_primary>
+ </error>
+
+ <error id="folder-no-gc-error" type="error">
+ <_primary>Global Catalog Server is not reachable</_primary>
+ <_secondary>Please make sure the Global Catalog Server name is correct.</_secondary>
+ </error>
+
+ <error id="folder-generic-error" type="error">
+ <_primary>Generic error</_primary>
+ </error>
+
+</error-list>
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]