LIBCAMEL_REVISION=1
LIBCAMEL_AGE=0
-LIBEXCHANGE_STORAGE_CURRENT=3
-LIBEXCHANGE_STORAGE_REVISION=0
-LIBEXCHANGE_STORAGE_AGE=0
-
LIBGDATA_CURRENT=1
LIBGDATA_REVISION=0
LIBGDATA_AGE=0
AC_SUBST(LIBCAMEL_CURRENT)
AC_SUBST(LIBCAMEL_REVISION)
AC_SUBST(LIBCAMEL_AGE)
-AC_SUBST(LIBEXCHANGE_STORAGE_CURRENT)
-AC_SUBST(LIBEXCHANGE_STORAGE_REVISION)
-AC_SUBST(LIBEXCHANGE_STORAGE_AGE)
AC_SUBST(LIBGDATA_CURRENT)
AC_SUBST(LIBGDATA_REVISION)
AC_SUBST(LIBGDATA_AGE)
fi
AM_CONDITIONAL(SUNLDAP, [test "$with_sunldap" != no])
- SAVE_CFLAGS="$CFLAGS"
- SAVE_LIBS="$LIBS"
- LDAP_CFLAGS="$LDAP_CFLAGS -DLDAP_DEPRECATED"
- CFLAGS="$CFLAGS $LDAP_CFLAGS"
- LIBS="$LIBS $LDAP_LIBS"
- AC_CHECK_FUNCS(ldap_ntlm_bind)
- CFLAGS="$SAVE_CFLAGS"
- LIBS="$SAVE_LIBS"
- dnl You need to enable LDAP and Kerberos to enable Exchange support in e-d-s
- msg_no_ntlm="no"
- msg_exchange="no"
- if test "$msg_ldap" != "no" ; then
- if test "$ac_cv_func_ldap_ntlm_bind" != no ; then
- msg_exchange="yes"
- else
- dnl The user wanted to build with openldap, but his openldap did not have NTLM
- dnl support. Make him aware of this with a warning message at the end.
- msg_no_ntlm="yes"
- fi
- fi
else
dnl Win32 LDAP support
LDAP_CFLAGS="-DLDAP_DEPRECATED"
AM_CONDITIONAL(ENABLE_LDAP, true)
AM_CONDITIONAL(SUNLDAP, false)
msg_ldap="yes"
- msg_no_ntlm="no"
- msg_exchange="yes"
fi
DBUS_GLIB_REQUIRED=dbus_glib_minimum_version
servers/Makefile
servers/groupwise/Makefile
servers/groupwise/libegroupwise.pc
-servers/exchange/Makefile
-servers/exchange/xntlm/Makefile
-servers/exchange/lib/Makefile
-servers/exchange/storage/Makefile
-servers/exchange/storage/libexchange-storage.pc
servers/google/Makefile
servers/google/libgdata/Makefile
servers/google/libgdata/libgdata.pc
SSL support: $msg_ssl
SMIME support: $msg_smime
IPv6 support: $msg_ipv6
- Exchange support: $msg_exchange
Dot Locking: $msg_dot
File Locking: $msg_file
Large files: $enable_largefile
IMAPX support: $msg_imapx
"
fi
-
-if test "$msg_no_ntlm" != "no" ; then
- echo ""
- AC_MSG_WARN([
-No NTLM support in OpenLDAP; Plaintext password authentication will be
-used when connecting to the Exchange Global Catalog server. Consider
-installing the evo-openldap package, or building OpenLDAP with the
-patch in servers/exchange/docs/openldap-ntlm.diff
-])
-fi
libedataserverui/e-name-selector-list.c
libedataserverui/e-passwords.c
libedataserverui/e-source-selector-dialog.c
-servers/exchange/lib/e2k-autoconfig.c
-servers/exchange/lib/e2k-security-descriptor.c
-servers/exchange/lib/e2k-sid.c
-servers/exchange/storage/e-storage.c
-servers/exchange/storage/exchange-account.c
-servers/exchange/storage/exchange-hierarchy-foreign.c
servers/groupwise/e-gw-connection.c
-if ENABLE_LDAP
-EXCHANGE = exchange
-else
-EXCHANGE =
-endif
-
-SUBDIRS = groupwise $(EXCHANGE) google
+SUBDIRS = groupwise google
+++ /dev/null
-2009-04-24 Milan Crha <mcrha@redhat.com>
-
- ** Part of fix for bug #569652
-
- * storage/exchange-esource.c: (find_account_group),
- (add_folder_esource): Do not use deprecated
- e_source_list_peek_group_by_name and add
- account's uid as a group property.
-
-2009-04-08 Milan Crha <mcrha@redhat.com>
-
- * storage/exchange-esource.c: (add_folder_esource):
- Do not disable alarm notifications for foreign calendars fully,
- only do not notify for them by default.
-
-2009-02-26 Matthew Barnes <mbarnes@redhat.com>
-
- ** Fixes part of bug #572950
-
- * lib/Makefile.am:
- * storage/Makefile.am:
- Fix ordering of -I compiler directives. Patch by Daniel Macks.
-
-2009-02-10 Matthew Barnes <mbarnes@redhat.com>
-
- ** Fixes bug #570653
-
- * storage/exchange-hierarchy-foreign.c:
- Kill n_std_folders and use G_N_ELEMENTS (std_folders) instead.
-
-2009-02-09 Milan Crha <mcrha@redhat.com>
-
- ** Part of fix for bug #555888
-
- * lib/e2k-context.c: (proxy_settings_changed), (e2k_context_set_auth):
- EProxy API changed, use e_proxy_peek_uri_for now.
-
-2009-01-14 Matthew Barnes <mbarnes@redhat.com>
-
- ** Fixes part of bug #564543
-
- * lib/e2k-context.c (e2k_context_set_auth):
- Call soup_session_add_feature() instead of soup_logger_attach().
-
- * lib/e2k-context.c (e2k_context_fba):
- Call soup_form_encode_hash() instead of soup_form_encode_urlencoded().
-
-2009-01-12 Chow Loong Jin <hyperair@gmail.com>
-
- ** Fix for bug #518920
-
- * servers/exchange/lib/e2k-context.c (e2k_context_fba):
- Handle relative URIs in value of action attribute of form in
- form-based authentication.
-
-2008-12-02 Milan Crha <mcrha@redhat.com>
-
- ** Fix for bug #562228
-
- * lib/e2k-autoconfig.c: (validate): Always store correct owa_path when
- validating, without trailing slash and without mailbox name.
-
-2008-10-19 Milan Crha <mcrha@redhat.com>
-
- ** Fix for bug #553944
-
- * lib/e2k-context.c: (unsubscribe_internal), (destroy_sub_list),
- (e2k_context_unsubscribe): Do not unsubscribe from the server when
- destroying context and make copy of the uri, because it comes from
- the structure we are going to free.
-
-2008-10-19 Milan Crha <mcrha@redhat.com>
-
- ** Fix for bug #544141
-
- * storage/exchange-account.c: (set_sf_prop): Do not store invalid
- values in 'standard_uris', it leads to crash later.
-
-2008-09-25 Milan Crha <mcrha@redhat.com>
-
- * storage/exchange-account.c: Removed unused header.
-
-2008-08-18 Milan Crha <mcrha@redhat.com>
-
- ** Part of fix for bug #324203
-
- * storage/exchange-account.h: (exchange_account_get_account_uri_param):
- * storage/exchange-account.c: (exchange_account_get_account_uri_param):
- New function to retrieve account's source url params easily.
- * storage/exchange-esource.c: (add_folder_esource):
- Update GAL source's "can-browse" property properly.
-
-2008-08-14 Milan Crha <mcrha@redhat.com>
-
- ** Fix for bug #337503
-
- * storage/exchange-hierarchy-webdav.c: (xfer_folder):
- Do not unref new folder, it's owned by the hierarchy.
- * storage/exchange-account.c: (struct _ExchangeAccountPrivate), (init),
- (dispose), (exchange_account_rescan_tree), (hierarchy_new_folder),
- (exchange_account_get_folders), (exchange_account_get_folder_tree):
- Removed unused variable and related code.
- * storage/exchange-account.c: (hierarchy_removed_folder):
- Do not unref more times than we actually reffed it before.
-
-2008-08-12 Milan Crha <mcrha@redhat.com>
-
- ** Part of fix for bug #547308
-
- * lib/e2k-global-catalog.c: (connect_ldap): Better warning on console.
- * lib/e2k-global-catalog-ldap.h: (e2k_global_catalog_get_ldap):
- * lib/e2k-global-catalog.c: (e2k_global_catalog_get_ldap):
- Return also ldap error if requested.
-
-2008-07-30 Milan Crha <mcrha@redhat.com>
-
- * lib/e2k-global-catalog.c: (connect_ldap):
- Removed debug printf added in the last commit.
-
-2008-07-30 Milan Crha <mcrha@redhat.com>
-
- ** Part of fix for bug #500389
-
- * lib/actest.c: (test_main):
- * lib/test-utils.c: (test_get_gc):
- * lib/e2k-validate.h: (enum E2kAutoconfigGalAuthPref),
- (struct ExchangeParams): New enum to setup GAL authentication method.
- * storage/exchange-account.c: (struct _ExchangeAccountPrivate),
- (exchange_account_connect), (exchange_account_new):
- * lib/e2k-autoconfig.c: (e2k_autoconfig_new),
- (e2k_autoconfig_set_owa_uri), (e2k_autoconfig_set_gc_server),
- (e2k_autoconfig_get_global_catalog), (set_account_uri_string):
- * lib/e2k-autoconfig.h: (struct E2kAutoconfig),
- (e2k_autoconfig_set_gc_server):
- * lib/e2k-global-catalog.h: (e2k_global_catalog_new):
- * lib/e2k-global-catalog.c: (struct _E2kGlobalCatalogPrivate),
- (connect_ldap), (e2k_global_catalog_new):
- New ability to set different authentication type to GAL and OWA.
-
- * lib/e2k-context.c: (e2k_soup_message_new_full):
- Do not crash on invalid uri.
-
-2008-06-16 Milan Crha <mcrha@redhat.com>
-
- ** Part of fix for bug #273627
-
- * lib/e2k-autoconfig.c: (validate):
- Use mailbox value from ExchangeParams structure if set, otherwise
- extract mailbox from the home_uri as before.
-
-2008-05-26 Milan Crha <mcrha@redhat.com>
-
- ** Fix for bug #473658
-
- * lib/e2k-properties.c: (copy_prop), (properties_free_cb),
- (get_propinfo), (foreach_callback), (foreach_namespace_callback),
- (e2k_prop_namespace_name), (e2k_prop_namespace_abbrev): Added locks
- to guard global variables 'known_properties' and 'namespaces'.
-
-2008-05-02 Bharath Acharya <abharath@novell.com>
-
- ** Fix for bug #530763
-
- * lib/e2k-context.c: (e2k_context_transfer_start):
- * lib/e2k-utils.c: (e2k_strdup_with_trailing_slash): Return NULL if the
- value of dest_folder is disturbed to prevent the crash.
-
-2008-04-29 Milan Crha <mcrha@redhat.com>
-
- ** Fix for bug #502899
-
- * storage/exchange-account.c: (struct _ExchangeAccountPrivate), (init),
- (dispose), (finalize), (exchange_account_rescan_tree), (get_folder),
- (hierarchy_new_folder), (hierarchy_removed_folder), (context_redirect),
- (get_parent_and_name), (exchange_account_get_folder),
- (exchange_account_get_folders), (exchange_account_get_folder_tree):
- Guard private folder's hash tables with a lock to prevent access to
- them from different threads in same the time.
-
-2008-03-27 Matthew Barnes <mbarnes@redhat.com>
-
- ** Fixes bug #500389
-
- * lib/e2k-global-catalog.c (connect_ldap):
- Fall back to simple binds if the global catalog server
- does not support NTLM binds.
-
-2008-03-25 Veerapuram Varadhan <vvaradhan@novell.com>
-
- ** Added configurable Proxy settings for Evolution.
-
- * lib/e2k-context.c: (proxy_settings_changed), (init), (dispose),
- (e2k_context_set_auth):
-
-2008-03-24 Matthew Barnes <mbarnes@redhat.com>
-
- ** Fixes bug #523023
-
- * storage/exchange-hierarchy-webdav.c (scan_subtree):
- Fix a severe EFolder reference count leak.
-
-2008-02-25 Matthew Barnes <mbarnes@redhat.com>
-
- * lib/e2k-kerberos.c (get_init_cred):
- Fix a couple discarded const warnings.
-
-2008-02-12 Matthew Barnes <mbarnes@redhat.com>
-
- * storage/exchange-account.c:
- Fix another G_GNUC_PRETTY_FUNCTION straggler.
-
-2008-02-06 Matthew Barnes <mbarnes@redhat.com>
-
- ** Fixes part of bug #514682
-
- * lib/Makefile.am:
- * storage/Makefile.am:
- Fix a compilation error that occurs when building in a
- remote object directory (#514682, patch by Paul Smith).
-
-2008-02-04 Dan Winship <danw@gnome.org>
-
- * lib/e2k-context.c (session_authenticate): Only authenticate the
- auth once; if we're called again, let it fail, since the cached
- password must be incorrect. #513646.
-
-2008-01-30 Milan Crha <mcrha@redhat.com>
-
- ** Part of fix for bug #395939
-
- * lib/e2k-context.c: (dispose): Memory leak fix.
-
-2008-01-27 Dan Winship <danw@gnome.org>
-
- * lib/e2k-context.c (e2k_context_fba): Fix a double free. #511301.
-
-2008-01-24 Milan Crha <mcrha@redhat.com>
-
- ** Fix for bug #511235
-
- * lib/e2k-context.c: (session_authenticate):
- Changed prototype to reflect actual libsoup.
- Thanks to Dan Winship for pointing this out.
-
-2008-01-17 Kjartan Maraas <kmaraas@gnome.org>
-
- * lib/e2k-context.h: Correct the function signature of
- e2k_soup_message_new_full() so things build.
-
-2008-01-15 Dan Winship <danw@gnome.org>
-
- * lib/e2k-autoconfig.c: Update for libsoup 2.4
-
- * lib/e2k-context.c: Update for libsoup 2.4
- (e2k_context_fba): Use soup-forms methods.
- (setup_message): Rewrite the old SoupMessageFilter-based stuff to
- use SoupSession::request-started instead.
- (e2k_context_get, e2k_context_get_owa): Return a SoupBuffer
- directly rather than returning a char * and length.
-
- * lib/e2k-http-utils.c (e2k_http_get_headers): kludge to get
- around the auto-header-merging behavior of SoupMessageHeaders,
- which makes it hard to parse WWW-Authenticate and Set-Cookie.
-
- * storage/exchange-oof.c (find_str_case, exchange_oof_get):
- Update for e2k_context_get_owa() change. Rewrite to not modify the
- response body, to avoid needing an extra strdup.
-
-2008-01-12 Srinivasa Ragavan <sragavan@novell.com>
-
- ** Fix for bug #361972
-
- * lib/e2k-context.c: (e2k_context_fba): No point crashing if the
- action is not recognised by soup. So if the message is null return.
-
-2007-12-31 Sushma Rai <rsushma@novell.com>
-
- ** Fixes bug #327965
-
- * storage/exchange-account.[ch] (exchange_account_get_windows_domain):
- Added new, to return the windows domain value.
-
- * storage/exchange-esource.c (add_folder_esource): Setting the e-source
- property username with the domain, if the domain is specified.
-
-2007-12-06 Tobias Mueller <tobiasmue@svn.gnome.org>
- Patch by Milan Crha <mcrha@redhat.com>
-
- ** Fix for bug #462593
-
- * lib/e2k-context.c: (e2k_soup_message_new): Print message on console
- if invalid uri has been passed to soup_message_new.
- * lib/e2k-autoconfig.c: (e2k_autoconfig_get_context):
- Prevent from crash on invalid uri.
-
-2007-11-15 Matthew Barnes <mbarnes@redhat.com>
-
- * lib/e2k-autoconfig.c (get_ctx_auth_handler):
- * lib/e2k-result.c (prop_get_binary_array), (prop_get_binary):
- Initialize 'length' before calling g_base64_decode().
-
-2007-10-27 Matthew Barnes <mbarnes@redhat.com>
-
- * lib/e2k-user-dialog.c:
- * lib/e2k-user-dialog.h:
- Remove these dead files from SCM.
-
-2007-10-03 Srinivasa Ragavan <sragavan@novell.com>
-
- ** Fix for BNC bug #203480
-
- * storage/exchange-account.c: Compiler warning for usage of
- unintialized variable.
-
-2007-09-28 Matthew Barnes <mbarnes@redhat.com>
-
- * lib/e2k-context.c (write_prop):
- * lib/e2k-autoconfig.c (get_ctx_auth_handler):
- * lib/e2k-result.c (prop_get_binary_array), (prop_get_string_array):
- Use GLib's Base64 API instead of e2k_base64_encode() and
- e2k_base64_decode(). Straggler from bug #474000.
-
-2007-09-28 Matthew Barnes <mbarnes@redhat.com>
-
- * storage/exchange-account.c:
- * lib/e2k-context.c:
- * lib/e2k-autoconfig.c:
- * lib/e2k-result.c:
- Remove #include "e2k-encoding-utils.h"
-
-2007-09-27 Matthew Barnes <mbarnes@redhat.com>
-
- ** Fixes part of bug #474000
-
- * lib/Makefile.am:
- * lib/e2k-encoding-utils.c:
- * lib/e2k-encoding-utils.h:
- Remove redundant Base64 codec implementation.
-
-2007-09-03 Veerapuram Varadhan <vvaradhan@novell.com>
-
- * storage/exchange-hierarchy-webdav.c: Check for validity of
- deleted_items_uri before using it. Fixes a crash that happens
- when started in calendar mode. Have seen some BGO traces showing
- it - but do not have the bug-id atm. Will close them later.
-
-2007-09-03 Veerapuram Varadhan <vvaradhan@novell.com>
-
- ** Fixes #290330 (bnc)
- * storage/exchange-hierarchy-webdav.c: Fetch FOLDER_CLASS and
- PERMANENT_URL properties for public folders as well.
-
-2007-08-29 Chenthill Palanisamy <pchenthill@novell.com>
-
- Fixes #301263 (bnc)
- * storage/exchange-account.[ch]: Added a new function
- to scan foriegn folder hierarchy.
- * storage/exchange-esource.c: (add_folder_esource):
- Set the foriegn folder property.
-
-2007-08-24 Milan Crha <mcrha@redhat.com>
-
- ** Fix for bug #381548 from John D. Ramsdell
-
- * lib/e2k-context.c: (e2k_context_fba):
- Make fail with zero-length action string like with NULL.
-
-2007-08-10 Milan Crha <mcrha@redhat.com>
-
- ** Fix for bug #327977
-
- * lib/e2k-validate.h: (e2k_validate_user):
- * lib/e2k-autoconfig.c: (e2k_validate_user):
- Added parameter for parent window to pass to password dialog.
-
-2007-08-03 Jeff Cai<jeff.cai@sun.com>
-
- * storage/exchange-account.c:
- Not print debug information.
- Fix #439147
-
-2007-07-09 Chenthill Palanisamy <pchenthill@novell.com>
-
- * storage/exchange-account.c:
- * storage/exchange-account.h: (exchange_account_fetch): Fetch
- the EAaccount from the exchange account.
- * storage/exchange-esource.c: (add_folder_esource): Added the subscriber's
- email id to corresponding esource.
-
- Committing on behalf of Suman Manjunath <msuman@novell.com> and
- Bharath Acharya <abharath@novell.com>
-
-2007-07-03 Srinivasa Ragavan <sragavan@novell.com>
-
-
- * lib/e2k-autoconfig.c: (e2k_validate_user): Have the full url to
- avoid asking the password again.
- * lib/e2k-validate.h:
-
-2007-06-15 Matthew Barnes <mbarnes@redhat.com>
-
- * storage/exchange-hierarchy-webdav.c (xfer_folder):
- Duplicate the string returned from e_folder_get_physical_uri()
- (#312854).
-
-2007-06-04 Veerapuram Varadhan <vvaradhan@novell.com>
-
- ** Fixes #415922
- * lib/e2k-autoconfig.c (e2k_autoconfig_get_context): Add support
- for Microsoft ISA Server 2004 proxy URLs.
- * lib/e2k-context.c (e2k_context_fba): Decode the URI - just incase.
-
-2007-05-15 Ross Burton <ross@openedhand.com>
-
- * lib/e2k-user-dialog.c:
- Remove bonobo includes, they are not used.
-
-2007-05-09 Srinivasa Ragavan <sragavan@novell.com>
-
- * lib/e2k-utils.c: Fix for build break.
-
-2007-05-07 Matthew Barnes <mbarnes@redhat.com>
-
- * lib/e2k-rule-xml.c:
- * lib/e2k-rule.h:
- * lib/e2k-security-descriptor.c:
- * lib/e2k-utils.c:
- * storage/e-folder-exchange.c:
- Fix warnings reported by 'sparse'. Patch from Kjartan Maraas.
-
-2007-04-05 Matthew Barnes <mbarnes@redhat.com>
-
- * lib/e2k-marshal.list:
- Turns out, evolution-exchange still needs NONE:INT,INT.
-
-2007-04-05 Ross Burton <ross@openedhand.com>
-
- * storage/e-folder-exchange.c:
- Use g_mkdir_with_parents (#383686).
-
-2007-04-04 Ross Burton <ross@openedhand.com>
-
- * storage/exchange-hierarchy.c:
- * storage/e-shell-marshal.list:
- * storage/exchange-account.c:
- * storage/e-storage.c:
- * storage/exchange-hierarchy-somedav.c:
- * storage/e-folder.c:
- * storage/Makefile.am:
- * lib/e2k-marshal.list:
- Remove marshallers that are in GLib already (#400970).
-
-2007-04-01 Matthew Barnes <mbarnes@redhat.com>
-
- ** Various code clean-ups from Kjartan Maraas.
-
- * storage/exchange-account.h (exchange_account_set_password):
- Function declaration should not be subject to conditional compilation.
-
- * storage/e-folder-type-registry.c
- (e_folder_type_registry_get_display_name_for_type),
- (e_folder_type_registry_get_description_for_type):
- Return NULL, not FALSE.
-
- * lib/e2k-rule-xml.c: Declare private arrays as static.
-
- * lib/e2k-context.c (e2k_context_new), (e2k_debug_print_request),
- (e2k_debug_print_response): Use NULL instead of zero (0).
-
- * lib/e2k-context.c (do_notification):
- g_io_channel_read_chars() returns GIOStatus, not GIOError.
-
- * lib/e2k-autoconfig.c (e2k_autoconfig_check_exchange):
- Fix a compiler warning.
-
-2007-03-26 Matthew Barnes <mbarnes@redhat.com>
-
- * storage/e-folder-exchange.c:
- Don't mix declarations and code (#405495).
- Patch from Jens Granseuer.
-
-2007-03-16 Matthew Barnes <mbarnes@redhat.com>
-
- ** Fixes part of bug #360240
-
- * storage/exchange-hierarchy-webdav.c (scan_subtree):
- * storage/exchange-account.c (add_folder_tree):
- * lib/e2k-uri.c (e2k_uri_new):
- Remove unused variables.
-
-2007-01-08 Chenthill Palanisamy <pchenthill@novell.com>
-
- * storage/exchange-account.[ch]: (exchange_account_get_hierarchy_by_email):
- Added a new API to get the foreign user's folder hierarchy.
- (exchange_account_get_hierarchy): Changed the name to exchange_account_get_hierarchy_by_type.
-
-2006-12-19 Jeff Cai <jeff.cai@sun.com>
-
- ** Fix for 387397
-
- * storage/exchange-account.c: Change macro definitions to
- satisfy both linux and Solaris.
-
-2006-12-18 Veerapuram Varadhan <vvaradhan@novell.com>
-
- * storage/e-folder-exchange.c: (init): Initialize rescan_tree to
- TRUE
-
-2006-12-18 Veerapuram Varadhan <vvaradhan@novell.com>
-
- ** Missed changes
-
- * storage/exchange-types.h: Moved ExchangeHierarchyTypes enum
- here.
-
-2006-12-18 Veerapuram Varadhan <vvaradhan@novell.com>
-
- ** Fix for 346728, 268412
-
- * storage/exchange-hierarchy.h: Move ExchangeHierarchyTypes to
- exchange-types.h
-
- * storage/exchange-hierarchy-webdav.c: (scan_subtree): Do not
- rescan a tree/folder when its rescan_tree is set to FALSE. Also,
- just fetch DISPLAY_NAME and HAS_SUBS properties for public
- folders.
-
- * storage/exchange-account.[ch]: (exchange_account_get_hierarchy):
- Added to return hierarchy for a given type.
- (exchange_account_get_folder_tree): Returns a tree of folders
- for the requested URI/PATH.
-
- * storage/e-folder-exchange.[ch]:
- (e_folder_exchange_get_rescan_tree): Returns rescan_tree flag.
- (e_folder_exchange_set_rescan_tree): Sets rescan_tree flag.
-
-2006-12-13 Veerapuram Varadhan <vvaradhan@novell.com>
-
- ** Fix for bnc #208395
-
- * storage/exchange-hierarchy-webdav.c: (e_folder_webdav_new):
- * storage/e-folder-exchange.c: (e_folder_exchange_new):
- Folder name can contain any characters including URI special
- characters, encode it and use it as physical uri.
-
-2006-11-15 Chenthill Palanisamy <pchenthill@novell.com>
-
- * storage/exchange-account.c:
- (exchange_account_connect): Check if the mode is unsupported
- and reset the connecting variable.
- Fixes #219729 (bugzilla.novell.com)
-
-2006-11-07 Chenthill Palanisamy <pchenthill@novell.com>
-
- * storage/exchange-constants.h: Define a flag to
- indicate the foriegn folder.
- * storage/exchange-esource.c: (add_folder_esource):
- Disable alarms for foriegn folders.
- * storage/exchange-hierarchy-foreign.c:
- (exchange_hierarchy_foreign_add_folder):
- Pass the masked value for the folder type.
- Fixes #208318 (bugzilla.novell.com)
-
-2006-11-07 Chenthill Palanisamy <pchenthill@novell.com>
-
- Fixes the removal of properties.
- * lib/e2k-context.c: (write_prop): Do not check for the
- existance of the value while removing the properties.
- Fixes #207960 (buzilla.novell.com)
-
-2006-10-12 Srinivasa Ragavan <sragavan@novell.com>
-
- ** Fix for #bug 347811
-
- * storage/exchange-account.c: Reverting Varadhan's last commit to
- lookup hierarchies based on offline settings, and makeing that as
- FALSE. Reopening bug #268412
-
-2006-09-30 Veerapuram Varadhan <vvaradhan@novell.com>
-
- ** Fixes #347811
- * storage/exchange-account.c (setup_account_hierarchies): While
- creating hierarchies for the folders, set offline_supported with
- the account level settings.
-
-2006-07-24 Veerapuram Varadhan <vvaradhan@novell.com>
-
- * lib/e2k-context.c (e2k_context_set_auth): Create SoupSessionSync
- with a default timeout of 30 secs.
-
-2006-07-24 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-account.h: Added two more error codes
- ExchangeAccountFolderResult.
-
- * storage/exchange-account.c (exchange_account_discover_shared_folder):
- Return proper error codes when GC server is NULL or invalid username
- is selected. Fixes #234359.
-
-2006-07-24 Sushma Rai <rsushma@novell.com>
-
- * storage/Makefile.am: Added exchange-esource.h to
- libexchange_storageinclude_HEADERS. See #313081.
-
-2006-07-22 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-account.[ch]: Added a new API to read the e-mail id
- from the given ExchangeAccount. Fixes #311322.
- Patch submitted by "Vandana Shenoy .B <shvandana@novell.com>"
-
-2006-05-11 Chenthill Palanisamy <pchenthill@novell.com>
-
- Fixes #334626
- * storage/exchange-esource.c:
- (add_folder_esource): set the list of calendar selections
- in gconf for the newly created source.
-
-2006-05-10 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-account.c (setup_account_hierarchies): Setting
- parameter "deep_searchable" to TRUE for favorite folders, so that we
- scan for the sub folders if a public folder has sub folders.
-
- * storage/exchange-hierarchy-favorites.c
- (exchange_hierarchy_favorites_new): Similar.
- Fixes #268412.
-
-2006-05-10 Sushma Rai <rsushma@novell.com>
-
- * exchange/lib/e2k-autoconfig.c (e2k_validate_user): Set result to
- E2K_AUTOCONFIG_CANCELLED on cancel. Fixes #332131.
-
-2006-04-19 Harish Krishnaswamy <kharish@novell.com>
-
- Patch suggested by Carlos Lozano <clozano at andago dot com>
-
- * storage/exchange-account.c (is_password_expired),
- (exchange_account_set_password): Ensure checks for expiry or
- weakness take effect while trying for nt domain. The conditionals
- should be AND'ed not OR'ed.
-
-2006-04-18 Sushma Rai <rsushma@novell.com>
-
- * lib/e2k-uri.c (e2k_uri_new): Reverting the changes made for extracting
- the user name and domain names from user name provided, which is in the
- form of email id. Now we are doung it during account creation itself.
-
- * lib/e2k-validate.h: Changed the signature of e2k_validate_user().
-
- * lib/e2k-autoconfig.c (e2k_validate_user): Authenticating with the
- username provided, and if it fails and username is of the form
- user@domain, extracting the username from it and trying once more.
- Fixes #329371.
-
-2006-04-06 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-hierarchy-webdav.c (xfer_folder): Removing the
- separator from the folder name.
-
-2006-03-06 Irene Huang <Irene.Huang@sun.com>
-
- Fixes bug #331633
-
- * lib/e2k-global-catalog.c: (find_domain_dn): Check and see if
- dn_value->str[0] is nil before duplicating.
-
-2006-03-06 Sushma Rai <rsushma@novell.com>
-
- * storage/e-folder-exchange.c (e_folder_exchange_new_from_file):
- Freeing xml doc and xml property. See #329251.
-
-2006-03-06 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-oof.c (exchange_oof_get): Initialize variables.
-
- * lib/e2k-context.c (e2k_context_fba): Similar. See #329251.
-
-2006-03-06 Sushma Rai <rsushma@novell.com>
-
- * lib/e2k-autoconfig.c (e2k_autoconfig_get_context): Freeing old value
- of home_uri beofre storing the new value.
- (e2k_autoconfig_check_exchange): Freeing xml property. See #329251.
-
- * storage/exchange-account.c (exchange_account_connect): Not
- duplicating password string. See #329251.
-
-2006-03-06 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-esource.c (is_offline): Freeing GconfValue,
- See #329251.
-
-2006-03-06 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-account.c (exchange_account_connect): Skip the quota
- limit warning display if the GC server is missing. If the quota limits
- are set on the account, and GC server field is missing,
- sending/receiving mails would fail, based on quota settings.
- Fixes #333163.
-
-2006-02-25 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-hierarchy-webdav.c (scan_subtree): Do not unref the
- folder which is being used later in subtrees.
-
-2006-02-13 Chenthill Palanisamy <pchenthill@novell.com>
-
- * storage/exchange-hierarchy-webdav.c: (init),
- (hierarchy_new_folder): Ref the folder before inserting so that it
- doesn't die on before removing. Fixes #326413.
-
-2006-02-10 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-esource.c (add_folder_esource): Calling
- e_source_sync() only when we set the property.
-
-2006-02-06 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-account.c (exchange_account_connect): Freeing
- E2kResult.
-
- * storage/e-folder-exchange.c (e_folder_exchange_save_to_file):
- Returning on NULL uris or folder name, before finding the folder size.
- Also freeing folder size string.
-
- * storage/exchange-hierarchy-favorites.c (get_hrefs): Initializing
- nresults to zero.
-
- * storage/exchange-oof.c (exchange_oof_get): Similar.
-
- * lib/e2k-freebusy.c (e2k_freebusy_new): Similar.
-
- * storage/exchange-hierarchy-foreign.c (check_hide_private)
- (find_folder): Initializing nresults to zero and Freeing E2kResult.
-
- * storage/exchange-hierarchy-somedav.c
- (exchange_hierarchy_somedav_add_folder): Similar.
-
- * storage/exchange-hierarchy-webdav.c (scan_subtree): Unrefing folder.
-
- * storage/exchange-esource.c (add_folder_esource): Freeing authtype.
- Fixes #329251.
-
-2006-01-31 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-account.c (hierarchy_new_folder): Removed the debug
- messages. Fixes #327428
-
-2006-01-27 Sushma Rai <rsushma@novell.com>
-
- * lib/e2k-uri.c (e2k_uri_new): Checking if the user name entered is
- e-mail id and extracting the user name and domain from it.
- Fixes #323637.
-
-2006-01-18 Sushma Rai <rsushma@novell.com>
-
- * lib/e2k-autoconfig.c (e2k_validate_user): Whenever the authenticate
- button is pressed, always prompt for password. Fixes #327292.
-
-2006-01-14 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-esource.c (add_folder_esource): Marking the GAL
- folder for autocompletion, while creating it. Fixes #303998.
-
-2006-01-14 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-constants.h: using API_VERSION for Exchange
- Connector book and calendar factories. See #323115.
-
-2006-01-12 Sushma Rai <rsushma@novell.com>
-
- * lib/e2k-autoconfig.c (e2k_validate_user): Freeing password string.
-
- * storage/exchange-account.c (display_passwd_expiry_message)
- (change_passwd_cb): Removed these unused functions.
- (find_passwd_exp_period): Retruning max_pwd_age_days or error instead of
- invoking display_passwd_expiry_message().
- (exchange_account_connect): Freeing E2KAutoconfig structure.
- (exchange_account_check_password_expiry): Implemeted. Returns password validity
- period. Fixes #326060.
-
-2006-01-10 Simon Zheng <simon.zheng@sun.com>
-
- * lib/e2k-autoconfig.c:
- * storage/e-folder-exchange.c:
- * storage/e-folder.c:
- * storage/e-storage.c:
- As file e-util.h is renamed, replace "libedataserver/e-util.h"
- as "libedataserver/e-data-server-util.h".
-
-2005-12-21 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-esource.c (add_folder_esource): Calling
- e_source_list_sync() after updating the offline status of the existing
- source.
-
- * storage/exchange-account.h: Exposing exchange_account_get_authtype(),
- which is now used from exchange-operations plugin.
-
-2005-12-19 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-account.[ch] (exchange_account_set_save_password):
- Sets the flag in EAccount to TRUE if user has selected save password.
- (exchange_account_is_save_password): Returns the save_passwd flag
- value. Setting this value was missed in evolution 2.4
-
-2005-12-19 Sushma Rai <rsushma@novell.com>
-
- * lib/e2k-autoconfig.c (validate): Free E2kAutoconfig structure.
- Fixes #324483.
-
-2005-12-17 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-account.c: Using the integer varable
- "account_online" to store the mode, instead of boolean. This fixes the
- problem of comparing account_online value (TRUE/FALSE) with
- OFFLINE_MODE/ONLINE_MODE (1/2).
- (exchange_account_rescan_tree)(exchange_account_open_folder)
- (exchange_account_set_offline)(exchange_account_is_offline)
- (setup_account_hierarchies)(exchange_account_connect): Similar.
-
- * storage/exchange-hierarchy.[ch] (scan_subtree)
- (exchange_hierarchy_scan_subtree): Similar.
-
- * storage/exchange-hierarchy-webdav.c (xfer_folder)(rescan)
- (scan_subtree): Similar.
-
- * storage/exchange-hierarchy-foreign.c (scan_subtree): Similar.
-
- * storage/exchange-hierarchy-somedav.c (scan_subtree): Similar.
- This fixes the problem of not loading the folders after creating an
- account, even if the user is authenticated. Fixes #322657.
-
-2005-12-17 Sushma Rai <rsushma@novell.com>
-
- * lib/e2k-autoconfig.c (e2k_validate_user): Corrected the key by
- adding the trailing slash.
-
- * storage/exchange-account.c (exchange_account_new): Using the proper
- password key so that during account creation password will not be asked
- for the second time at the end. Fixes #322657.
-
-2005-12-15 Sushma Rai <rsushma@novell.com>
-
- * lib/e2k-autoconfig.c (e2k_validate_user): Fixes the problem
- of validating and authenticating user only on pressing "Authenticate"
- button twice, even if the user gives the proper password.
-
-2005-12-11 Tor Lillqvist <tml@novell.com>
-
- * lib/Makefile.am: Drop unused CONNECTOR_LOCALEDIR.
-
- * lib/e2k-autoconfig.c
- * lib/e2k-context.c: Include appropriate headers on Win32.
-
- * lib/e2k-autoconfig.c: Drop inclusion of
- libedataserver/e-account.h and libedataserver/e-account-list.h,
- that API is not used here.
- (find_global_catalog): Add Win32 implementation.
- (find_olson_timezone): Use g_win32_getlocale() on Win32 instead of
- the usually nonexistent LANG environment variable.
- (read_config): Form path to connector.conf at run-time for the
- benefit of Win32 freely chosen end-user install location.
-
- * lib/e2k-autoconfig.c
- * lib/e2k-path.c
- * storage/e-folder-exchange.c
- * storage/exchange-hierarchy-foreign.c
- * storage/exchange-hierarchy-webdav.c: Use gstdio wrappers.
-
- * lib/e2k-context.c: Define strtok_r() using strtok() on Windows,
- where strtok() is MT-safe. Wrap socket API calls with simple
- macros for Unix/Winsock portability. Use
- g_io_channel_win32_new_socket() on Windows.
-
- * lib/e2k-global-catalog-ldap.h: Include winldap.h on Windows. Add
- some OpenLDAP macros that aren't present in winldap.h.
-
- * lib/e2k-global-catalog.c: Remove duplicate inclusion of ldap.h,
- it's already included by e2k-global-catalog-ldap.h
- (finalize): g_free() works fine on NULL pointers.
- (connect_ldap, get_ldap_connection): Rename ldap_connect() to
- connect_ldap() to avoid clash with the ldap_connect() function in
- the LDAP API.
- (connect_ldap): Use WINNT authentication on Windows.
-
- * lib/e2k-path.c (find_folders_recursive):
- * storage/exchange-account.c (setup_account_hierarchies): Use
- g_dir* instead of dirent API for portability.
-
- * storage/Makefile.am: Use NO_UNDEFINED (meaning -no-undefined on
- Windows). Link with all needed libraries for the benefit of
- -no-undefined.
-
- * storage/e-folder-exchange.c (e_mkdir_hier) Remove duplicate
- implementation, already have it as e_util_mkdir_hier() in
- libedataserver/e-util.c.
- (sanitize_path): Must return something in all cases, this function
- is not void. Why did gcc let this through with just a warning?
-
- * storage/e-folder-exchange.c
- * storage/exchange-hierarchy-foreign.c: Use e_xml_parse_file()
- instead of xmlParseFile(), as that doesn't take UTF-8 filenames on
- Windows. Use e_xml_save_file() for the same reason.
-
- * storage/e-folder-exchange.c (e_xml_get_child_by_name): Remove,
- now in libedataserver/e-xml-utils.c.
-
- * storage/exchange-account.c (exchange_account_set_password):
- Do compile even if not HAVE_KRB5, but always return failure. Means
- less ifdefs elsewhere.
- (e_filename_make_safe): Remove this function which isn't used,
- especially as there is an exact duplicate in evolution's
- e-util/e-util.c. If it eventually is needed also somewhere in
- e-d-s, move it to libedataserver instead.
-
-2005-12-12 Irene Huang <Irene.Huang@sun.com>
-
- * lib/e2k-autoconfig.c: (e2k_validate_user): If password
- exists, used the remembered password to do the
- authentification. If validation failed, forget password.
-
-2005-12-10 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-account.c (exchange_account_connect): set
- account->priv->connecting flag to FALSE on NULL password.
- Also removed unnecessary looping with try_password_again and also the
- commented out code.
-
-2005-12-08 Tor Lillqvist <tml@novell.com>
-
- * storage/e-shell-marshal.list: Add NONE:INT.
-
-2005-12-07 Tor Lillqvist <tml@novell.com>
-
- * storage/Makefile.am: Link with libedatasererui's bootstrap
- import library on Win32. Link also with libedataserver. Move
- libexchange.la and libxntlm.la from LDFLAGS to LIBADD. Install
- e-shell-marshal.h (for the benefit of evolution-exchange, which
- used to generate its own copy, but having several copies of the
- same file in different places is confusing).
-
-2005-11-26 Sushma Rai <rsushma@novell.com>
-
- * storage/exchange-account.c (exchange_account_remove_folder)
- (get_password)(exchange_account_connect): Fix for compile time warnings.
- (exchange_account_connect): Initialize the return value, info_result
- before cheking the validity of ExchangeAccount. Fixes a crash.
-
-2005-11-25 Tor Lillqvist <tml@novell.com>
-
- * lib/e2k-uri.c (e2k_uri_new)
- * storage/exchange-oof.c (find_str_case): Use
- g_ascii_strncasecmp() instead of strncasecmp() for portability.
-
-2005-10-21 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * storage/exchange-account.c (exchange_account_remove_folder) : Proceed
- with deletion of folder only if the folder being removed is *not* a
- standard folder. This fixes #312848.
-
-2005-10-20 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * lib : Add the test programs
- * lib/Makefile.am : Add the entries to compile these.
-
-2005-09-30 Arunprakash <arunp@novell.com>
-
- * storage/exchange-account.c (setup_account_hierarchies) : Skips the
- hierarchies creation if it is done.
- ** Fixes #312229.
-
-2005-08-26 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * lib/e2k-autoconfig.c (e2k_validate_user) : Fix the password key to
- be consistent with the camel key.
- * storage/e-folder-exchange.c (sanitize_path) : Strips the ';' in the
- path.
- * storage/exchange-account.c (get_hierarchy_for)
- (setup_account_hierarchies) : Fix the physical uri to delimit the
- folder path from the uri with a ';'
- (exchange_account_new) : Fix the uri authority to be same as the camel
- uri which would be later used in all components for creating the
- password key.
-
-2005-09-05 Praveen Kumar <kpraveen@novell.com>
-
- ** Fixes bug 314588.
-
- * lib/e2k-context.c (e2k_context_new) : Modified the constructor
- to return NULL if there is no host name in the SOUP URI.
-
-2005-09-14 Irene Huang <Irene.Huang@sun.com>
-
- Fix for bug #316274
-
- * storage/exchange-account.h: only declare exchange_account_set_
- password function when the macro HAVE_KRB5 is defined.
-
-2005-08-25 Arunprakash <arunp@novell.com>
-
- * storage/exchange-account.c (init) : set the default linestatus
- to offline.
- (exchange_account_rescan_tree) : Use the proper linestatus value.
- (exchange_account_set_offline) : Added lock before modifying
- the account linestatus to complete the connection in progress.
- (exchange_account_set_online) : Similar.
- (exchange_account_is_offline) : Return the proper linestatus.
-
-2005-08-25 Arunprakash <arunp@novell.com>
-
- * storage/exchange-account.c (hierarchy_new_folder) : Removes
- redundant computation.
-
-2005-08-22 Not Zed <NotZed@Ximian.com>
-
- * storage/exchange-esource.c (is_offline): provide a proper c
- prototype for this, () is pre-iso-c.
-
-2005-08-22 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * storage/exchange-account.c (get_password) : Store the password
- (exchange_account_connect) : Handle NULL password, and also move
- the mutex to the end of connect.
- * storage/exchange-esource.c (add_folder_esource) : Add the auth
- properties to the esources.
-
-2005-08-17 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * storage/exchange-account.c (exchange_account_get_folder): Lookup on
- NULL data is wrong. Handle it earlier.
- * storage/exchange-hierarchy-webdav.c (rescan) : Use
- E2K_PR_EXCHANGE_FOLDER_SIZE for getting the folder size.
- (scan_subtree): Similar. Also, dont scan the deleted items subtree.
-
-2005-08-12 Praveen Kumar <kpraveen@novell.com>
-
- * storage/exchange-esource.c
- (is_offline): Added new
- (add_folder_esource): Modified to add the calendar and tasks to
- the selected list only if the account is online. This is a part
- of the fix to the bug 237272.
-
-2005-08-02 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * storage/exchange-hierarchy-favorites.c (remove_folder) : Remove
- the esources only after we have removed the folder from the server.
- * storage/exchange-account.c (exchange_account_rescan_tree) : Add the
- toplevel folder of the hierarchy in the fresh folder list manually
- * storage/exchange-hierarchy-somedav.c (scan_subtree) : Temporary fix.
- Allow a rescan for now.
- * storage/exchange-esource.c (remove_folder_esource) : Handle the
- addressbook esource removal properly. We no longer use the absolute
- uri for addressbooks, except for GAL.
-
-2005-07-28 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * storage/exchange-account.c (is_password_expired) : This should be
- included only if kerberos is enabled in the configure options.
-
-2005-07-22 Praveen Kumar <kpraveen@novell.com>
-
- * storage/exchange-esource.c (add_folder_esource) : Modified the way
- of Exchange addressbook ESource URI handling to be the same way as
- calendar ESource URI handling except for "gal://" protocol
-
-2005-07-21 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * storage/Makefile.am : Add the separated esource handling code files.
- * storage/exchange-esource.[ch] : Added new
- * storage/e-folder-exchange.c : Reinclude the esource creation code.
- * storage/exchange-account.c : Add a new fresh_folder list. This has
- the latest list of folders available for the account, excluding the
- folders that were deleted in the current session.
- (exchange_account_rescan_tree) : Add a scan for fetching any new
- folders apart from scanning the existing folder properties.
- (exchange_account_get_folders): First check for the fresh_folder list
- if available and get the list from that.
- * storage/exchange-hierarchy-favorites.c : Reinclude the esource
- removal code.
- * storage/exchange-hierarchy-foreign.c : Similar
- * storage/exchange-hierarchy-gal.c : Similar
- * storage/exchange-hierarchy-webdav.c : Similar
-
-2005-07-15 Arunprakash <arunp@novell.com>
-
- * storage/exchange-account.c (exchange_account_connect) : Update the
- error value before looping. This fixes #310483.
-
-2005-07-14 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * storage/Makefile.am : Use the version-info
- * storage/exchange-account.c : Fix a warning
-
-2005-07-14 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * storage/exchange-hierarchy-foreign.c (remove_folder) : The esource
- removal should be moved to the eplugins code.
-
-2005-07-11 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- Initial patch submitted by Arun Prakash <arunp@novell.com>.
- * storage/exchange-account.c : The private ExchangeAccount structure
- now also stores the quota_limit which can be used by the plugins to
- display.
- (get_password) : Now returns the error status
- (exchange_account_set_password) : Similar
- (exchange_account_connect) : This now accepts a password for connecting
- and also returns the appropriate error code so that the plugins can
- print appropriate messages.
- (exchange_account_get_quota_limit) : Newly added.
- (exchange_account_check_password_expiry) : Newly added
- * storage/exchange-account.h : Added a new ExchangeAccountResult enum
- for returning the connection status. Also modified the appropriate
- function declarations.
-
-2005-07-11 Shakti Sen <shprasad@novell.com>
-
- * storage/Makefile.am: Included files exchange-hierarchy-foreign.c
- and exchange-hierarchy-foreign.h
- * storage/exchange-account.c: Added foreign hierarchy support.
- * storage/exchange-hierarchy-foreign.[ch]: Added newly for foreign
- hierarchy support.
-
-2005-07-08 Praveen Kumar <kpraveen@novell.com>
-
- * lib/Makefile.am : Added entry for ek-sid.h in the headers files to
- be installed
-
-2005-07-08 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * storage/Makefile.am : We should be using the CURRENT, REVISION and
- AGE variables for the version-info of the exchange library.
-
-2005-07-07 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * storage/e-folder-exchange.c : Remove dead code
- * storage/exchange-account.c : Make ExchangeFolderSize a member of
- ExchangeAccount. Also removed some dead codE
- (exchange_account_folder_size_add) (exchange_account_folder_size_remove)
- (exchange_account_folder_size_rename)
- (exchange_account_folder_size_get_model) : Added new
- * storage/exchange-account.h : Similar
- * storage/exchange-folder-size.c : Replaced E2K_MAKE_TYPE with
- G_DEFINE_TYPE and made necessary changes to init and class_init members
- (format_size_func)(parent_destroyed)(exchange_folder_size_display) :
- All moved to plugins.
- * storage/exchange-folder-size.h : Similar
- * storage/exchange-hierarchy-somedav.c : Fixed a warning
- * storage/exchange-hierarchy-webdav.c : Removed ExchangeFolderSize as
- its member and updated the methods used to access it. We should now
- query the ExchangeAccount object for FolderSize information updation
- * storage/exchange-hierarchy-webdav.h : Removed dead code
-
-2005-07-01 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * lib/e2k-autoconfig.c (validate) : This should only return the
- exception type and not print anything. The plugin will now print the
- proper error message.
- (e2k_validate_user) : Similar
- * lib/e2k-autoconfig.h : Move E2kAutoconfigResult to e2k-validate.h
- so that the plugins can use it.
- * lib/e2k-validate.h : Moved E2kAutoconfigResult here.
- * storage/e-folder-exchange.c (e_mkdir_hier) : Make use of
- g_build_filename instead of the deprecated g_concat_dir_and_file
- * storage/e-folder-type-registry.c : Remove unwanted code.
- * storage/e-folder.c : Similar
- * storage/e-storage.c : Similar
- * storage/exchange-folder-size.c : Similar
-
-2005-06-28 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * storage/exchange-account.c (exchange_account_is_favorite_folder) :
- Added new to check for favorites folder.
- * storage/exchange-account.h : Similar
- * storage/exchange-hierarchy-favorites.c
- (exchange_hierarchy_favorites_is_added) : The main implementation.
- Newly added.
- * storage/exchange-hierarchy-favorites.h : Similar
-
-2005-06-22 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * storage/Makefile.am : e-shell-marshall.list should be disted.
- * lib/Makefile.am : mapi-properties should also be disted.
-
-2005-06-15 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * storage/Makefile.am : Install exchange-hierarchy-webdav.h and
- exchange-hierarchy-somedav.h
-
-2005-06-14 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * storage/libexchange-storage.pc.in : Dont hardcode the libsoup
- version.
-
-2005-06-12 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * lib/Makefile.am : Use ENABLE_KRB5 instead of HAVE_KRB5
-
-2005-06-12 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * lib/Makefile.am : Include e2k-global-catalog-ldap.h. Install
- e2k-global-catalog-ldap.h and e2k-validate.h
- * lib/e2k-global-catalog.c : Use e2k-global-catalog-ldap.h
- * lib/e2k-global-catalog.h : Remove the use of ldap.h from here.
- * storage/Makefile.am : Use KRB5_LDFLAGS instead of KRB5_LIBS
- * lib/e2k-global-catalog-ldap.h : Added new
- * lib/e2k-validate.h : Added new
-
-2005-06-12 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * lib/Makefile.am : Remove commented code and fix spacings
- * storage/Makefile.am : Similar. Also added exchange-oof.[ch]
- * lib/e2k-context.c : Use the proper VERSION definition name.
-
-2005-06-10 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- First movement of exchange server communication code into e-d-s HEAD.
-
-2005-06-07 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * storage/Makefile.am : Removed references to config-listener and
- foreign-hierarchy
- * storage/e-folder-exchange.c : Removed references to e_source here.
- * storage/e-storage.c : Removed from e-d-s and moved back to exchange.
- * storage/exchange-account.c : Removed references to foreign hierarchy.
- * storage/exchange-account.h : Added constants.h
- * storage/exchange-constants.h : Avoided re-inclusion
- * storage/exchange-hierarchy-favorites.c : Removed esource references.
- * storage/exchange-hierarchy-gal.c : Removed esource references
- * storage/exchange-hierarchy-webdav.c : Removed references to foreign
- hierarchy.
- * storage/exchange-types.h : Similar
-
-2005-06-03 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * storage/e-shell-marshal.list : New file
-
-2005-06-02 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * libexchange-storage.pc.in : Moved it from exchange to
- exchange/storage
- * lib/Makefile.am : Added a few more header files that had to be
- installed.
- * storage/Makefile.am : Similar
- * storage/e-folder-exchange.c : Merged the changes from HEAD.
- * storage/e-folder.c : Added marshalling code.
- * storage/e-storage.c : Similar
- * storage/exchange-account.c (exchange_account_get_username): Added new
- * storage/exchange-account.h : Similar
- * storage/exchange-component.[ch] : Removed from Makefile.am. Should be
- removing these files from the repository.
- * storage/exchange-config-listener.[ch] : Merged the changed from HEAD.
- * storage/exchange-hierarchy-favorites.c : Similar
- * storage/exchange-hierarchy-foreign.c : Similar
- * storage/exchange-hierarchy-gal.c : Similar
- * storage/exchange-hierarchy-webdav.c : Similar
- * storage/exchange-constants.h : Added a new file.
-
-2005-05-21 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * lib/Makefile.am : Install e2k-global-catalog.h and e2k-utils.h
- Also added this new ChangeLog file
+++ /dev/null
-SUBDIRS = xntlm lib storage
+++ /dev/null
-2005-08-19 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * openldap-ntlm.diff : Moved from evolutio-exchange
+++ /dev/null
-(Note that this patch is not useful on its own... it just adds some
-hooks to work with the LDAP authentication process at a lower level
-than the API otherwise allows. The code that calls these hooks and
-actually drives the NTLM authentication process is in
-lib/e2k-global-catalog.c, and the code that actually implements the
-NTLM algorithms is in xntlm/.)
-
-This is a patch against OpenLDAP 2.2.6. Apply with -p0
-
-
---- include/ldap.h.orig 2004-01-01 13:16:28.000000000 -0500
-+++ include/ldap.h 2004-07-14 11:58:49.000000000 -0400
-@@ -1753,5 +1753,26 @@
- LDAPControl **cctrls ));
-
-
-+/*
-+ * hacks for NTLM
-+ */
-+#define LDAP_AUTH_NTLM_REQUEST ((ber_tag_t) 0x8aU)
-+#define LDAP_AUTH_NTLM_RESPONSE ((ber_tag_t) 0x8bU)
-+LDAP_F( int )
-+ldap_ntlm_bind LDAP_P((
-+ LDAP *ld,
-+ LDAP_CONST char *dn,
-+ ber_tag_t tag,
-+ struct berval *cred,
-+ LDAPControl **sctrls,
-+ LDAPControl **cctrls,
-+ int *msgidp ));
-+LDAP_F( int )
-+ldap_parse_ntlm_bind_result LDAP_P((
-+ LDAP *ld,
-+ LDAPMessage *res,
-+ struct berval *challenge));
-+
-+
- LDAP_END_DECL
- #endif /* _LDAP_H */
---- libraries/libldap/Makefile.in.orig 2004-01-01 13:16:29.000000000 -0500
-+++ libraries/libldap/Makefile.in 2004-07-14 13:37:23.000000000 -0400
-@@ -20,7 +20,7 @@
- SRCS = bind.c open.c result.c error.c compare.c search.c \
- controls.c messages.c references.c extended.c cyrus.c \
- modify.c add.c modrdn.c delete.c abandon.c \
-- sasl.c sbind.c kbind.c unbind.c cancel.c \
-+ sasl.c ntlm.c sbind.c kbind.c unbind.c cancel.c \
- filter.c free.c sort.c passwd.c whoami.c \
- getdn.c getentry.c getattr.c getvalues.c addentry.c \
- request.c os-ip.c url.c sortctrl.c vlvctrl.c \
-@@ -29,7 +29,7 @@
- OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \
- controls.lo messages.lo references.lo extended.lo cyrus.lo \
- modify.lo add.lo modrdn.lo delete.lo abandon.lo \
-- sasl.lo sbind.lo kbind.lo unbind.lo cancel.lo \
-+ sasl.lo ntlm.lo sbind.lo kbind.lo unbind.lo cancel.lo \
- filter.lo free.lo sort.lo passwd.lo whoami.lo \
- getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \
- request.lo os-ip.lo url.lo sortctrl.lo vlvctrl.lo \
---- /dev/null 2004-06-30 15:04:37.000000000 -0400
-+++ libraries/libldap/ntlm.c 2004-07-14 13:44:18.000000000 -0400
-@@ -0,0 +1,137 @@
-+/* $OpenLDAP: pkg/ldap/libraries/libldap/ntlm.c,v 1.1.4.10 2002/01/04 20:38:21 kurt Exp $ */
-+/*
-+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
-+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
-+ */
-+
-+/* Mostly copied from sasl.c */
-+
-+#include "portable.h"
-+
-+#include <stdlib.h>
-+#include <stdio.h>
-+
-+#include <ac/socket.h>
-+#include <ac/string.h>
-+#include <ac/time.h>
-+#include <ac/errno.h>
-+
-+#include "ldap-int.h"
-+
-+int
-+ldap_ntlm_bind(
-+ LDAP *ld,
-+ LDAP_CONST char *dn,
-+ ber_tag_t tag,
-+ struct berval *cred,
-+ LDAPControl **sctrls,
-+ LDAPControl **cctrls,
-+ int *msgidp )
-+{
-+ BerElement *ber;
-+ int rc;
-+ ber_int_t id;
-+
-+ Debug( LDAP_DEBUG_TRACE, "ldap_ntlm_bind\n", 0, 0, 0 );
-+
-+ assert( ld != NULL );
-+ assert( LDAP_VALID( ld ) );
-+ assert( msgidp != NULL );
-+
-+ if( msgidp == NULL ) {
-+ ld->ld_errno = LDAP_PARAM_ERROR;
-+ return ld->ld_errno;
-+ }
-+
-+ /* create a message to send */
-+ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
-+ ld->ld_errno = LDAP_NO_MEMORY;
-+ return ld->ld_errno;
-+ }
-+
-+ assert( LBER_VALID( ber ) );
-+
-+ LDAP_NEXT_MSGID( ld, id );
-+ rc = ber_printf( ber, "{it{istON}" /*}*/,
-+ id, LDAP_REQ_BIND,
-+ ld->ld_version, dn, tag,
-+ cred );
-+
-+ /* Put Server Controls */
-+ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
-+ ber_free( ber, 1 );
-+ return ld->ld_errno;
-+ }
-+
-+ if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
-+ ld->ld_errno = LDAP_ENCODING_ERROR;
-+ ber_free( ber, 1 );
-+ return ld->ld_errno;
-+ }
-+
-+ /* send the message */
-+ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber, id );
-+
-+ if(*msgidp < 0)
-+ return ld->ld_errno;
-+
-+ return LDAP_SUCCESS;
-+}
-+
-+int
-+ldap_parse_ntlm_bind_result(
-+ LDAP *ld,
-+ LDAPMessage *res,
-+ struct berval *challenge)
-+{
-+ ber_int_t errcode;
-+ ber_tag_t tag;
-+ BerElement *ber;
-+ ber_len_t len;
-+
-+ Debug( LDAP_DEBUG_TRACE, "ldap_parse_ntlm_bind_result\n", 0, 0, 0 );
-+
-+ assert( ld != NULL );
-+ assert( LDAP_VALID( ld ) );
-+ assert( res != NULL );
-+
-+ if ( ld == NULL || res == NULL ) {
-+ return LDAP_PARAM_ERROR;
-+ }
-+
-+ if( res->lm_msgtype != LDAP_RES_BIND ) {
-+ ld->ld_errno = LDAP_PARAM_ERROR;
-+ return ld->ld_errno;
-+ }
-+
-+ if ( ld->ld_error ) {
-+ LDAP_FREE( ld->ld_error );
-+ ld->ld_error = NULL;
-+ }
-+ if ( ld->ld_matched ) {
-+ LDAP_FREE( ld->ld_matched );
-+ ld->ld_matched = NULL;
-+ }
-+
-+ /* parse results */
-+
-+ ber = ber_dup( res->lm_ber );
-+
-+ if( ber == NULL ) {
-+ ld->ld_errno = LDAP_NO_MEMORY;
-+ return ld->ld_errno;
-+ }
-+
-+ tag = ber_scanf( ber, "{ioa" /*}*/,
-+ &errcode, challenge, &ld->ld_error );
-+ ber_free( ber, 0 );
-+
-+ if( tag == LBER_ERROR ) {
-+ ld->ld_errno = LDAP_DECODING_ERROR;
-+ return ld->ld_errno;
-+ }
-+
-+ ld->ld_errno = errcode;
-+
-+ return( ld->ld_errno );
-+}
+++ /dev/null
-noinst_LTLIBRARIES = \
- libexchange.la
-
-PROP_GENERATED = e2k-propnames.h e2k-propnames.c e2k-proptags.h
-
-mapi_properties = $(srcdir)/mapi-properties
-e2k_propnames_h_in = $(srcdir)/e2k-propnames.h.in
-e2k_propnames_c_in = $(srcdir)/e2k-propnames.c.in
-e2k_proptags_h_in = $(srcdir)/e2k-proptags.h.in
-
-e2k-propnames.h: $(e2k_propnames_h_in) $(mapi_properties)
- @echo Building $@
- @( awk '/^@AUTOGENERATE@/ {exit;} {print;}' $(e2k_propnames_h_in); \
- awk '/^x/ { printf "#define %-39s E2K_NS_MAPI_PROPTAG \"%s\"\n", $$2, $$1; }' $(mapi_properties); \
- awk '{if (tail) { print; }} /^@AUTOGENERATE@/ {tail=1;}' $(e2k_propnames_h_in) ) \
- > $@
-
-e2k-propnames.c: $(e2k_propnames_c_in) $(mapi_properties)
- @echo Building $@
- @( awk '/^@AUTOGENERATE@/ {exit;} {print;}' $(e2k_propnames_c_in); \
- awk '/^x/ { print "\t{ \"" $$1 "\", \"" $$2 "\" },"; }' $(mapi_properties); \
- awk '{if (tail) { print; }} /^@AUTOGENERATE@/ {tail=1;}' $(e2k_propnames_c_in) ) \
- > $@
-
-e2k-proptags.h: $(e2k_proptags_h_in) $(mapi_properties)
- @echo Building $@
- @( awk '/^@AUTOGENERATE@/ {exit;} {print;}' $(e2k_proptags_h_in); \
- awk '/^x/ { printf "#define E2K_PROPTAG_%-39s 0%s\n", $$2, $$1; }' $(mapi_properties); \
- awk '{if (tail) { print; }} /^@AUTOGENERATE@/ {tail=1;}' $(e2k_proptags_h_in) ) \
- > $@
-
-BUILT_SOURCES = $(PROP_GENERATED)
-NODIST_FILES = $(PROP_GENERATED)
-CLEANFILES = $(PROP_GENERATED)
-
-MARSHAL_GENERATED = e2k-marshal.c e2k-marshal.h
-
-e2k-marshal.h: e2k-marshal.list
- ( @GLIB_GENMARSHAL@ --prefix=e2k_marshal $(srcdir)/e2k-marshal.list --header > e2k-marshal.tmp \
- && mv e2k-marshal.tmp e2k-marshal.h ) \
- || ( rm -f e2k-marshal.tmp && exit 1 )
-
-e2k-marshal.c: e2k-marshal.h
- ( (echo '#include "e2k-marshal.h"'; @GLIB_GENMARSHAL@ --prefix=e2k_marshal $(srcdir)/e2k-marshal.list --body) > e2k-marshal.tmp \
- && mv e2k-marshal.tmp e2k-marshal.c ) \
- || ( rm -f e2k-marshal.tmp && exit 1 )
-
-BUILT_SOURCES += $(MARSHAL_GENERATED)
-NODIST_FILES += $(MARSHAL_GENERATED)
-CLEANFILES += $(MARSHAL_GENERATED)
-
-if ENABLE_KRB5
-KERBEROS_FILES = \
- e2k-kerberos.c \
- e2k-kerberos.h
-else
-KERBEROS_FILES =
-endif
-
-# Fix the code to not use E_DATA_SERVER_UI_CFLAGS
-
-libexchange_la_CPPFLAGS = \
- $(AM_CPPFLAGS) \
- -DCONNECTOR_PREFIX=\""$(prefix)"\" \
- -I$(top_srcdir) \
- -I$(top_srcdir)/servers/exchange/xntlm \
- $(LDAP_CFLAGS) \
- $(KRB5_CFLAGS) \
- $(SOUP_CFLAGS) \
- $(E_DATA_SERVER_CFLAGS) \
- $(E_DATA_SERVER_UI_CFLAGS)
-
-libexchange_la_SOURCES = \
- $(MARSHAL_GENERATED) \
- e2k-propnames.h \
- e2k-proptags.h \
- e2k-action.c \
- e2k-action.h \
- e2k-autoconfig.c \
- e2k-autoconfig.h \
- e2k-context.c \
- e2k-context.h \
- e2k-freebusy.c \
- e2k-freebusy.h \
- e2k-global-catalog.c \
- e2k-global-catalog-ldap.h \
- e2k-http-utils.c \
- e2k-http-utils.h \
- e2k-operation.c \
- e2k-operation.h \
- e2k-path.c \
- e2k-path.h \
- e2k-properties.c \
- e2k-properties.h \
- e2k-restriction.c \
- e2k-restriction.h \
- e2k-result.c \
- e2k-result.h \
- e2k-rule.c \
- e2k-rule.h \
- e2k-rule-xml.c \
- e2k-rule-xml.h \
- e2k-security-descriptor.c \
- e2k-security-descriptor.h \
- e2k-sid.c \
- e2k-sid.h \
- e2k-types.h \
- e2k-uri.c \
- e2k-uri.h \
- e2k-utils.c \
- e2k-utils.h \
- e2k-validate.h \
- e2k-xml-utils.c \
- e2k-xml-utils.h \
- $(KERBEROS_FILES) \
- mapi.h
-
-libexchangeincludedir = $(privincludedir)/exchange
-
-libexchangeinclude_HEADERS = \
- e2k-autoconfig.h \
- e2k-context.h \
- e2k-freebusy.h \
- e2k-global-catalog.h \
- e2k-global-catalog-ldap.h \
- e2k-http-utils.h \
- e2k-marshal.h \
- e2k-operation.h \
- e2k-properties.h \
- e2k-propnames.h \
- e2k-restriction.h \
- e2k-result.h \
- e2k-security-descriptor.h \
- e2k-sid.h \
- e2k-types.h \
- e2k-uri.h \
- e2k-utils.h \
- e2k-validate.h \
- e2k-xml-utils.h \
- mapi.h
-
-EXTRA_DIST = \
- e2k-marshal.list \
- mapi-properties \
- $(e2k_propnames_h_in) \
- $(e2k_propnames_c_in) \
- $(e2k_proptags_h_in)
-
-dist-hook:
- cd $(distdir); rm -f $(NODIST_FILES)
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2003, 2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* Autoconfig test program */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <pthread.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "e2k-autoconfig.h"
-#include "test-utils.h"
-
-const gchar *test_program_name = "actest";
-
-static E2kOperation op;
-
-static gpointer
-cancel (gpointer data)
-{
- e2k_operation_cancel (&op);
- return NULL;
-}
-
-static void
-quit (gint sig)
-{
- static pthread_t cancel_thread;
-
- if (!cancel_thread) {
- pthread_create (&cancel_thread, NULL, cancel, NULL);
- } else
- exit (0);
-}
-
-void
-test_main (gint argc, gchar **argv)
-{
- E2kAutoconfig *ac;
- E2kAutoconfigResult result;
- const gchar *username, *password, *owa_uri, *gc_server;
-
- signal (SIGINT, quit);
-
- if (argc < 2 || argc > 4) {
- fprintf (stderr, "Usage: %s username [OWA URL] [Global Catalog server]\n", argv[0]);
- exit (1);
- }
-
- username = argv[1];
- password = test_get_password (username, NULL);
-
- owa_uri = argc > 2 ? argv[2] : NULL;
- gc_server = argc > 3 ? argv[3] : NULL;
-
- e2k_operation_init (&op);
- ac = e2k_autoconfig_new (owa_uri, username, password,
- E2K_AUTOCONFIG_USE_EITHER);
-
- if (ac->owa_uri) {
- if (!owa_uri)
- printf ("[Default OWA URI: %s]\n", ac->owa_uri);
- } else {
- printf ("No default OWA URI available. Must specify on commandline.\n");
- goto done;
- }
-
- if (ac->gc_server)
- printf ("[Default GC: %s]\n", ac->gc_server);
- if (ac->nt_domain)
- printf ("[Default NT Domain: %s]\n", ac->nt_domain);
- if (ac->w2k_domain)
- printf ("[Default W2k Domain: %s]\n", ac->w2k_domain);
- printf ("\n");
-
- if (gc_server)
- e2k_autoconfig_set_gc_server (ac, gc_server, -1, E2K_AUTOCONFIG_USE_GAL_DEFAULT);
-
- result = e2k_autoconfig_check_exchange (ac, &op);
- if (result != E2K_AUTOCONFIG_OK) {
- const gchar *msg;
- switch (result) {
- case E2K_AUTOCONFIG_CANT_RESOLVE:
- msg = "Could not resolve hostname";
- break;
- case E2K_AUTOCONFIG_CANT_CONNECT:
- msg = "Could not connect to server";
- break;
- case E2K_AUTOCONFIG_REDIRECT:
- msg = "Multiple redirection";
- break;
- case E2K_AUTOCONFIG_AUTH_ERROR:
- msg = "Authentication error. Password incorrect?";
- break;
- case E2K_AUTOCONFIG_AUTH_ERROR_TRY_DOMAIN:
- msg = "Authentication error. Password incorrect, or try DOMAIN\\username?";
- break;
- case E2K_AUTOCONFIG_AUTH_ERROR_TRY_BASIC:
- msg = "Authentication error. Password incorrect, or try Basic auth?";
- break;
- case E2K_AUTOCONFIG_AUTH_ERROR_TRY_NTLM:
- msg = "Authentication error. Password incorrect, or try NTLM auth?";
- break;
- case E2K_AUTOCONFIG_TRY_SSL:
- msg = "Need to use SSL";
- break;
- case E2K_AUTOCONFIG_EXCHANGE_5_5:
- msg = "This is an Exchange 5.5 server";
- break;
- case E2K_AUTOCONFIG_NOT_EXCHANGE:
- msg = "Server does not appear to be Exchange";
- break;
- case E2K_AUTOCONFIG_NO_OWA:
- msg = "Did not find OWA at given URL";
- break;
- case E2K_AUTOCONFIG_NO_MAILBOX:
- msg = "You don't seem to have a mailbox here";
- break;
- case E2K_AUTOCONFIG_CANT_BPROPFIND:
- msg = "Server does not allow BPROPFIND";
- break;
- case E2K_AUTOCONFIG_CANCELLED:
- msg = "Cancelled";
- break;
- case E2K_AUTOCONFIG_FAILED:
- default:
- msg = "Unknown error";
- break;
- }
-
- printf ("Exchange check to %s failed:\n %s\n",
- ac->owa_uri, msg);
- goto done;
- }
-
- result = e2k_autoconfig_check_global_catalog (ac, &op);
- if (result != E2K_AUTOCONFIG_OK) {
- const gchar *msg;
- switch (result) {
- case E2K_AUTOCONFIG_CANT_RESOLVE:
- msg = "Could not resolve GC server";
- break;
- case E2K_AUTOCONFIG_NO_MAILBOX:
- msg = "No data for user";
- break;
- case E2K_AUTOCONFIG_AUTH_ERROR_TRY_DOMAIN:
- msg = "Authentication error. Try DOMAIN\\username?";
- break;
- case E2K_AUTOCONFIG_CANCELLED:
- msg = "Cancelled";
- break;
- case E2K_AUTOCONFIG_FAILED:
- default:
- msg = "Unknown error";
- break;
- }
-
- printf ("\nGlobal Catalog check failed: %s\n", msg);
- if (!ac->gc_server) {
- if (ac->w2k_domain)
- printf ("got domain=%s but ", ac->w2k_domain);
- printf ("could not autodetect.\nSpecify GC on command-line.\n");
- }
- goto done;
- }
-
- printf ("%s is an Exchange Server %s\n\n", ac->exchange_server,
- ac->version == E2K_EXCHANGE_2000 ? "2000" :
- ac->version == E2K_EXCHANGE_2003 ? "2003" :
- "[Unknown version]");
-
- printf ("Name: %s\nEmail: %s\nTimezone: %s\nAccount URL: %s\n\n",
- ac->display_name, ac->email, ac->timezone, ac->account_uri);
-
- if (!ac->pf_server)
- printf ("Warning: public folder server was defaulted\n\n");
- done:
- e2k_operation_free (&op);
- e2k_autoconfig_free (ac);
- test_quit ();
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2003, 2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* Change password test program */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include "e2k-kerberos.h"
-#include "test-utils.h"
-
-const gchar *test_program_name = "cptest";
-
-static void
-krb_error (E2kKerberosResult result, const gchar *failed)
-{
- switch (result) {
- case E2K_KERBEROS_USER_UNKNOWN:
- fprintf (stderr, "Unknown user\n");
- exit (1);
-
- case E2K_KERBEROS_PASSWORD_INCORRECT:
- fprintf (stderr, "Password incorrect\n");
- exit (1);
-
- case E2K_KERBEROS_PASSWORD_EXPIRED:
- printf ("Note: password has expired\n");
- break;
-
- case E2K_KERBEROS_KDC_UNREACHABLE:
- fprintf (stderr, "KDC unreachable (network problem or no such domain)\n");
- exit (1);
-
- case E2K_KERBEROS_TIME_SKEW:
- fprintf (stderr, "Client/server time skew is too large.\n");
- exit (1);
-
- case E2K_KERBEROS_PASSWORD_TOO_WEAK:
- fprintf (stderr, "Server rejected new password\n");
- exit (1);
-
- case E2K_KERBEROS_FAILED:
- if (failed) {
- fprintf (stderr, "%s\n", failed);
- exit (1);
- }
- /* else fall through */
-
- default:
- fprintf (stderr, "Unknown error.\n");
- exit (1);
- }
-}
-
-void
-test_main (gint argc, gchar **argv)
-{
- gchar *domain, *at, *prompt, *password;
- gchar *newpass1, *newpass2;
- const gchar *user;
- gint res;
-
- if (argc != 2) {
- fprintf (stderr, "Usage: %s [user@]domain\n", argv[0]);
- exit (1);
- }
-
- domain = argv[1];
- at = strchr (domain, '@');
- if (at) {
- user = g_strndup (domain, at - domain);
- domain = at + 1;
- } else
- user = g_get_user_name ();
-
- prompt = g_strdup_printf ("Password for %s@%s", user, domain);
- password = test_ask_password (prompt);
- g_free (prompt);
-
- res = e2k_kerberos_check_password (user, domain, password);
- if (res != E2K_KERBEROS_OK)
- krb_error (res, NULL);
-
- newpass1 = test_ask_password ("New password");
- newpass2 = test_ask_password ("Confirm");
-
- if (!newpass1 || !newpass2 || strcmp (newpass1, newpass2) != 0) {
- fprintf (stderr, "Passwords do not match.\n");
- exit (1);
- }
-
- res = e2k_kerberos_change_password (user, domain, password, newpass1);
- if (res != E2K_KERBEROS_OK)
- krb_error (res, "Could not change password");
-
- printf ("Password changed\n");
- test_quit ();
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2003, 2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* Generic WebDAV test program */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "e2k-context.h"
-#include "e2k-uri.h"
-#include "e2k-utils.h"
-#include "e2k-xml-utils.h"
-
-#include "test-utils.h"
-
-static void
-print_header (gpointer name, gpointer value, gpointer data)
-{
- gboolean *isxml = data;
-
- printf ("%s: %s\n", (gchar *)name, (gchar *)value);
- if (!g_ascii_strcasecmp (name, "Content-Type") &&
- strstr (value, "/xml"))
- *isxml = TRUE;
-}
-
-const gchar *test_program_name = "davcat";
-
-void
-test_main (gint argc, gchar **argv)
-{
- E2kContext *ctx;
- SoupMessage *msg;
- GByteArray *input;
- gchar buf[1024], *base_uri, *root_uri, *eol, *vers, *p;
- gchar *method, *path, *uri;
- gchar *name, *value;
- gint nread;
- gboolean isxml = FALSE;
-
- if (argc != 2) {
- fprintf (stderr, "usage: %s URI\n", argv[0]);
- exit (1);
- }
- base_uri = argv[1];
- ctx = test_get_context (base_uri);
-
- input = g_byte_array_new ();
- do {
- nread = read (STDIN_FILENO, buf, sizeof (buf));
- if (nread > 0)
- g_byte_array_append (input, buf, nread);
- } while (nread > 0 || (nread == -1 && errno == EINTR));
- g_byte_array_append (input, "", 1);
-
- method = input->data;
- eol = strchr (method, '\n');
- p = strchr (method, ' ');
- if (!eol || !p || p > eol) {
- fprintf (stderr, "Could not parse request method\n");
- exit (1);
- }
- *p = '\0';
-
- path = p + 1;
- if (*path == '/')
- path++;
- p = strchr (path, ' ');
- if (!p || p > eol)
- p = eol;
- *p = '\0';
- if (p < eol)
- vers = p + 1;
- else
- vers = NULL;
-
- root_uri = g_strdup (base_uri);
- p = strstr (root_uri, "://");
- if (p) {
- p = strchr (p + 3, '/');
- if (p)
- *p = '\0';
- }
- uri = e2k_uri_concat (root_uri, path);
- g_free (root_uri);
- msg = e2k_soup_message_new (ctx, uri, method);
- if (!msg) {
- fprintf (stderr, "Could not create message to %s\n", uri);
- exit (1);
- }
- g_free (uri);
-
- if (vers) {
- if (strncmp (vers, "HTTP/1.", 7) != 0 ||
- (vers[7] != '0' && vers[7] != '1')) {
- fprintf (stderr, "Could not parse HTTP version\n");
- exit (1);
- }
- if (vers[7] == '0')
- soup_message_set_http_version (msg, SOUP_HTTP_1_0);
- }
-
- while (1) {
- name = eol + 1;
- eol = strchr (name, '\n');
- p = strchr (name, ':');
- if (!eol || eol == name || !p || p > eol || p[1] != ' ')
- break;
- *p = '\0';
- value = p + 2;
- *eol = '\0';
- if (eol[-1] == '\r')
- eol[-1] = '\0';
- soup_message_add_header (msg->request_headers, name, value);
- }
-
- p = name;
- if (*p == '\r')
- p++;
- if (*p == '\n')
- p++;
-
- if (*p) {
- msg->request.body = e2k_lf_to_crlf (p);
- msg->request.length = strlen (msg->request.body);
- msg->request.owner = SOUP_BUFFER_SYSTEM_OWNED;
-
- if (!soup_message_get_header (msg->request_headers, "Content-Type")) {
- soup_message_add_header (msg->request_headers,
- "Content-Type", "text/xml");
- }
- }
-
- e2k_context_send_message (ctx, NULL, msg);
-
- printf ("%d %s\n", msg->status_code, msg->reason_phrase);
- if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code))
- exit (1);
-
- soup_message_foreach_header (msg->response_headers,
- print_header, &isxml);
- printf ("\n");
-
- if (isxml) {
- xmlDoc *doc;
-
- doc = e2k_parse_xml (msg->response.body, msg->response.length);
- if (doc) {
- xmlDocFormatDump (stdout, doc, 1);
- xmlFreeDoc (doc);
- } else
- fwrite (msg->response.body, 1, msg->response.length, stdout);
- } else
- fwrite (msg->response.body, 1, msg->response.length, stdout);
- printf ("\n");
-
- g_object_unref (msg);
- g_byte_array_free (input, TRUE);
- g_object_unref (ctx);
- test_quit ();
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2002-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* e2k-action.c: Exchange server-side rule actions */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include "e2k-action.h"
-#include "e2k-propnames.h"
-#include "e2k-restriction.h"
-#include "e2k-rule.h"
-#include "e2k-utils.h"
-#include "mapi.h"
-
-/* The apparently-constant store entryid prefix for a move or copy action */
-#define E2K_ACTION_XFER_STORE_ENTRYID_PREFIX "\x00\x00\x00\x00\x38\xa1\xbb\x10\x05\xe5\x10\x1a\xa1\xbb\x08\x00\x2b\x2a\x56\xc2\x00\x00\x45\x4d\x53\x4d\x44\x42\x2e\x44\x4c\x4c\x00\x00\x00\x00"
-#define E2K_ACTION_XFER_STORE_ENTRYID_PREFIX_LEN (sizeof (E2K_ACTION_XFER_STORE_ENTRYID_PREFIX) - 1)
-
-static GByteArray *
-copy_bytearray (GByteArray *ba)
-{
- GByteArray *copy;
-
- copy = g_byte_array_sized_new (ba->len);
- copy->len = ba->len;
- memcpy (copy->data, ba->data, copy->len);
-
- return copy;
-}
-
-static E2kAction *
-xfer_action (E2kActionType type, GByteArray *store_entryid,
- GByteArray *folder_source_key)
-{
- E2kAction *act;
-
- act = g_new0 (E2kAction, 1);
- act->type = type;
- act->act.xfer.store_entryid = copy_bytearray (store_entryid);
- act->act.xfer.folder_source_key = copy_bytearray (folder_source_key);
-
- return act;
-}
-
-/**
- * e2k_action_move:
- * @store_entryid: The PR_STORE_ENTRYID of the message store
- * @folder_source_key: The PR_SOURCE_KEY of a folder in that store
- *
- * Creates a rule action to move a message into the indicated folder
- *
- * Return value: the new rule action
- **/
-E2kAction *
-e2k_action_move (GByteArray *store_entryid, GByteArray *folder_source_key)
-{
- return xfer_action (E2K_ACTION_MOVE, store_entryid, folder_source_key);
-}
-
-/**
- * e2k_action_copy:
- * @store_entryid: The PR_STORE_ENTRYID of the message store
- * @folder_source_key: The PR_SOURCE_KEY of a folder in that store
- *
- * Creates a rule action to copy a message into the indicated folder
- *
- * Return value: the new rule action
- **/
-E2kAction *
-e2k_action_copy (GByteArray *store_entryid, GByteArray *folder_source_key)
-{
- return xfer_action (E2K_ACTION_COPY, store_entryid, folder_source_key);
-}
-
-static E2kAction *
-reply_action (E2kActionType type, GByteArray *template_entryid,
- guint8 template_guid[16])
-{
- E2kAction *act;
-
- act = g_new0 (E2kAction, 1);
- act->type = type;
- act->act.reply.entryid = copy_bytearray (template_entryid);
- memcpy (act->act.reply.reply_template_guid, template_guid, 16);
-
- return act;
-}
-
-/**
- * e2k_action_reply:
- * @template_entryid: The entryid of the reply template
- * @template_guid: The GUID of the reply template
- *
- * Creates a rule action to reply to a message using the indicated
- * template
- *
- * Return value: the new rule action
- **/
-E2kAction *
-e2k_action_reply (GByteArray *template_entryid, guint8 template_guid[16])
-{
- return reply_action (E2K_ACTION_REPLY, template_entryid, template_guid);
-}
-
-/**
- * e2k_action_oof_reply:
- * @template_entryid: The entryid of the reply template
- * @template_guid: The GUID of the reply template
- *
- * Creates a rule action to send an Out-of-Office reply to a message
- * using the indicated template
- *
- * Return value: the new rule action
- **/
-E2kAction *
-e2k_action_oof_reply (GByteArray *template_entryid, guint8 template_guid[16])
-{
- return reply_action (E2K_ACTION_OOF_REPLY, template_entryid, template_guid);
-}
-
-/**
- * e2k_action_defer:
- * @data: data identifying the deferred action
- *
- * Creates a rule action to defer processing on a message
- *
- * Return value: the new rule action
- **/
-E2kAction *
-e2k_action_defer (GByteArray *data)
-{
- E2kAction *act;
-
- act = g_new0 (E2kAction, 1);
- act->type = E2K_ACTION_DEFER;
- act->act.defer_data = copy_bytearray (data);
-
- return act;
-}
-
-/**
- * e2k_action_bounce:
- * @bounce_code: a bounce code
- *
- * Creates a rule action to bounce a message
- *
- * Return value: the new rule action
- **/
-E2kAction *
-e2k_action_bounce (E2kActionBounceCode bounce_code)
-{
- E2kAction *act;
-
- act = g_new0 (E2kAction, 1);
- act->type = E2K_ACTION_BOUNCE;
- act->act.bounce_code = bounce_code;
-
- return act;
-}
-
-static E2kAction *
-forward_action (E2kActionType type, E2kAddrList *list)
-{
- E2kAction *act;
-
- g_return_val_if_fail (type == E2K_ACTION_FORWARD || type == E2K_ACTION_DELEGATE, NULL);
- g_return_val_if_fail (list->nentries > 0, NULL);
-
- act = g_new0 (E2kAction, 1);
- act->type = type;
- act->act.addr_list = list;
-
- return act;
-}
-
-/**
- * e2k_action_forward:
- * @list: a list of recipients
- *
- * Creates a rule action to forward a message to the indicated list of
- * recipients
- *
- * Return value: the new rule action
- **/
-E2kAction *
-e2k_action_forward (E2kAddrList *list)
-{
- return forward_action (E2K_ACTION_FORWARD, list);
-}
-
-/**
- * e2k_action_delegate:
- * @list: a list of recipients
- *
- * Creates a rule action to delegate a meeting request to the
- * indicated list of recipients
- *
- * Return value: the new rule action
- **/
-E2kAction *
-e2k_action_delegate (E2kAddrList *list)
-{
- return forward_action (E2K_ACTION_DELEGATE, list);
-}
-
-/**
- * e2k_action_tag:
- * @propname: a MAPI property name
- * @type: the type of @propname
- * @value: the value for @propname
- *
- * Creates a rule action to set the given property to the given value
- * on a message.
- *
- * Return value: the new rule action
- **/
-E2kAction *
-e2k_action_tag (const gchar *propname, E2kPropType type, gpointer value)
-{
- E2kAction *act;
-
- act = g_new0 (E2kAction, 1);
- act->type = E2K_ACTION_TAG;
- e2k_rule_prop_set (&act->act.proptag.prop, propname);
- act->act.proptag.type = type;
- act->act.proptag.value = value; /* FIXME: copy? */
-
- return act;
-}
-
-/**
- * e2k_action_delete:
- *
- * Creates a rule action to permanently delete a message (ie, not just
- * move it to the trash).
- *
- * Return value: the new rule action
- **/
-E2kAction *
-e2k_action_delete (void)
-{
- E2kAction *act;
-
- act = g_new0 (E2kAction, 1);
- act->type = E2K_ACTION_DELETE;
-
- return act;
-}
-
-/**
- * e2k_addr_list_new:
- * @nentries: the number of entries
- *
- * Creates an address list for a forward or delegate rule, with
- * @nentries slots
- *
- * Return value: the new address list
- **/
-E2kAddrList *
-e2k_addr_list_new (gint nentries)
-{
- E2kAddrList *list;
-
- list = g_malloc0 (sizeof (E2kAddrList) +
- (nentries - 1) * sizeof (E2kAddrEntry));
- list->nentries = nentries;
-
- return list;
-}
-
-static void
-addr_entry_set_core (E2kPropValue *pv, GByteArray *entryid,
- const gchar *display_name, const gchar *email_type,
- const gchar *email_addr)
-{
- e2k_rule_prop_set (&pv[0].prop, PR_ENTRYID);
- pv[0].type = E2K_PROP_TYPE_BINARY;
- pv[0].value = entryid;
-
- e2k_rule_prop_set (&pv[1].prop, PR_DISPLAY_NAME);
- pv[1].type = E2K_PROP_TYPE_STRING;
- pv[1].value = g_strdup (display_name);
-
- e2k_rule_prop_set (&pv[2].prop, PR_OBJECT_TYPE);
- pv[2].type = E2K_PROP_TYPE_INT;
- pv[2].value = GINT_TO_POINTER (MAPI_MAILUSER);
-
- e2k_rule_prop_set (&pv[3].prop, PR_DISPLAY_TYPE);
- pv[3].type = E2K_PROP_TYPE_INT;
- pv[3].value = GINT_TO_POINTER (DT_MAILUSER);
-
- e2k_rule_prop_set (&pv[4].prop, PR_TRANSMITTABLE_DISPLAY_NAME);
- pv[4].type = E2K_PROP_TYPE_STRING;
- pv[4].value = g_strdup (display_name);
-
- e2k_rule_prop_set (&pv[5].prop, PR_EMAIL_ADDRESS);
- pv[5].type = E2K_PROP_TYPE_STRING;
- pv[5].value = g_strdup (email_addr);
-
- e2k_rule_prop_set (&pv[6].prop, PR_ADDRTYPE);
- pv[6].type = E2K_PROP_TYPE_STRING;
- pv[6].value = g_strdup (email_type);
-
- e2k_rule_prop_set (&pv[7].prop, PR_SEND_INTERNET_ENCODING);
- pv[7].type = E2K_PROP_TYPE_INT;
- pv[7].value = GINT_TO_POINTER (0); /* "Let transport decide" */
-
- e2k_rule_prop_set (&pv[8].prop, PR_RECIPIENT_TYPE);
- pv[8].type = E2K_PROP_TYPE_INT;
- pv[8].value = GINT_TO_POINTER (MAPI_TO);
-
- e2k_rule_prop_set (&pv[9].prop, PR_SEARCH_KEY);
- pv[9].type = E2K_PROP_TYPE_BINARY;
- pv[9].value = e2k_search_key_generate (email_type, email_addr);
-}
-
-/**
- * e2k_addr_list_set_local:
- * @list: the address list
- * @entry_num: the list entry to set
- * @display_name: the UTF-8 display name of the recipient
- * @exchange_dn: the Exchange 5.5-style DN of the recipient
- * @email: the SMTP email address of the recipient
- *
- * Sets entry number @entry_num of @list to refer to the indicated
- * local Exchange user.
- **/
-void
-e2k_addr_list_set_local (E2kAddrList *list, gint entry_num,
- const gchar *display_name,
- const gchar *exchange_dn,
- const gchar *email)
-{
- E2kPropValue *pv;
-
- list->entry[entry_num].nvalues = 12;
- list->entry[entry_num].propval = pv = g_new0 (E2kPropValue, 12);
-
- addr_entry_set_core (pv, e2k_entryid_generate_local (exchange_dn),
- display_name, "EX", exchange_dn);
-
- e2k_rule_prop_set (&pv[10].prop, PR_EMS_AB_DISPLAY_NAME_PRINTABLE);
- pv[10].type = E2K_PROP_TYPE_STRING;
- pv[10].value = g_strdup ("FIXME");
-
- e2k_rule_prop_set (&pv[11].prop, PR_SMTP_ADDRESS);
- pv[11].type = E2K_PROP_TYPE_STRING;
- pv[11].value = g_strdup (email);
-}
-
-/**
- * e2k_addr_list_set_oneoff:
- * @list: the address list
- * @entry_num: the list entry to set
- * @display_name: the UTF-8 display name of the recipient
- * @email: the SMTP email address of the recipient
- *
- * Sets entry number @entry_num of @list to refer to the indicated
- * "one-off" SMTP user.
- **/
-void
-e2k_addr_list_set_oneoff (E2kAddrList *list, gint entry_num,
- const gchar *display_name, const gchar *email)
-{
- E2kPropValue *pv;
-
- list->entry[entry_num].nvalues = 12;
- list->entry[entry_num].propval = pv = g_new0 (E2kPropValue, 12);
-
- addr_entry_set_core (pv, e2k_entryid_generate_oneoff (display_name, email, TRUE),
- display_name, "SMTP", email);
-
- e2k_rule_prop_set (&pv[10].prop, PR_SEND_RICH_INFO);
- pv[10].type = E2K_PROP_TYPE_BOOL;
- pv[10].value = GINT_TO_POINTER (FALSE);
-
- e2k_rule_prop_set (&pv[11].prop, PR_RECORD_KEY);
- pv[11].type = E2K_PROP_TYPE_BINARY;
- pv[11].value = e2k_entryid_generate_oneoff (display_name, email, FALSE);
-}
-
-/**
- * e2k_addr_list_free:
- * @list: the address list
- *
- * Frees @list and all its entries.
- **/
-void
-e2k_addr_list_free (E2kAddrList *list)
-{
- gint i, j;
- E2kAddrEntry *entry;
-
- for (i = 0; i < list->nentries; i++) {
- entry = &list->entry[i];
-
- for (j = 0; j < entry->nvalues; j++)
- e2k_rule_free_propvalue (&entry->propval[j]);
- g_free (entry->propval);
- }
- g_free (list);
-}
-
-/**
- * e2k_action_free:
- * @act: the action
- *
- * Frees @act
- **/
-void
-e2k_action_free (E2kAction *act)
-{
- switch (act->type) {
- case E2K_ACTION_MOVE:
- case E2K_ACTION_COPY:
- if (act->act.xfer.store_entryid)
- g_byte_array_free (act->act.xfer.store_entryid, TRUE);
- if (act->act.xfer.folder_source_key)
- g_byte_array_free (act->act.xfer.folder_source_key, TRUE);
- break;
-
- case E2K_ACTION_REPLY:
- case E2K_ACTION_OOF_REPLY:
- if (act->act.reply.entryid)
- g_byte_array_free (act->act.reply.entryid, TRUE);
- break;
-
- case E2K_ACTION_DEFER:
- if (act->act.defer_data)
- g_byte_array_free (act->act.defer_data, TRUE);
- break;
-
- case E2K_ACTION_FORWARD:
- case E2K_ACTION_DELEGATE:
- if (act->act.addr_list)
- e2k_addr_list_free (act->act.addr_list);
- break;
-
- case E2K_ACTION_TAG:
- e2k_rule_free_propvalue (&act->act.proptag);
- break;
-
- default:
- /* Nothing to free */
- break;
- }
-
- g_free (act);
-}
-
-/**
- * e2k_actions_free:
- * @actions: an array of #E2kAction
- *
- * Frees @actions and all of its elements
- **/
-void
-e2k_actions_free (GPtrArray *actions)
-{
- gint i;
-
- for (i = 0; i < actions->len; i++)
- e2k_action_free (actions->pdata[i]);
- g_ptr_array_free (actions, TRUE);
-}
-
-static gboolean
-extract_action (guint8 **data, gint *len, E2kAction **act_ret)
-{
- gint my_len;
- guint8 *my_data;
- guint16 actlen;
- E2kAction *act;
-
- if (!e2k_rule_extract_uint16 (data, len, &actlen))
- return FALSE;
-
- my_data = *data;
- my_len = actlen;
-
- *data += actlen;
- *len -= actlen;
-
- data = &my_data;
- len = &my_len;
-
- if (*len < 1)
- return FALSE;
-
- act = g_new0 (E2kAction, 1);
- act->type = **data;
- (*data)++;
- (*len)--;
-
- if (!e2k_rule_extract_uint32 (data, len, &act->flavor))
- goto lose;
- if (!e2k_rule_extract_uint32 (data, len, &act->flags))
- goto lose;
-
- switch (act->type) {
- case E2K_ACTION_MOVE:
- case E2K_ACTION_COPY:
- /* FIXME: what is this? */
- if (*len < 1 || **data != 1)
- goto lose;
- (*len)--;
- (*data)++;
-
- if (!e2k_rule_extract_binary (data, len, &act->act.xfer.store_entryid))
- goto lose;
- /* Remove the constant part */
- if (act->act.xfer.store_entryid->len <= E2K_ACTION_XFER_STORE_ENTRYID_PREFIX_LEN ||
- memcmp (act->act.xfer.store_entryid->data,
- E2K_ACTION_XFER_STORE_ENTRYID_PREFIX,
- E2K_ACTION_XFER_STORE_ENTRYID_PREFIX_LEN) != 0)
- goto lose;
- act->act.xfer.store_entryid->len -=
- E2K_ACTION_XFER_STORE_ENTRYID_PREFIX_LEN;
- memmove (act->act.xfer.store_entryid->data,
- act->act.xfer.store_entryid->data +
- E2K_ACTION_XFER_STORE_ENTRYID_PREFIX_LEN,
- act->act.xfer.store_entryid->len);
-
- if (!e2k_rule_extract_binary (data, len, &act->act.xfer.folder_source_key))
- goto lose;
- /* Likewise */
- if (act->act.xfer.folder_source_key->len < 1 ||
- act->act.xfer.folder_source_key->data[0] != MAPI_FOLDER)
- goto lose;
- memmove (act->act.xfer.folder_source_key->data,
- act->act.xfer.folder_source_key->data + 1,
- act->act.xfer.folder_source_key->len);
-
- *act_ret = act;
- return TRUE;
-
- case E2K_ACTION_REPLY:
- case E2K_ACTION_OOF_REPLY:
- /* The reply template GUID is 16 bytes, the entryid
- * is the rest.
- */
- if (*len <= 16)
- goto lose;
-
- act->act.reply.entryid = g_byte_array_sized_new (*len - 16);
- memcpy (act->act.reply.entryid->data, *data, *len - 16);
- act->act.reply.entryid->len = *len - 16;
- memcpy (act->act.reply.reply_template_guid, *data + *len - 16, 16);
-
- *act_ret = act;
- return TRUE;
-
- case E2K_ACTION_DEFER:
- act->act.defer_data = g_byte_array_sized_new (*len);
- memcpy (act->act.defer_data->data, *data, *len);
- act->act.defer_data->len = *len;
-
- *act_ret = act;
- return TRUE;
-
- case E2K_ACTION_BOUNCE:
- if (!e2k_rule_extract_uint32 (data, len, &act->act.bounce_code))
- goto lose;
-
- *act_ret = act;
- return TRUE;
-
- case E2K_ACTION_FORWARD:
- case E2K_ACTION_DELEGATE:
- {
- guint16 nentries, nvalues;
- gint i, j;
-
- if (!e2k_rule_extract_uint16 (data, len, &nentries))
- goto lose;
- act->act.addr_list = e2k_addr_list_new (nentries);
- for (i = 0; i < nentries; i++) {
- /* FIXME: what is this? */
- if (*len < 1 || **data != 1)
- goto lose;
- (*len)--;
- (*data)++;
-
- if (!e2k_rule_extract_uint16 (data, len, &nvalues))
- goto lose;
- act->act.addr_list->entry[i].nvalues = nvalues;
- act->act.addr_list->entry[i].propval = g_new0 (E2kPropValue, nvalues);
-
- for (j = 0; j < nvalues; j++) {
- if (!e2k_rule_extract_propvalue (data, len, &act->act.addr_list->entry[i].propval[j]))
- goto lose;
- }
- }
-
- *act_ret = act;
- return TRUE;
- }
-
- case E2K_ACTION_TAG:
- if (!e2k_rule_extract_propvalue (data, len, &act->act.proptag))
- goto lose;
-
- *act_ret = act;
- return TRUE;
-
- case E2K_ACTION_DELETE:
- *act_ret = act;
- return TRUE;
-
- case E2K_ACTION_MARK_AS_READ:
- /* FIXME */
- return FALSE;
-
- default:
- break;
- }
-
- lose:
- e2k_action_free (act);
- return FALSE;
-}
-
-/**
- * e2k_actions_extract:
- * @data: pointer to data pointer
- * @len: pointer to data length
- * @actions: pointer to array to store actions in
- *
- * Attempts to extract a list of actions from *@data, which contains a
- * binary-encoded list of actions from a server-side rule.
- *
- * On success, *@actions will contain the extracted list, *@data will
- * be advanced past the end of the restriction data, and *@len will be
- * decremented accordingly.
- *
- * Return value: success or failure
- **/
-gboolean
-e2k_actions_extract (guint8 **data, gint *len, GPtrArray **actions)
-{
- GPtrArray *acts;
- E2kAction *act;
- guint32 actlen;
- guint16 nacts;
- gint i;
-
- if (!e2k_rule_extract_uint32 (data, len, &actlen))
- return FALSE;
- if (actlen > *len)
- return FALSE;
-
- if (!e2k_rule_extract_uint16 (data, len, &nacts))
- return FALSE;
-
- acts = g_ptr_array_new ();
- for (i = 0; i < nacts; i++) {
- if (!extract_action (data, len, &act)) {
- e2k_actions_free (acts);
- return FALSE;
- } else
- g_ptr_array_add (acts, act);
- }
-
- *actions = acts;
- return TRUE;
-}
-
-static void
-append_action (GByteArray *ba, E2kAction *act)
-{
- gint actlen_offset, actlen;
- gchar type;
-
- /* Save space for length */
- actlen_offset = ba->len;
- e2k_rule_append_uint16 (ba, 0);
-
- e2k_rule_append_byte (ba, act->type);
- e2k_rule_append_uint32 (ba, act->flavor);
- e2k_rule_append_uint32 (ba, act->flags);
-
- switch (act->type) {
- case E2K_ACTION_MOVE:
- case E2K_ACTION_COPY:
- /* FIXME: what is this? */
- e2k_rule_append_byte (ba, 1);
-
- e2k_rule_append_uint16 (ba, act->act.xfer.store_entryid->len +
- E2K_ACTION_XFER_STORE_ENTRYID_PREFIX_LEN);
- g_byte_array_append (ba, (guint8 *) E2K_ACTION_XFER_STORE_ENTRYID_PREFIX,
- E2K_ACTION_XFER_STORE_ENTRYID_PREFIX_LEN);
- g_byte_array_append (ba, act->act.xfer.store_entryid->data,
- act->act.xfer.store_entryid->len);
-
- e2k_rule_append_uint16 (ba, 49);
- type = MAPI_FOLDER;
- g_byte_array_append (ba, (guint8 *) &type, 1);
- g_byte_array_append (ba, act->act.xfer.folder_source_key->data,
- act->act.xfer.folder_source_key->len);
- break;
-
- case E2K_ACTION_REPLY:
- case E2K_ACTION_OOF_REPLY:
- g_byte_array_append (ba, act->act.reply.entryid->data,
- act->act.reply.entryid->len);
- g_byte_array_append (ba, act->act.reply.reply_template_guid, 16);
- break;
-
- case E2K_ACTION_DEFER:
- g_byte_array_append (ba, act->act.defer_data->data,
- act->act.defer_data->len);
- break;
-
- case E2K_ACTION_BOUNCE:
- e2k_rule_append_uint32 (ba, act->act.bounce_code);
- break;
-
- case E2K_ACTION_FORWARD:
- case E2K_ACTION_DELEGATE:
- {
- gint i, j;
- E2kAddrList *list;
- E2kAddrEntry *entry;
-
- list = act->act.addr_list;
- e2k_rule_append_uint16 (ba, list->nentries);
- for (i = 0; i < list->nentries; i++) {
- /* FIXME: what is this? */
- e2k_rule_append_byte (ba, 1);
-
- entry = &list->entry[i];
- e2k_rule_append_uint16 (ba, entry->nvalues);
- for (j = 0; j < entry->nvalues; j++)
- e2k_rule_append_propvalue (ba, &entry->propval[j]);
- }
- break;
- }
-
- case E2K_ACTION_TAG:
- e2k_rule_append_propvalue (ba, &act->act.proptag);
- break;
-
- case E2K_ACTION_DELETE:
- break;
-
- case E2K_ACTION_MARK_AS_READ:
- /* FIXME */
- break;
-
- default:
- break;
- }
-
- actlen = ba->len - actlen_offset - 2;
- e2k_rule_write_uint16 (ba->data + actlen_offset, actlen);
-}
-
-/**
- * e2k_actions_append:
- * @ba: a buffer into which a server-side rule is being constructed
- * @actions: the actions to append to @ba
- *
- * Appends @actions to @ba as part of a server-side rule.
- **/
-void
-e2k_actions_append (GByteArray *ba, GPtrArray *actions)
-{
- gint actlen_offset, actlen, i;
-
- /* Save space for length */
- actlen_offset = ba->len;
- e2k_rule_append_uint32 (ba, 0);
-
- e2k_rule_append_uint16 (ba, actions->len);
- for (i = 0; i < actions->len; i++)
- append_action (ba, actions->pdata[i]);
-
- actlen = ba->len - actlen_offset - 4;
- e2k_rule_write_uint32 (ba->data + actlen_offset, actlen);
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2002-2004 Novell, Inc. */
-
-#ifndef __E2K_ACTION_H__
-#define __E2K_ACTION_H__
-
-#include "e2k-types.h"
-#include "e2k-properties.h"
-#include "e2k-rule.h"
-
-G_BEGIN_DECLS
-
-gboolean e2k_actions_extract (guint8 **data,
- gint *len,
- GPtrArray **actions);
-void e2k_actions_append (GByteArray *ba,
- GPtrArray *actions);
-
-E2kAction *e2k_action_move (GByteArray *store_entryid,
- GByteArray *folder_source_key);
-E2kAction *e2k_action_copy (GByteArray *store_entryid,
- GByteArray *folder_source_key);
-E2kAction *e2k_action_reply (GByteArray *template_entryid,
- guint8 template_guid[16]);
-E2kAction *e2k_action_oof_reply (GByteArray *template_entryid,
- guint8 template_guid[16]);
-E2kAction *e2k_action_defer (GByteArray *data);
-E2kAction *e2k_action_bounce (E2kActionBounceCode bounce_code);
-E2kAction *e2k_action_forward (E2kAddrList *list);
-E2kAction *e2k_action_delegate (E2kAddrList *list);
-E2kAction *e2k_action_tag (const gchar *propname,
- E2kPropType type,
- gpointer value);
-E2kAction *e2k_action_delete (void);
-
-void e2k_actions_free (GPtrArray *actions);
-void e2k_action_free (E2kAction *act);
-
-E2kAddrList *e2k_addr_list_new (gint nentries);
-void e2k_addr_list_set_local (E2kAddrList *list,
- gint entry_num,
- const gchar *display_name,
- const gchar *exchange_dn,
- const gchar *email);
-void e2k_addr_list_set_oneoff (E2kAddrList *list,
- gint entry_num,
- const gchar *display_name,
- const gchar *email);
-void e2k_addr_list_free (E2kAddrList *list);
-
-G_END_DECLS
-
-#endif /* __E2K_ACTION_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2003, 2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* e2k-autoconfig: Automatic account configuration backend code */
-
-/* Note on gtk-doc: Several functions in this file have intentionally-
- * broken gtk-doc comments (that have only a single "*" after the
- * opening "/") so that they can be overridden by versions in
- * docs/reference/tmpl/e2k-autoconfig.sgml that use better markup.
- * If you change the docs here, be sure to change them there as well.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-
-#ifndef G_OS_WIN32
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#else
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <windns.h>
-#ifndef DNS_TYPE_SRV
-#define DNS_TYPE_SRV 33
-#endif
-#endif
-
-#include "e2k-autoconfig.h"
-#include "e2k-context.h"
-#include "e2k-global-catalog.h"
-#include "e2k-propnames.h"
-#include "e2k-uri.h"
-#include "e2k-utils.h"
-#include "e2k-xml-utils.h"
-#include "xntlm.h"
-
-#include <libedataserver/e-data-server-util.h>
-#include <libedataserver/e-url.h>
-#include <libedataserverui/e-passwords.h>
-#include <gconf/gconf-client.h>
-#include <libxml/tree.h>
-#include <libxml/HTMLparser.h>
-
-#include <gtk/gtk.h>
-
-#ifdef G_OS_WIN32
-#undef CONNECTOR_PREFIX
-#define CONNECTOR_PREFIX e_util_get_prefix ()
-#endif
-
-static gchar *find_olson_timezone (const gchar *windows_timezone);
-static void set_account_uri_string (E2kAutoconfig *ac);
-
-/**
- * e2k_autoconfig_new:
- * @owa_uri: the OWA URI, or %NULL to (try to) use a default
- * @username: the username (or DOMAIN\username), or %NULL to use a default
- * @password: the password, or %NULL if not yet known
- * @auth_pref: information about what auth type to use
- *
- * Creates an autoconfig context, based on information stored in the
- * config file or provided as arguments.
- *
- * Return value: an autoconfig context
- **/
-E2kAutoconfig *
-e2k_autoconfig_new (const gchar *owa_uri, const gchar *username,
- const gchar *password, E2kAutoconfigAuthPref auth_pref)
-{
- E2kAutoconfig *ac;
-
- ac = g_new0 (E2kAutoconfig, 1);
-
- if (e2k_autoconfig_lookup_option ("Disable-Plaintext")) {
- ac->auth_pref = E2K_AUTOCONFIG_USE_NTLM;
- ac->require_ntlm = TRUE;
- } else
- ac->auth_pref = auth_pref;
-
- e2k_autoconfig_set_owa_uri (ac, owa_uri);
- /* use same auth for gal as for the server */
- e2k_autoconfig_set_gc_server (ac, NULL, -1, ac->auth_pref == E2K_AUTOCONFIG_USE_BASIC ? E2K_AUTOCONFIG_USE_GAL_BASIC :
- ac->auth_pref == E2K_AUTOCONFIG_USE_NTLM ? E2K_AUTOCONFIG_USE_GAL_NTLM :
- E2K_AUTOCONFIG_USE_GAL_DEFAULT);
- e2k_autoconfig_set_username (ac, username);
- e2k_autoconfig_set_password (ac, password);
-
- return ac;
-}
-
-/**
- * e2k_autoconfig_free:
- * @ac: an autoconfig context
- *
- * Frees @ac.
- **/
-void
-e2k_autoconfig_free (E2kAutoconfig *ac)
-{
- g_free (ac->owa_uri);
- g_free (ac->gc_server);
- g_free (ac->username);
- g_free (ac->password);
- g_free (ac->display_name);
- g_free (ac->email);
- g_free (ac->account_uri);
- g_free (ac->exchange_server);
- g_free (ac->timezone);
- g_free (ac->nt_domain);
- g_free (ac->w2k_domain);
- g_free (ac->home_uri);
- g_free (ac->exchange_dn);
- g_free (ac->pf_server);
-
- g_free (ac);
-}
-
-static void
-reset_gc_derived (E2kAutoconfig *ac)
-{
- if (ac->display_name) {
- g_free (ac->display_name);
- ac->display_name = NULL;
- }
- if (ac->email) {
- g_free (ac->email);
- ac->email = NULL;
- }
- if (ac->account_uri) {
- g_free (ac->account_uri);
- ac->account_uri = NULL;
- }
-}
-
-static void
-reset_owa_derived (E2kAutoconfig *ac)
-{
- /* Clear the information we explicitly get from OWA */
- if (ac->timezone) {
- g_free (ac->timezone);
- ac->timezone = NULL;
- }
- if (ac->exchange_dn) {
- g_free (ac->exchange_dn);
- ac->exchange_dn = NULL;
- }
- if (ac->pf_server) {
- g_free (ac->pf_server);
- ac->pf_server = NULL;
- }
- if (ac->home_uri) {
- g_free (ac->home_uri);
- ac->home_uri = NULL;
- }
-
- /* Reset domain info we may have implicitly got */
- ac->use_ntlm = (ac->auth_pref != E2K_AUTOCONFIG_USE_BASIC);
- if (ac->nt_domain_defaulted) {
- g_free (ac->nt_domain);
- ac->nt_domain = g_strdup (e2k_autoconfig_lookup_option ("NT-Domain"));
- ac->nt_domain_defaulted = FALSE;
- }
- if (ac->w2k_domain)
- g_free (ac->w2k_domain);
- ac->w2k_domain = g_strdup (e2k_autoconfig_lookup_option ("Domain"));
-
- /* Reset GC-derived information since it depends on the
- * OWA-derived information too.
- */
- reset_gc_derived (ac);
-}
-
-/**
- * e2k_autoconfig_set_owa_uri:
- * @ac: an autoconfig context
- * @owa_uri: the new OWA URI, or %NULL
- *
- * Sets @ac's #owa_uri field to @owa_uri (or the default if @owa_uri is
- * %NULL), and resets any fields whose values had been set based on
- * the old value of #owa_uri.
- **/
-void
-e2k_autoconfig_set_owa_uri (E2kAutoconfig *ac, const gchar *owa_uri)
-{
- reset_owa_derived (ac);
- if (ac->gc_server_autodetected)
- e2k_autoconfig_set_gc_server (ac, NULL, -1, ac->gal_auth);
- g_free (ac->owa_uri);
-
- if (owa_uri) {
- if (!strncmp (owa_uri, "http", 4))
- ac->owa_uri = g_strdup (owa_uri);
- else
- ac->owa_uri = g_strdup_printf ("http://%s", owa_uri);
- } else
- ac->owa_uri = g_strdup (e2k_autoconfig_lookup_option ("OWA-URL"));
-}
-
-/**
- * e2k_autoconfig_set_gc_server:
- * @ac: an autoconfig context
- * @gc_server: the new GC server, or %NULL
- * @gal_limit: GAL search size limit, or -1 for no limit
- * @gal_auth: Preferred authentication method for gal
- *
- * Sets @ac's #gc_server field to @gc_server (or the default if
- * @gc_server is %NULL) and the #gal_limit field to @gal_limit, and
- * resets any fields whose values had been set based on the old value
- * of #gc_server.
- **/
-void
-e2k_autoconfig_set_gc_server (E2kAutoconfig *ac, const gchar *gc_server,
- gint gal_limit, E2kAutoconfigGalAuthPref gal_auth)
-{
- const gchar *default_gal_limit;
-
- reset_gc_derived (ac);
- g_free (ac->gc_server);
-
- if (gc_server)
- ac->gc_server = g_strdup (gc_server);
- else
- ac->gc_server = g_strdup (e2k_autoconfig_lookup_option ("Global-Catalog"));
- ac->gc_server_autodetected = FALSE;
-
- if (gal_limit == -1) {
- default_gal_limit = e2k_autoconfig_lookup_option ("GAL-Limit");
- if (default_gal_limit)
- gal_limit = atoi (default_gal_limit);
- }
- ac->gal_limit = gal_limit;
- ac->gal_auth = gal_auth;
-}
-
-/**
- * e2k_autoconfig_set_username:
- * @ac: an autoconfig context
- * @username: the new username (or DOMAIN\username), or %NULL
- *
- * Sets @ac's #username field to @username (or the default if
- * @username is %NULL), and resets any fields whose values had been
- * set based on the old value of #username.
- **/
-void
-e2k_autoconfig_set_username (E2kAutoconfig *ac, const gchar *username)
-{
- gint dlen;
-
- reset_owa_derived (ac);
- g_free (ac->username);
-
- if (username) {
- /* If the username includes a domain name, split it out */
- dlen = strcspn (username, "/\\");
- if (username[dlen]) {
- g_free (ac->nt_domain);
- ac->nt_domain = g_strndup (username, dlen);
- ac->username = g_strdup (username + dlen + 1);
- ac->nt_domain_defaulted = FALSE;
- } else
- ac->username = g_strdup (username);
- } else
- ac->username = g_strdup (g_get_user_name ());
-}
-
-/**
- * e2k_autoconfig_set_password:
- * @ac: an autoconfig context
- * @password: the new password, or %NULL to clear
- *
- * Sets or clears @ac's #password field.
- **/
-void
-e2k_autoconfig_set_password (E2kAutoconfig *ac, const gchar *password)
-{
- g_free (ac->password);
- ac->password = g_strdup (password);
-}
-
-static void
-get_ctx_auth_handler (SoupMessage *msg, gpointer user_data)
-{
- E2kAutoconfig *ac = user_data;
- GSList *headers;
- const gchar *challenge_hdr;
-
- ac->saw_ntlm = ac->saw_basic = FALSE;
- headers = e2k_http_get_headers (msg->response_headers,
- "WWW-Authenticate");
- while (headers) {
- challenge_hdr = headers->data;
-
- if (!strcmp (challenge_hdr, "NTLM"))
- ac->saw_ntlm = TRUE;
- else if (!strncmp (challenge_hdr, "Basic ", 6))
- ac->saw_basic = TRUE;
-
- if (!strncmp (challenge_hdr, "NTLM ", 5) &&
- (!ac->w2k_domain || !ac->nt_domain)) {
- guchar *challenge;
- gsize length = 0;
-
- challenge = g_base64_decode (challenge_hdr + 5, &length);
- if (!ac->nt_domain)
- ac->nt_domain_defaulted = TRUE;
- xntlm_parse_challenge (challenge, length,
- NULL,
- ac->nt_domain ? NULL : &ac->nt_domain,
- ac->w2k_domain ? NULL : &ac->w2k_domain);
- g_free (challenge);
- ac->saw_ntlm = TRUE;
- g_slist_free (headers);
- return;
- }
-
- headers = headers->next;
- }
- g_slist_free (headers);
-}
-
-/*
- * e2k_autoconfig_get_context:
- * @ac: an autoconfig context
- * @op: an #E2kOperation, for cancellation
- * @result: on output, a result code
- *
- * Checks if @ac's URI and authentication parameters work, and if so
- * returns an #E2kContext using them. On return, *@result (which
- * may not be %NULL) will contain a result code as follows:
- *
- * %E2K_AUTOCONFIG_OK: success
- * %E2K_AUTOCONFIG_REDIRECT: The server issued a valid-looking
- * redirect. @ac->owa_uri has been updated and the caller
- * should try again.
- * %E2K_AUTOCONFIG_TRY_SSL: The server requires SSL.
- * @ac->owa_uri has been updated and the caller should try
- * again.
- * %E2K_AUTOCONFIG_AUTH_ERROR: Generic authentication failure.
- * Probably password incorrect
- * %E2K_AUTOCONFIG_AUTH_ERROR_TRY_DOMAIN: Authentication failed.
- * Including an NT domain with the username (or using NTLM)
- * may fix the problem.
- * %E2K_AUTOCONFIG_AUTH_ERROR_TRY_BASIC: Caller requested NTLM
- * auth, but only Basic was available.
- * %E2K_AUTOCONFIG_AUTH_ERROR_TRY_NTLM: Caller requested Basic
- * auth, but only NTLM was available.
- * %E2K_AUTOCONFIG_EXCHANGE_5_5: Server appears to be Exchange 5.5.
- * %E2K_AUTOCONFIG_NOT_EXCHANGE: Server does not appear to be
- * any version of Exchange
- * %E2K_AUTOCONFIG_NO_OWA: Server may be Exchange 2000, but OWA
- * is not present at the given URL.
- * %E2K_AUTOCONFIG_NO_MAILBOX: OWA claims the user has no mailbox.
- * %E2K_AUTOCONFIG_CANT_RESOLVE: Could not resolve hostname.
- * %E2K_AUTOCONFIG_CANT_CONNECT: Could not connect to server.
- * %E2K_AUTOCONFIG_CANCELLED: User cancelled
- * %E2K_AUTOCONFIG_FAILED: Other error.
- *
- * Return value: the new context, or %NULL
- *
- * (If you change this comment, see the note at the top of this file.)
- **/
-E2kContext *
-e2k_autoconfig_get_context (E2kAutoconfig *ac, E2kOperation *op,
- E2kAutoconfigResult *result)
-{
- E2kContext *ctx;
- SoupMessage *msg;
- E2kHTTPStatus status;
- const gchar *ms_webstorage;
- xmlDoc *doc;
- xmlNode *node;
- xmlChar *equiv, *content, *href;
-
- ctx = e2k_context_new (ac->owa_uri);
- if (!ctx) {
- *result = E2K_AUTOCONFIG_FAILED;
- return NULL;
- }
- e2k_context_set_auth (ctx, ac->username, ac->nt_domain,
- ac->use_ntlm ? "NTLM" : "Basic", ac->password);
-
- msg = e2k_soup_message_new (ctx, ac->owa_uri, SOUP_METHOD_GET);
-
- g_return_val_if_fail (msg != NULL, NULL);
- g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
-
- soup_message_headers_append (msg->request_headers, "Accept-Language",
- e2k_http_accept_language ());
- soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT);
-
- soup_message_add_status_code_handler (msg, "got-headers",
- E2K_HTTP_UNAUTHORIZED,
- G_CALLBACK (get_ctx_auth_handler),
- ac);
-
- try_again:
- e2k_context_send_message (ctx, op, msg);
- status = msg->status_code;
-
- /* Check for cancellation or other transport error. */
- if (E2K_HTTP_STATUS_IS_TRANSPORT_ERROR (status)) {
- if (status == E2K_HTTP_CANCELLED)
- *result = E2K_AUTOCONFIG_CANCELLED;
- else if (status == E2K_HTTP_CANT_RESOLVE)
- *result = E2K_AUTOCONFIG_CANT_RESOLVE;
- else
- *result = E2K_AUTOCONFIG_CANT_CONNECT;
- goto done;
- }
-
- /* Check for an authentication failure. This could be because
- * the password is incorrect, or because we used Basic auth
- * without specifying a domain and the server doesn't have a
- * default domain, or because we tried to use an auth type the
- * server doesn't allow.
- */
- if (status == E2K_HTTP_UNAUTHORIZED) {
- if (!ac->use_ntlm && !ac->nt_domain)
- *result = E2K_AUTOCONFIG_AUTH_ERROR_TRY_DOMAIN;
- else if (ac->use_ntlm && !ac->saw_ntlm)
- *result = E2K_AUTOCONFIG_AUTH_ERROR_TRY_BASIC;
- else if (!ac->use_ntlm && !ac->saw_basic)
- *result = E2K_AUTOCONFIG_AUTH_ERROR_TRY_NTLM;
- else
- *result = E2K_AUTOCONFIG_AUTH_ERROR;
- goto done;
- }
-
- /* A redirection to "logon.asp" means this is Exchange 5.5
- * OWA. A redirection to "owalogon.asp" means this is Exchange
- * 2003 forms-based authentication. A redirection to
- * "CookieAuth.dll" means that it's an Exchange 2003 server
- * behind an ISA Server 2004 proxy. Other redirections most
- * likely indicate that the user's mailbox has been moved to a
- * new server.
- */
- if (E2K_HTTP_STATUS_IS_REDIRECTION (status)) {
- const gchar *location;
- gchar *new_uri;
-
- location = soup_message_headers_get (msg->response_headers,
- "Location");
- if (!location) {
- *result = E2K_AUTOCONFIG_FAILED;
- goto done;
- }
-
- if (strstr (location, "/logon.asp")) {
- *result = E2K_AUTOCONFIG_EXCHANGE_5_5;
- goto done;
- } else if (strstr (location, "/owalogon.asp") ||
- strstr (location, "/CookieAuth.dll")) {
- if (e2k_context_fba (ctx, msg))
- goto try_again;
- *result = E2K_AUTOCONFIG_AUTH_ERROR;
- goto done;
- }
-
- new_uri = e2k_strdup_with_trailing_slash (location);
- e2k_autoconfig_set_owa_uri (ac, new_uri);
- g_free (new_uri);
- *result = E2K_AUTOCONFIG_REDIRECT;
- goto done;
- }
-
- /* If the server requires SSL, it will send back 403 Forbidden
- * with a body explaining that.
- */
- if (status == E2K_HTTP_FORBIDDEN &&
- !strncmp (ac->owa_uri, "http:", 5) && msg->response_body->length > 0) {
- if (strstr (msg->response_body->data, "SSL")) {
- gchar *new_uri =
- g_strconcat ("https:", ac->owa_uri + 5, NULL);
- e2k_autoconfig_set_owa_uri (ac, new_uri);
- g_free (new_uri);
- *result = E2K_AUTOCONFIG_TRY_SSL;
- goto done;
- }
- }
-
- /* Figure out some stuff about the server */
- ms_webstorage = soup_message_headers_get (msg->response_headers,
- "MS-WebStorage");
- if (ms_webstorage) {
- if (!strncmp (ms_webstorage, "6.0.", 4))
- ac->version = E2K_EXCHANGE_2000;
- else if (!strncmp (ms_webstorage, "6.5.", 4))
- ac->version = E2K_EXCHANGE_2003;
- else
- ac->version = E2K_EXCHANGE_FUTURE;
- } else {
- const gchar *server = soup_message_headers_get (msg->response_headers, "Server");
-
- /* If the server explicitly claims to be something
- * other than IIS, then return the "not windows"
- * error.
- */
- if (server && !strstr (server, "IIS")) {
- *result = E2K_AUTOCONFIG_NOT_EXCHANGE;
- goto done;
- }
-
- /* It's probably Exchange 2000... older versions
- * didn't include the MS-WebStorage header here. But
- * we don't know for sure.
- */
- ac->version = E2K_EXCHANGE_UNKNOWN;
- }
-
- /* If we're talking to OWA, then 404 Not Found means you don't
- * have a mailbox. Otherwise, it means you're not talking to
- * Exchange (even 5.5).
- */
- if (status == E2K_HTTP_NOT_FOUND) {
- if (ms_webstorage)
- *result = E2K_AUTOCONFIG_NO_MAILBOX;
- else
- *result = E2K_AUTOCONFIG_NOT_EXCHANGE;
- goto done;
- }
-
- /* Any other error else gets generic failure */
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
- *result = E2K_AUTOCONFIG_FAILED;
- goto done;
- }
-
- /* Parse the returned HTML. */
- doc = e2k_parse_html (msg->response_body->data, msg->response_body->length);
- if (!doc) {
- /* Not HTML? */
- *result = ac->version == E2K_EXCHANGE_UNKNOWN ?
- E2K_AUTOCONFIG_NO_OWA :
- E2K_AUTOCONFIG_FAILED;
- goto done;
- }
-
- /* Make sure it's not Exchange 5.5 */
- if (ac->version == E2K_EXCHANGE_UNKNOWN &&
- strstr (ac->owa_uri, "/logon.asp")) {
- *result = E2K_AUTOCONFIG_EXCHANGE_5_5;
- goto done;
- }
-
- /* Make sure it's not trying to redirect us to Exchange 5.5 */
- for (node = doc->children; node; node = e2k_xml_find (node, "meta")) {
- gboolean ex55 = FALSE;
-
- equiv = xmlGetProp (node, (xmlChar *) "http-equiv");
- content = xmlGetProp (node, (xmlChar *) "content");
- if (equiv && content &&
- !g_ascii_strcasecmp ((gchar *) equiv, "REFRESH") &&
- xmlStrstr (content, (xmlChar *) "/logon.asp"))
- ex55 = TRUE;
- if (equiv)
- xmlFree (equiv);
- if (content)
- xmlFree (content);
-
- if (ex55) {
- *result = E2K_AUTOCONFIG_EXCHANGE_5_5;
- goto done;
- }
- }
-
- /* Try to find the base URI */
- node = e2k_xml_find (doc->children, "base");
- if (node) {
- /* We won */
- *result = E2K_AUTOCONFIG_OK;
- href = xmlGetProp (node, (xmlChar *) "href");
- g_free (ac->home_uri);
- ac->home_uri = g_strdup ((gchar *) href);
- xmlFree (href);
- } else
- *result = E2K_AUTOCONFIG_FAILED;
- xmlFreeDoc (doc);
-
- done:
- g_object_unref (msg);
-
- if (*result != E2K_AUTOCONFIG_OK) {
- g_object_unref (ctx);
- ctx = NULL;
- }
- return ctx;
-}
-
-static const gchar *home_properties[] = {
- PR_STORE_ENTRYID,
- E2K_PR_EXCHANGE_TIMEZONE
-};
-static const gint n_home_properties = sizeof (home_properties) / sizeof (home_properties[0]);
-
-/*
- * e2k_autoconfig_check_exchange:
- * @ac: an autoconfiguration context
- * @op: an #E2kOperation, for cancellation
- *
- * Tries to connect to the the Exchange server using the OWA URL,
- * username, and password in @ac. Attempts to determine the domain
- * name and home_uri, and then given the home_uri, looks up the
- * user's mailbox entryid (used to find his Exchange 5.5 DN) and
- * default timezone.
- *
- * The returned codes are the same as for e2k_autoconfig_get_context()
- * with the following changes/additions/removals:
- *
- * %E2K_AUTOCONFIG_REDIRECT: URL returned in first redirect returned
- * another redirect, which was not followed.
- * %E2K_AUTOCONFIG_CANT_BPROPFIND: The server does not allow
- * BPROPFIND due to IIS Lockdown configuration
- * %E2K_AUTOCONFIG_TRY_SSL: Not used; always handled internally by
- * e2k_autoconfig_check_exchange()
- *
- * Return value: an #E2kAutoconfigResult
- *
- * (If you change this comment, see the note at the top of this file.)
- **/
-E2kAutoconfigResult
-e2k_autoconfig_check_exchange (E2kAutoconfig *ac, E2kOperation *op)
-{
- xmlDoc *doc;
- xmlNode *node;
- E2kHTTPStatus status;
- E2kAutoconfigResult result;
- gchar *new_uri, *pf_uri;
- E2kContext *ctx;
- gboolean redirected = FALSE;
- E2kResultIter *iter;
- E2kResult *results;
- GByteArray *entryid;
- const gchar *exchange_dn, *timezone, *hrefs[] = { "" };
- xmlChar *prop;
- SoupBuffer *response;
- E2kUri *euri;
-
- g_return_val_if_fail (ac->owa_uri != NULL, E2K_AUTOCONFIG_FAILED);
- g_return_val_if_fail (ac->username != NULL, E2K_AUTOCONFIG_FAILED);
- g_return_val_if_fail (ac->password != NULL, E2K_AUTOCONFIG_FAILED);
-
- try_again:
- ctx = e2k_autoconfig_get_context (ac, op, &result);
-
- switch (result) {
- case E2K_AUTOCONFIG_OK:
- break;
-
- case E2K_AUTOCONFIG_AUTH_ERROR_TRY_BASIC:
- if (ac->use_ntlm && !ac->require_ntlm) {
- ac->use_ntlm = FALSE;
- goto try_again;
- } else
- return E2K_AUTOCONFIG_AUTH_ERROR;
-
- case E2K_AUTOCONFIG_AUTH_ERROR_TRY_NTLM:
- return E2K_AUTOCONFIG_AUTH_ERROR;
-
- case E2K_AUTOCONFIG_REDIRECT:
- if (!redirected) {
- redirected = TRUE;
- goto try_again;
- } else
- return result;
-
- case E2K_AUTOCONFIG_TRY_SSL:
- goto try_again;
-
- case E2K_AUTOCONFIG_NO_OWA:
- default:
- /* If the provided OWA URI had no path, try appending
- * /exchange.
- */
- euri = e2k_uri_new (ac->owa_uri);
- g_return_val_if_fail (euri != NULL, result);
- if (!euri->path || !strcmp (euri->path, "/")) {
- e2k_uri_free (euri);
- new_uri = e2k_uri_concat (ac->owa_uri, "exchange/");
- e2k_autoconfig_set_owa_uri (ac, new_uri);
- g_free (new_uri);
- goto try_again;
- }
- e2k_uri_free (euri);
- return result;
- }
-
- /* Find the link to the public folders */
- if (ac->version < E2K_EXCHANGE_2003)
- pf_uri = g_strdup_printf ("%s/?Cmd=contents", ac->owa_uri);
- else
- pf_uri = g_strdup_printf ("%s/?Cmd=navbar", ac->owa_uri);
-
- status = e2k_context_get_owa (ctx, NULL, pf_uri, FALSE, &response);
- g_free (pf_uri);
- if (E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
- doc = e2k_parse_html (response->data, response->length);
- soup_buffer_free (response);
- } else
- doc = NULL;
-
- if (doc) {
- for (node = e2k_xml_find (doc->children, "img"); node; node = e2k_xml_find (node, "img")) {
- prop = xmlGetProp (node, (xmlChar *) "src");
- if (prop && xmlStrstr (prop, (xmlChar *) "public") && node->parent) {
- node = node->parent;
- xmlFree (prop);
- prop = xmlGetProp (node, (xmlChar *) "href");
- if (prop) {
- euri = e2k_uri_new ((gchar *) prop);
- ac->pf_server = g_strdup (euri->host);
- e2k_uri_free (euri);
- xmlFree (prop);
- }
- break;
- }
- }
- xmlFreeDoc (doc);
- } else
- g_warning ("Could not parse pf page");
-
- /* Now find the store entryid and default timezone. We
- * gratuitously use BPROPFIND in order to test if they
- * have the IIS Lockdown problem.
- */
- iter = e2k_context_bpropfind_start (ctx, op,
- ac->home_uri, hrefs, 1,
- home_properties,
- n_home_properties);
- results = e2k_result_iter_next (iter);
- if (results) {
- timezone = e2k_properties_get_prop (results->props,
- E2K_PR_EXCHANGE_TIMEZONE);
- if (timezone)
- ac->timezone = find_olson_timezone (timezone);
-
- entryid = e2k_properties_get_prop (results->props,
- PR_STORE_ENTRYID);
- if (entryid) {
- exchange_dn = e2k_entryid_to_dn (entryid);
- if (exchange_dn)
- ac->exchange_dn = g_strdup (exchange_dn);
- }
- }
- status = e2k_result_iter_free (iter);
- g_object_unref (ctx);
-
- if (status == E2K_HTTP_UNAUTHORIZED) {
- if (ac->use_ntlm && !ac->require_ntlm) {
- ac->use_ntlm = FALSE;
- goto try_again;
- } else
- return E2K_AUTOCONFIG_AUTH_ERROR;
- } else if (status == E2K_HTTP_NOT_FOUND)
- return E2K_AUTOCONFIG_CANT_BPROPFIND;
- else if (status == E2K_HTTP_CANCELLED)
- return E2K_AUTOCONFIG_CANCELLED;
- else if (status == E2K_HTTP_CANT_RESOLVE)
- return E2K_AUTOCONFIG_CANT_RESOLVE;
- else if (E2K_HTTP_STATUS_IS_TRANSPORT_ERROR (status))
- return E2K_AUTOCONFIG_CANT_CONNECT;
- else if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status))
- return E2K_AUTOCONFIG_FAILED;
-
- return ac->exchange_dn ? E2K_AUTOCONFIG_OK : E2K_AUTOCONFIG_FAILED;
-}
-
-/* FIXME: make this cancellable */
-static void
-find_global_catalog (E2kAutoconfig *ac)
-{
-#ifndef G_OS_WIN32
- gint count, len;
- guchar answer[1024], namebuf[1024], *end, *p;
- guint16 type, qclass, rdlength, priority, weight, port;
- guint32 ttl;
- HEADER *header;
-
- if (!ac->w2k_domain)
- return;
-
- len = res_querydomain ("_gc._tcp", ac->w2k_domain, C_IN, T_SRV,
- answer, sizeof (answer));
- if (len == -1)
- return;
-
- header = (HEADER *)answer;
- p = answer + sizeof (HEADER);
- end = answer + len;
-
- /* See RFCs 1035 and 2782 for details of the parsing */
-
- /* Skip query */
- count = ntohs (header->qdcount);
- while (count-- && p < end) {
- p += dn_expand (answer, end, p, (gchar *) namebuf, sizeof (namebuf));
- p += 4;
- }
-
- /* Read answers */
- while (count-- && p < end) {
- p += dn_expand (answer, end, p, (gchar *) namebuf, sizeof (namebuf));
- GETSHORT (type, p);
- GETSHORT (qclass, p);
- GETLONG (ttl, p);
- GETSHORT (rdlength, p);
-
- if (type != T_SRV || qclass != C_IN) {
- p += rdlength;
- continue;
- }
-
- GETSHORT (priority, p);
- GETSHORT (weight, p);
- GETSHORT (port, p);
- p += dn_expand (answer, end, p, (gchar *) namebuf, sizeof (namebuf));
-
- /* FIXME: obey priority and weight */
- ac->gc_server = g_strdup ((gchar *) namebuf);
- ac->gc_server_autodetected = TRUE;
- return;
- }
-
- return;
-#else
- gchar *name, *casefolded_name;
- PDNS_RECORD dnsrecp, rover;
-
- name = g_strconcat ("_gc._tcp.", ac->w2k_domain, NULL);
- casefolded_name = g_utf8_strdown (name, -1);
- g_free (name);
-
- if (DnsQuery_UTF8 (casefolded_name, DNS_TYPE_SRV, DNS_QUERY_STANDARD,
- NULL, &dnsrecp, NULL) != ERROR_SUCCESS) {
- g_free (casefolded_name);
- return;
- }
-
- for (rover = dnsrecp; rover != NULL; rover = rover->pNext) {
- if (rover->wType != DNS_TYPE_SRV ||
- strcmp (rover->pName, casefolded_name) != 0)
- continue;
- ac->gc_server = g_strdup (rover->Data.SRV.pNameTarget);
- ac->gc_server_autodetected = TRUE;
- g_free (casefolded_name);
- DnsRecordListFree (dnsrecp, DnsFreeRecordList);
- return;
- }
-
- g_free (casefolded_name);
- DnsRecordListFree (dnsrecp, DnsFreeRecordList);
- return;
-#endif
-}
-
-/**
- * e2k_autoconfig_get_global_catalog
- * @ac: an autoconfig context
- * @op: an #E2kOperation, for cancellation
- *
- * Tries to connect to the global catalog associated with @ac
- * (trying to figure it out from the domain name if the server
- * name is not yet known).
- *
- * Return value: the global catalog, or %NULL if the GC server name
- * wasn't provided and couldn't be autodetected.
- */
-E2kGlobalCatalog *
-e2k_autoconfig_get_global_catalog (E2kAutoconfig *ac, E2kOperation *op)
-{
- if (!ac->gc_server) {
- find_global_catalog (ac);
- if (!ac->gc_server)
- return NULL;
- }
-
- return e2k_global_catalog_new (ac->gc_server, ac->gal_limit,
- ac->username, ac->nt_domain,
- ac->password, ac->gal_auth);
-}
-
-/*
- * e2k_autoconfig_check_global_catalog
- * @ac: an autoconfig context
- * @op: an #E2kOperation, for cancellation
- *
- * Tries to connect to the global catalog associated with @ac
- * (trying to figure it out from the domain name if the server
- * name is not yet known). On success it will look up the user's
- * full name and email address (based on his Exchange DN).
- *
- * Possible return values are:
- *
- * %E2K_AUTOCONFIG_OK: Success
- * %E2K_AUTOCONFIG_CANT_RESOLVE: Could not determine GC server
- * %E2K_AUTOCONFIG_NO_MAILBOX: Could not find information for
- * the user
- * %E2K_AUTOCONFIG_AUTH_ERROR_TRY_DOMAIN: Plaintext password auth
- * failed: need to specify NT domain
- * %E2K_AUTOCONFIG_CANCELLED: Operation was cancelled
- * %E2K_AUTOCONFIG_FAILED: Other error.
- *
- * Return value: an #E2kAutoconfigResult.
- *
- * (If you change this comment, see the note at the top of this file.)
- */
-E2kAutoconfigResult
-e2k_autoconfig_check_global_catalog (E2kAutoconfig *ac, E2kOperation *op)
-{
- E2kGlobalCatalog *gc;
- E2kGlobalCatalogEntry *entry;
- E2kGlobalCatalogStatus status;
- E2kAutoconfigResult result;
-
- g_return_val_if_fail (ac->exchange_dn != NULL, E2K_AUTOCONFIG_FAILED);
-
- gc = e2k_autoconfig_get_global_catalog (ac, op);
- if (!gc)
- return E2K_AUTOCONFIG_CANT_RESOLVE;
-
- set_account_uri_string (ac);
-
- status = e2k_global_catalog_lookup (
- gc, op, E2K_GLOBAL_CATALOG_LOOKUP_BY_LEGACY_EXCHANGE_DN,
- ac->exchange_dn, E2K_GLOBAL_CATALOG_LOOKUP_EMAIL |
- E2K_GLOBAL_CATALOG_LOOKUP_MAILBOX, &entry);
-
- if (status == E2K_GLOBAL_CATALOG_OK) {
- ac->display_name = g_strdup (entry->display_name);
- ac->email = g_strdup (entry->email);
- result = E2K_AUTOCONFIG_OK;
- } else if (status == E2K_GLOBAL_CATALOG_CANCELLED)
- result = E2K_AUTOCONFIG_CANCELLED;
-#ifndef HAVE_LDAP_NTLM_BIND
- else if (status == E2K_GLOBAL_CATALOG_AUTH_FAILED &&
- !ac->nt_domain)
- result = E2K_AUTOCONFIG_AUTH_ERROR_TRY_DOMAIN;
-#endif
- else if (status == E2K_GLOBAL_CATALOG_ERROR)
- result = E2K_AUTOCONFIG_FAILED;
- else
- result = E2K_AUTOCONFIG_NO_MAILBOX;
-
- g_object_unref (gc);
- return result;
-}
-
-static void
-set_account_uri_string (E2kAutoconfig *ac)
-{
- E2kUri *owa_uri, *home_uri;
- gchar *path, *mailbox;
- GString *uri;
-
- owa_uri = e2k_uri_new (ac->owa_uri);
- home_uri = e2k_uri_new (ac->home_uri);
-
- uri = g_string_new ("exchange://");
- if (ac->nt_domain && (!ac->use_ntlm || !ac->nt_domain_defaulted)) {
- e2k_uri_append_encoded (uri, ac->nt_domain, FALSE, "\\;:@/");
- g_string_append_c (uri, '\\');
- }
- e2k_uri_append_encoded (uri, ac->username, FALSE, ";:@/");
-
- if (!ac->use_ntlm)
- g_string_append (uri, ";auth=Basic");
-
- g_string_append_c (uri, '@');
- e2k_uri_append_encoded (uri, owa_uri->host, FALSE, ":/");
- if (owa_uri->port)
- g_string_append_printf (uri, ":%d", owa_uri->port);
- g_string_append_c (uri, '/');
-
- if (!strcmp (owa_uri->protocol, "https"))
- g_string_append (uri, ";use_ssl=always");
- g_string_append (uri, ";ad_server=");
- e2k_uri_append_encoded (uri, ac->gc_server, FALSE, ";?");
- if (ac->gal_limit != -1)
- g_string_append_printf (uri, ";ad_limit=%d", ac->gal_limit);
- if (ac->gal_auth != E2K_AUTOCONFIG_USE_GAL_DEFAULT) {
- const gchar *value = NULL;
-
- switch (ac->gal_auth) {
- case E2K_AUTOCONFIG_USE_GAL_BASIC: value = "basic"; break;
- case E2K_AUTOCONFIG_USE_GAL_NTLM: value = "ntlm"; break;
- case E2K_AUTOCONFIG_USE_GAL_DEFAULT: /* should not get here */ break;
- }
-
- if (value)
- g_string_append_printf (uri, ";ad_auth=%s", value);
- }
-
- path = g_strdup (home_uri->path + 1);
- mailbox = strrchr (path, '/');
- if (mailbox && !mailbox[1]) {
- *mailbox = '\0';
- mailbox = strrchr (path, '/');
- }
- if (mailbox) {
- *mailbox++ = '\0';
- g_string_append (uri, ";mailbox=");
- e2k_uri_append_encoded (uri, mailbox, FALSE, ";?");
- }
- g_string_append (uri, ";owa_path=/");
- e2k_uri_append_encoded (uri, path, FALSE, ";?");
- g_free (path);
-
- g_string_append (uri, ";pf_server=");
- e2k_uri_append_encoded (uri, ac->pf_server ? ac->pf_server : home_uri->host, FALSE, ";?");
-
- ac->account_uri = uri->str;
- ac->exchange_server = g_strdup (home_uri->host);
- g_string_free (uri, FALSE);
- e2k_uri_free (home_uri);
- e2k_uri_free (owa_uri);
-}
-
-/* Approximate mapping from Exchange timezones to Olson ones. Exchange
- * is less specific, so we factor in the language/country info from
- * the locale in our guess.
- *
- * We strip " Standard Time" / " Daylight Time" from the Windows
- * timezone names. (Actually, we just strip the last two words.)
- */
-static struct {
- const gchar *windows_name, *lang, *country, *olson_name;
-} zonemap[] = {
- /* (GMT-12:00) Eniwetok, Kwajalein */
- { "Dateline", NULL, NULL, "Pacific/Kwajalein" },
-
- /* (GMT-11:00) Midway Island, Samoa */
- { "Samoa", NULL, NULL, "Pacific/Midway" },
-
- /* (GMT-10:00) Hawaii */
- { "Hawaiian", NULL, NULL, "Pacific/Honolulu" },
-
- /* (GMT-09:00) Alaska */
- { "Alaskan", NULL, NULL, "America/Juneau" },
-
- /* (GMT-08:00) Pacific Time (US & Canada); Tijuana */
- { "Pacific", NULL, "CA", "America/Vancouver" },
- { "Pacific", "es", "MX", "America/Tijuana" },
- { "Pacific", NULL, NULL, "America/Los_Angeles" },
-
- /* (GMT-07:00) Arizona */
- { "US Mountain", NULL, NULL, "America/Phoenix" },
-
- /* (GMT-07:00) Mountain Time (US & Canada) */
- { "Mountain", NULL, "CA", "America/Edmonton" },
- { "Mountain", NULL, NULL, "America/Denver" },
-
- /* (GMT-06:00) Central America */
- { "Central America", NULL, "BZ", "America/Belize" },
- { "Central America", NULL, "CR", "America/Costa_Rica" },
- { "Central America", NULL, "GT", "America/Guatemala" },
- { "Central America", NULL, "HN", "America/Tegucigalpa" },
- { "Central America", NULL, "NI", "America/Managua" },
- { "Central America", NULL, "SV", "America/El_Salvador" },
-
- /* (GMT-06:00) Central Time (US & Canada) */
- { "Central", NULL, NULL, "America/Chicago" },
-
- /* (GMT-06:00) Mexico City */
- { "Mexico", NULL, NULL, "America/Mexico_City" },
-
- /* (GMT-06:00) Saskatchewan */
- { "Canada Central", NULL, NULL, "America/Regina" },
-
- /* (GMT-05:00) Bogota, Lima, Quito */
- { "SA Pacific", NULL, "BO", "America/Bogota" },
- { "SA Pacific", NULL, "EC", "America/Guayaquil" },
- { "SA Pacific", NULL, "PA", "America/Panama" },
- { "SA Pacific", NULL, "PE", "America/Lima" },
-
- /* (GMT-05:00) Eastern Time (US & Canada) */
- { "Eastern", "fr", "CA", "America/Montreal" },
- { "Eastern", NULL, NULL, "America/New_York" },
-
- /* (GMT-05:00) Indiana (East) */
- { "US Eastern", NULL, NULL, "America/Indiana/Indianapolis" },
-
- /* (GMT-04:00) Atlantic Time (Canada) */
- { "Atlantic", "es", "US", "America/Puerto_Rico" },
- { "Atlantic", NULL, "VI", "America/St_Thomas" },
- { "Atlantic", NULL, "CA", "America/Halifax" },
-
- /* (GMT-04:00) Caracas, La Paz */
- { "SA Western", NULL, "BO", "America/La_Paz" },
- { "SA Western", NULL, "VE", "America/Caracas" },
-
- /* (GMT-04:00) Santiago */
- { "Pacific SA", NULL, NULL, "America/Santiago" },
-
- /* (GMT-03:30) Newfoundland */
- { "Newfoundland", NULL, NULL, "America/St_Johns" },
-
- /* (GMT-03:00) Brasilia */
- { "E. South America", NULL, NULL, "America/Sao_Paulo" },
-
- /* (GMT-03:00) Greenland */
- { "Greenland", NULL, NULL, "America/Godthab" },
-
- /* (GMT-03:00) Buenos Aires, Georgetown */
- { "SA Eastern", NULL, NULL, "America/Buenos_Aires" },
-
- /* (GMT-02:00) Mid-Atlantic */
- { "Mid-Atlantic", NULL, NULL, "America/Noronha" },
-
- /* (GMT-01:00) Azores */
- { "Azores", NULL, NULL, "Atlantic/Azores" },
-
- /* (GMT-01:00) Cape Verde Is. */
- { "Cape Verde", NULL, NULL, "Atlantic/Cape_Verde" },
-
- /* (GMT) Casablanca, Monrovia */
- { "Greenwich", NULL, "LR", "Africa/Monrovia" },
- { "Greenwich", NULL, "MA", "Africa/Casablanca" },
-
- /* (GMT) Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London */
- { "GMT", "ga", "IE", "Europe/Dublin" },
- { "GMT", "pt", "PT", "Europe/Lisbon" },
- { "GMT", NULL, NULL, "Europe/London" },
-
- /* (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna */
- { "W. Europe", "nl", "NL", "Europe/Amsterdam" },
- { "W. Europe", "it", "IT", "Europe/Rome" },
- { "W. Europe", "sv", "SE", "Europe/Stockholm" },
- { "W. Europe", NULL, "CH", "Europe/Zurich" },
- { "W. Europe", NULL, "AT", "Europe/Vienna" },
- { "W. Europe", "de", "DE", "Europe/Berlin" },
-
- /* (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague */
- { "Central Europe", "sr", "YU", "Europe/Belgrade" },
- { "Central Europe", "sk", "SK", "Europe/Bratislava" },
- { "Central Europe", "hu", "HU", "Europe/Budapest" },
- { "Central Europe", "sl", "SI", "Europe/Ljubljana" },
- { "Central Europe", "cz", "CZ", "Europe/Prague" },
-
- /* (GMT+01:00) Brussels, Copenhagen, Madrid, Paris */
- { "Romance", NULL, "BE", "Europe/Brussels" },
- { "Romance", "da", "DK", "Europe/Copenhagen" },
- { "Romance", "es", "ES", "Europe/Madrid" },
- { "Romance", "fr", "FR", "Europe/Paris" },
-
- /* (GMT+01:00) Sarajevo, Skopje, Sofija, Vilnius, Warsaw, Zagreb */
- { "Central European", "bs", "BA", "Europe/Sarajevo" },
- { "Central European", "mk", "MK", "Europe/Skopje" },
- { "Central European", "bg", "BG", "Europe/Sofia" },
- { "Central European", "lt", "LT", "Europe/Vilnius" },
- { "Central European", "pl", "PL", "Europe/Warsaw" },
- { "Central European", "hr", "HR", "Europe/Zagreb" },
-
- /* (GMT+01:00) West Central Africa */
- { "W. Central Africa", NULL, NULL, "Africa/Kinshasa" },
-
- /* (GMT+02:00) Athens, Istanbul, Minsk */
- { "GTB", "el", "GR", "Europe/Athens" },
- { "GTB", "tr", "TR", "Europe/Istanbul" },
- { "GTB", "be", "BY", "Europe/Minsk" },
-
- /* (GMT+02:00) Bucharest */
- { "E. Europe", NULL, NULL, "Europe/Bucharest" },
-
- /* (GMT+02:00) Cairo */
- { "Egypt", NULL, NULL, "Africa/Cairo" },
-
- /* (GMT+02:00) Harare, Pretoria */
- { "South Africa", NULL, NULL, "Africa/Johannesburg" },
-
- /* (GMT+02:00) Helsinki, Riga, Tallinn */
- { "FLE", "lv", "LV", "Europe/Riga" },
- { "FLE", "et", "EE", "Europe/Tallinn" },
- { "FLE", "fi", "FI", "Europe/Helsinki" },
-
- /* (GMT+02:00) Jerusalem */
- { "Israel", NULL, NULL, "Asia/Jerusalem" },
-
- /* (GMT+03:00) Baghdad */
- { "Arabic", NULL, NULL, "Asia/Baghdad" },
-
- /* (GMT+03:00) Kuwait, Riyadh */
- { "Arab", NULL, "KW", "Asia/Kuwait" },
- { "Arab", NULL, "SA", "Asia/Riyadh" },
-
- /* (GMT+03:00) Moscow, St. Petersburg, Volgograd */
- { "Russian", NULL, NULL, "Europe/Moscow" },
-
- /* (GMT+03:00) Nairobi */
- { "E. Africa", NULL, NULL, "Africa/Nairobi" },
-
- /* (GMT+03:30) Tehran */
- { "Iran", NULL, NULL, "Asia/Tehran" },
-
- /* (GMT+04:00) Abu Dhabi, Muscat */
- { "Arabian", NULL, NULL, "Asia/Muscat" },
-
- /* (GMT+04:00) Baku, Tbilisi, Yerevan */
- { "Caucasus", NULL, NULL, "Asia/Baku" },
-
- /* (GMT+04:30) Kabul */
- { "Afghanistan", NULL, NULL, "Asia/Kabul" },
-
- /* (GMT+05:00) Ekaterinburg */
- { "Ekaterinburg", NULL, NULL, "Asia/Yekaterinburg" },
-
- /* (GMT+05:00) Islamabad, Karachi, Tashkent */
- { "West Asia", NULL, NULL, "Asia/Karachi" },
-
- /* (GMT+05:30) Kolkata, Chennai, Mumbai, New Delhi */
- { "India", NULL, NULL, "Asia/Calcutta" },
-
- /* (GMT+05:45) Kathmandu */
- { "Nepal", NULL, NULL, "Asia/Katmandu" },
-
- /* (GMT+06:00) Almaty, Novosibirsk */
- { "N. Central Asia", NULL, NULL, "Asia/Almaty" },
-
- /* (GMT+06:00) Astana, Dhaka */
- { "Central Asia", NULL, NULL, "Asia/Dhaka" },
-
- /* (GMT+06:00) Sri Jayawardenepura */
- { "Sri Lanka", NULL, NULL, "Asia/Colombo" },
-
- /* (GMT+06:30) Rangoon */
- { "Myanmar", NULL, NULL, "Asia/Rangoon" },
-
- /* (GMT+07:00) Bangkok, Hanoi, Jakarta */
- { "SE Asia", "th", "TH", "Asia/Bangkok" },
- { "SE Asia", "vi", "VN", "Asia/Saigon" },
- { "SE Asia", "id", "ID", "Asia/Jakarta" },
-
- /* (GMT+07:00) Krasnoyarsk */
- { "North Asia", NULL, NULL, "Asia/Krasnoyarsk" },
-
- /* (GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi */
- { "China", NULL, "HK", "Asia/Hong_Kong" },
- { "China", NULL, NULL, "Asia/Shanghai" },
-
- /* (GMT+08:00) Irkutsk, Ulaan Bataar */
- { "North Asia East", NULL, NULL, "Asia/Irkutsk" },
-
- /* (GMT+08:00) Perth */
- { "W. Australia", NULL, NULL, "Australia/Perth" },
-
- /* (GMT+08:00) Kuala Lumpur, Singapore */
- { "Singapore", NULL, NULL, "Asia/Kuala_Lumpur" },
-
- /* (GMT+08:00) Taipei */
- { "Taipei", NULL, NULL, "Asia/Taipei" },
-
- /* (GMT+09:00) Osaka, Sapporo, Tokyo */
- { "Tokyo", NULL, NULL, "Asia/Tokyo" },
-
- /* (GMT+09:00) Seoul */
- { "Korea", NULL, "KP", "Asia/Pyongyang" },
- { "Korea", NULL, "KR", "Asia/Seoul" },
-
- /* (GMT+09:00) Yakutsk */
- { "Yakutsk", NULL, NULL, "Asia/Yakutsk" },
-
- /* (GMT+09:30) Adelaide */
- { "Cen. Australia", NULL, NULL, "Australia/Adelaide" },
-
- /* (GMT+09:30) Darwin */
- { "AUS Central", NULL, NULL, "Australia/Darwin" },
-
- /* (GMT+10:00) Brisbane */
- { "E. Australia", NULL, NULL, "Australia/Brisbane" },
-
- /* (GMT+10:00) Canberra, Melbourne, Sydney */
- { "AUS Eastern", NULL, NULL, "Australia/Sydney" },
-
- /* (GMT+10:00) Guam, Port Moresby */
- { "West Pacific", NULL, NULL, "Pacific/Guam" },
-
- /* (GMT+10:00) Hobart */
- { "Tasmania", NULL, NULL, "Australia/Hobart" },
-
- /* (GMT+10:00) Vladivostok */
- { "Vladivostok", NULL, NULL, "Asia/Vladivostok" },
-
- /* (GMT+11:00) Magadan, Solomon Is., New Caledonia */
- { "Central Pacific", NULL, NULL, "Pacific/Midway" },
-
- /* (GMT+12:00) Auckland, Wellington */
- { "New Zealand", NULL, NULL, "Pacific/Auckland" },
-
- /* (GMT+12:00) Fiji, Kamchatka, Marshall Is. */
- { "Fiji", "ru", "RU", "Asia/Kamchatka" },
- { "Fiji", NULL, NULL, "Pacific/Fiji" },
-
- /* (GMT+13:00) Nuku'alofa */
- { "Tonga", NULL, NULL, "Pacific/Tongatapu" }
-};
-static const gint n_zone_mappings = sizeof (zonemap) / sizeof (zonemap[0]);
-
-static gchar *
-find_olson_timezone (const gchar *windows_timezone)
-{
- gint i, tzlen;
- const gchar *locale, *p;
- gchar lang[3] = { 0 }, country[3] = { 0 };
-
- /* Strip " Standard Time" / " Daylight Time" from name */
- p = windows_timezone + strlen (windows_timezone) - 1;
- while (p > windows_timezone && *p-- != ' ')
- ;
- while (p > windows_timezone && *p-- != ' ')
- ;
- tzlen = p - windows_timezone + 1;
-
- /* Find the first entry in zonemap with a matching name */
- for (i = 0; i < n_zone_mappings; i++) {
- if (!g_ascii_strncasecmp (windows_timezone,
- zonemap[i].windows_name,
- tzlen))
- break;
- }
- if (i == n_zone_mappings)
- return NULL; /* Shouldn't happen... */
-
- /* If there's only one choice, go with it */
- if (!zonemap[i].lang && !zonemap[i].country)
- return g_strdup (zonemap[i].olson_name);
-
- /* Find our language/country (hopefully). */
-#ifndef G_OS_WIN32
- locale = getenv ("LANG");
-#else
- locale = g_win32_getlocale ();
-#endif
- if (locale) {
- strncpy (lang, locale, 2);
- locale = strchr (locale, '_');
- if (locale++)
- strncpy (country, locale, 2);
- }
-#ifdef G_OS_WIN32
- g_free ((gchar *) locale);
-#endif
-
- /* Look for an entry where either the country or the
- * language matches.
- */
- do {
- if ((zonemap[i].lang && !strcmp (zonemap[i].lang, lang)) ||
- (zonemap[i].country && !strcmp (zonemap[i].country, country)))
- return g_strdup (zonemap[i].olson_name);
- } while (++i < n_zone_mappings &&
- !g_ascii_strncasecmp (windows_timezone,
- zonemap[i].windows_name,
- tzlen));
-
- /* None of the hints matched, so (semi-arbitrarily) return the
- * last of the entries with the right Windows timezone name.
- */
- return g_strdup (zonemap[i - 1].olson_name);
-}
-
-/* Config file handling */
-
-static GHashTable *config_options;
-
-static void
-read_config (void)
-{
- struct stat st;
- gchar *p, *name, *value;
- gchar *config_data;
- gint fd = -1;
-
- config_options = g_hash_table_new (e2k_ascii_strcase_hash,
- e2k_ascii_strcase_equal);
-
-#ifndef G_OS_WIN32
- fd = g_open ("/etc/ximian/connector.conf", O_RDONLY, 0);
-#endif
- if (fd == -1) {
- gchar *filename = g_build_filename (CONNECTOR_PREFIX,
- "etc/connector.conf",
- NULL);
-
- fd = g_open (filename, O_RDONLY, 0);
- g_free (filename);
- }
- if (fd == -1)
- return;
- if (fstat (fd, &st) == -1) {
- g_warning ("Could not stat connector.conf: %s",
- g_strerror (errno));
- close (fd);
- return;
- }
-
- config_data = g_malloc (st.st_size + 1);
- if (read (fd, config_data, st.st_size) != st.st_size) {
- g_warning ("Could not read connector.conf: %s",
- g_strerror (errno));
- close (fd);
- g_free (config_data);
- return;
- }
- close (fd);
- config_data[st.st_size] = '\0';
-
- /* Read config data */
- p = config_data;
-
- while (1) {
- for (name = p; isspace ((guchar)*name); name++)
- ;
-
- p = strchr (name, ':');
- if (!p || !p[1])
- break;
- *p = '\0';
- value = p + 2;
- p = strchr (value, '\n');
- if (!p)
- break;
- if (*(p - 1) == '\r')
- *(p - 1) = '\0';
- *p = '\0';
- p++;
-
- if (g_ascii_strcasecmp (value, "false") &&
- g_ascii_strcasecmp (value, "no"))
- g_hash_table_insert (config_options, name, value);
- };
-
- g_free (config_data);
-}
-
-/**
- * e2k_autoconfig_lookup_option:
- * @option: option name to look up
- *
- * Looks up an autoconfiguration hint in the config file (if present)
- *
- * Return value: the string value of the option, or %NULL if it is unset.
- **/
-const gchar *
-e2k_autoconfig_lookup_option (const gchar *option)
-{
- if (!config_options)
- read_config ();
- return g_hash_table_lookup (config_options, option);
-}
-
-static gboolean
-validate (const gchar *owa_url, gchar *user, gchar *password, ExchangeParams *exchange_params, E2kAutoconfigResult *result)
-{
- E2kAutoconfig *ac;
- E2kOperation op; /* FIXME */
- E2kUri *euri;
- gboolean valid = FALSE;
- const gchar *old, *new;
- gchar *path, *mailbox;
-
- ac = e2k_autoconfig_new (owa_url, user, password,
- E2K_AUTOCONFIG_USE_EITHER);
-
- e2k_operation_init (&op);
- /* e2k_autoconfig_set_gc_server (ac, ad_server, gal_limit) FIXME */
- /* e2k_autoconfig_set_gc_server (ac, NULL, -1); */
- *result = e2k_autoconfig_check_exchange (ac, &op);
-
- if (*result == E2K_AUTOCONFIG_OK) {
- /*
- * On error code 403 and SSL seen in server response
- * e2k_autoconfig_get_context() tries to
- * connect using https if owa url has http and vice versa.
- * And also re-sets the owa_uri in E2kAutoconfig.
- * So even if the uri is incorrect,
- * e2k_autoconfig_check_exchange() will return success.
- * In this case of account set up, owa_url paramter will still
- * have wrong url entered, and we throw the error, instead of
- * going ahead with account setup and failing later.
- */
- if (g_str_has_prefix (ac->owa_uri, "http:")) {
- if (!g_str_has_prefix (owa_url, "http:"))
- *result = E2K_AUTOCONFIG_CANT_CONNECT;
- }
- else if (!g_str_has_prefix (owa_url, "https:"))
- *result = E2K_AUTOCONFIG_CANT_CONNECT;
- }
-
- if (*result == E2K_AUTOCONFIG_OK) {
- gint len;
-
- *result = e2k_autoconfig_check_global_catalog (ac, &op);
- e2k_operation_free (&op);
-
- /* find mailbox and owa_path values */
- euri = e2k_uri_new (ac->home_uri);
- path = g_strdup (euri->path + 1);
- e2k_uri_free (euri);
-
- /* no slash at the end of path */
- len = strlen (path);
- while (len && path [len - 1] == '/') {
- path [len - 1] = '\0';
- len--;
- }
-
- /* change a mailbox only if not set by the caller */
- if (!exchange_params->mailbox || !*exchange_params->mailbox) {
- mailbox = strrchr (path, '/');
- if (mailbox && !mailbox[1]) {
- *mailbox = '\0';
- mailbox = strrchr (path, '/');
- }
- if (mailbox)
- *mailbox++ = '\0';
-
- g_free (exchange_params->mailbox);
- exchange_params->mailbox = g_strdup (mailbox);
- } else {
- /* always strip the mailbox part from the path */
- gchar *slash = strrchr (path, '/');
-
- if (slash)
- *slash = '\0';
- }
-
- exchange_params->owa_path = g_strdup_printf ("%s%s", "/", path);
- g_free (path);
- exchange_params->host = g_strdup (ac->pf_server);
- if (ac->gc_server)
- exchange_params->ad_server = g_strdup (ac->gc_server);
- exchange_params->is_ntlm = ac->saw_ntlm;
-
- valid = TRUE;
- }
- else {
- switch (*result) {
-
- case E2K_AUTOCONFIG_CANT_CONNECT:
- if (!strncmp (ac->owa_uri, "http:", 5)) {
- old = "http";
- new = "https";
- } else {
- old = "https";
- new = "http";
- }
-
- /* SURF : e_notice (NULL, GTK_MESSAGE_ERROR,
- _("Could not connect to the Exchange "
- "server.\nMake sure the URL is correct "
- "(try \"%s\" instead of \"%s\"?) "
- "and try again."), new, old);
- */
- valid = FALSE;
- break;
-
- case E2K_AUTOCONFIG_CANT_RESOLVE:
- /* SURF : e_notice (NULL, GTK_MESSAGE_ERROR,
- _("Could not locate Exchange server.\n"
- "Make sure the server name is spelled correctly "
- "and try again."));
- */
- valid = FALSE;
- break;
-
- case E2K_AUTOCONFIG_AUTH_ERROR:
- case E2K_AUTOCONFIG_AUTH_ERROR_TRY_NTLM:
- case E2K_AUTOCONFIG_AUTH_ERROR_TRY_BASIC:
- /* SURF : e_notice (NULL, GTK_MESSAGE_ERROR,
- _("Could not authenticate to the Exchange "
- "server.\nMake sure the username and "
- "password are correct and try again."));
- */
- valid = FALSE;
- break;
-
- case E2K_AUTOCONFIG_AUTH_ERROR_TRY_DOMAIN:
- /* SURF : e_notice (NULL, GTK_MESSAGE_ERROR,
- _("Could not authenticate to the Exchange "
- "server.\nMake sure the username and "
- "password are correct and try again.\n\n"
- "You may need to specify the Windows "
- "domain name as part of your username "
- "(eg, \"MY-DOMAIN\\%s\")."),
- ac->username);
- */
- valid = FALSE;
- break;
-
- case E2K_AUTOCONFIG_NO_OWA:
- case E2K_AUTOCONFIG_NOT_EXCHANGE:
- /* SURF : e_notice (NULL, GTK_MESSAGE_ERROR,
- _("Could not find OWA data at the indicated URL.\n"
- "Make sure the URL is correct and try again."));
- */
- valid = FALSE;
- break;
-
- case E2K_AUTOCONFIG_CANT_BPROPFIND:
- /* SURF : e_notice (
- NULL, GTK_MESSAGE_ERROR,
- _("Ximian 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 Ximian Connector.\n\n"
- "For information to provide to your Exchange "
- "administrator, please follow the link below:\n"
- "http://support.novell.com/cgi-bin/search/searchtid.cgi?/ximian/ximian328.html "));
- */
- valid = FALSE;
- break;
-
- case E2K_AUTOCONFIG_EXCHANGE_5_5:
- /* SURF : e_notice (
- NULL, GTK_MESSAGE_ERROR,
- _("The Exchange server URL you provided is for an "
- "Exchange 5.5 Server. Ximian Connector supports "
- "Microsoft Exchange 2000 and 2003 only."));
- */
- valid = FALSE;
- break;
-
- default:
- /* SURF : e_notice (NULL, GTK_MESSAGE_ERROR,
- _("Could not configure Exchange account because "
- "an unknown error occurred. Check the URL, "
- "username, and password, and try again."));
- */
- valid = FALSE; /* FIXME return valid */
- break;
- }
- }
-
- e2k_autoconfig_free (ac);
- return valid;
-}
-
-gboolean
-e2k_validate_user (const gchar *owa_url, gchar *pkey, gchar **user,
- ExchangeParams *exchange_params, gboolean *remember_password,
- E2kAutoconfigResult *result, GtkWindow *parent)
-{
- gboolean valid = FALSE, remember=FALSE;
- gchar *key, *password, *prompt;
- gchar *username;
- gchar **usernames;
- gint try = 0;
- EUri *uri;
-
- uri = e_uri_new (owa_url);
- key = g_strdup_printf ("%s%s/", pkey, uri->host); /* FIXME */
- e_uri_free (uri);
-
-try_auth_again:
- username = g_strdup (*user);
-
- password = e_passwords_get_password ("Exchange", key);
- if (password) {
- /* This can be the case, where user presses authenticate button and
- * later cancels the account setup or removal of account fails for
- * some reason. We need to prompt for the password always when
- * authenticate button is pressed */
- e_passwords_forget_password ("Exchange", key);
- }
-
- prompt = g_strdup_printf (_("Enter password for %s"), username);
- password = e_passwords_ask_password (_("Enter password"),
- "Exchange", key, prompt,
- E_PASSWORDS_REMEMBER_FOREVER|E_PASSWORDS_SECRET,
- &remember, parent);
- g_free (prompt);
- if (!password) {
- g_free (key);
- g_free (username);
- *result = E2K_AUTOCONFIG_CANCELLED;
- return valid;
- }
-
- valid = validate (owa_url, username, password, exchange_params, result);
- if (valid) {
- /* generate the proper key once the host name
- * is read and remember password temporarily,
- * so that at the end of * account creation,
- * user will not be prompted, for password will
- * not be asked again.
- */
- *remember_password = remember;
- g_free (key);
- if (exchange_params->is_ntlm)
- key = g_strdup_printf ("exchange://%s;auth=NTLM@%s/",
- username, exchange_params->host);
- else
- key = g_strdup_printf ("exchange://%s@%s/", username, exchange_params->host);
- e_passwords_add_password (key, password);
- e_passwords_remember_password ("Exchange", key);
- }
- else {
- if (try == 0) {
- /* Check for name as e-mail id and try once again
- * extracing username from e-mail id.
- */
- usernames = g_strsplit (*user, "@", 2);
- if (usernames && usernames[0] && usernames[1]) {
- username = g_strdup (usernames[0]);
- g_strfreev (usernames);
- try ++;
- memset(*user, 0, strlen(*user));
- g_free (*user);
- *user = g_strdup (username);
- g_free (username);
- goto try_auth_again;
- }
- }
- /* if validation failed*/
- e_passwords_forget_password ("Exchange", key);
- }
-
- g_free (key);
- g_free (password);
- g_free (username);
- return valid;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2003, 2004 Novell, Inc. */
-
-#ifndef __E2K_AUTOCONFIG_H__
-#define __E2K_AUTOCONFIG_H__
-
-#include "e2k-types.h"
-#include "e2k-operation.h"
-#include "e2k-validate.h"
-
-G_BEGIN_DECLS
-
-typedef enum {
- E2K_EXCHANGE_UNKNOWN,
- E2K_EXCHANGE_2000,
- E2K_EXCHANGE_2003,
-
- E2K_EXCHANGE_FUTURE
-} E2kExchangeVersion;
-
-typedef enum {
- E2K_AUTOCONFIG_USE_BASIC,
- E2K_AUTOCONFIG_USE_NTLM,
- E2K_AUTOCONFIG_USE_EITHER
-} E2kAutoconfigAuthPref;
-
-typedef struct {
- /* Input data. (gc_server is optional) */
- gchar *owa_uri, *gc_server;
- gchar *username, *password;
- gint gal_limit;
- E2kAutoconfigGalAuthPref gal_auth;
-
- /* Output data */
- E2kExchangeVersion version;
- gchar *display_name, *email;
- gchar *account_uri, *exchange_server;
- gchar *timezone;
-
- /* Private-ish members */
- gchar *nt_domain, *w2k_domain;
- gchar *home_uri, *exchange_dn;
- gchar *pf_server;
- E2kAutoconfigAuthPref auth_pref;
- gboolean require_ntlm, use_ntlm;
- gboolean saw_basic, saw_ntlm;
- gboolean nt_domain_defaulted, gc_server_autodetected;
-} E2kAutoconfig;
-
-E2kAutoconfig *e2k_autoconfig_new (const gchar *owa_uri,
- const gchar *username,
- const gchar *password,
- E2kAutoconfigAuthPref auth_pref);
-void e2k_autoconfig_free (E2kAutoconfig *ac);
-
-void e2k_autoconfig_set_owa_uri (E2kAutoconfig *ac,
- const gchar *owa_uri);
-void e2k_autoconfig_set_gc_server (E2kAutoconfig *ac,
- const gchar *gc_server,
- gint gal_limit,
- E2kAutoconfigGalAuthPref gal_auth);
-void e2k_autoconfig_set_username (E2kAutoconfig *ac,
- const gchar *username);
-void e2k_autoconfig_set_password (E2kAutoconfig *ac,
- const gchar *password);
-
-E2kContext *e2k_autoconfig_get_context (E2kAutoconfig *ac,
- E2kOperation *op,
- E2kAutoconfigResult *result);
-E2kAutoconfigResult e2k_autoconfig_check_exchange (E2kAutoconfig *ac,
- E2kOperation *op);
-E2kGlobalCatalog *e2k_autoconfig_get_global_catalog (E2kAutoconfig *ac,
- E2kOperation *op);
-E2kAutoconfigResult e2k_autoconfig_check_global_catalog (E2kAutoconfig *ac,
- E2kOperation *op);
-
-const gchar *e2k_autoconfig_lookup_option (const gchar *option);
-
-G_END_DECLS
-
-#endif /* __EXCHANGE_AUTOCONFIG_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2001-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <glib.h>
-
-#ifndef G_OS_WIN32
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#else
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <windns.h>
-#endif
-
-#include "e2k-context.h"
-#include "e2k-marshal.h"
-#include "e2k-propnames.h"
-#include "e2k-restriction.h"
-#include "e2k-uri.h"
-#include "e2k-utils.h"
-#include "e2k-xml-utils.h"
-
-#include <libedataserver/e-proxy.h>
-#include <libsoup/soup.h>
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/xmlmemory.h>
-
-#ifdef G_OS_WIN32
-/* The strtok() in Microsoft's C library is MT-safe (not stateless,
- * but that is not needed here).
- */
-#define strtok_r(s,sep,lasts ) (*(lasts) = strtok((s),(sep)))
-#endif
-
-#ifdef G_OS_WIN32
-#define CLOSE_SOCKET(socket) closesocket (socket)
-#define STATUS_IS_SOCKET_ERROR(status) ((status) == SOCKET_ERROR)
-#define SOCKET_IS_INVALID(socket) ((socket) == INVALID_SOCKET)
-#define BIND_STATUS_IS_ADDRINUSE() (WSAGetLastError () == WSAEADDRINUSE)
-#else
-#define CLOSE_SOCKET(socket) close (socket)
-#define STATUS_IS_SOCKET_ERROR(status) ((status) == -1)
-#define SOCKET_IS_INVALID(socket) ((socket) < 0)
-#define BIND_STATUS_IS_ADDRINUSE() (errno == EADDRINUSE)
-#endif
-
-#define PARENT_TYPE G_TYPE_OBJECT
-static GObjectClass *parent_class;
-
-enum {
- REDIRECT,
- LAST_SIGNAL
-};
-
-static guint signals [LAST_SIGNAL] = { 0 };
-
-struct _E2kContextPrivate {
- SoupSession *session, *async_session;
- gchar *owa_uri, *username, *password;
- time_t last_timestamp;
-
- /* Notification listener */
- SoupSocket *get_local_address_sock;
- GIOChannel *listener_channel;
- gint listener_watch_id;
-
- gchar *notification_uri;
- GHashTable *subscriptions_by_id, *subscriptions_by_uri;
-
- /* Forms-based authentication */
- gchar *cookie;
- gboolean cookie_verified;
- EProxy* proxy;
-};
-
-/* For operations with progress */
-#define E2K_CONTEXT_MIN_BATCH_SIZE 25
-#define E2K_CONTEXT_MAX_BATCH_SIZE 100
-
-/* For soup sync session timeout */
-#define E2K_SOUP_SESSION_TIMEOUT 30
-
-/* Soup session proxy-uri property */
-#define SOUP_SESSION_PROXY_URI "proxy-uri"
-
-#ifdef E2K_DEBUG
-gchar *e2k_debug;
-gint e2k_debug_level;
-
-static SoupLoggerLogLevel e2k_debug_request_filter (SoupLogger *logger,
- SoupMessage *msg,
- gpointer user_data);
-static SoupLoggerLogLevel e2k_debug_response_filter (SoupLogger *logger,
- SoupMessage *msg,
- gpointer user_data);
-#endif
-
-static gboolean renew_subscription (gpointer user_data);
-static void unsubscribe_internal (E2kContext *ctx, const gchar *uri, GList *sub_list, gboolean destrying);
-static gboolean do_notification (GIOChannel *source, GIOCondition condition, gpointer data);
-
-static void setup_message (SoupSession *session, SoupMessage *msg, SoupSocket *socket, gpointer user_data);
-static void proxy_settings_changed (EProxy *proxy, gpointer user_data);
-
-static void
-proxy_settings_changed (EProxy *proxy, gpointer user_data)
-{
- SoupURI *proxy_uri = NULL;
- E2kContext* ctx = (E2kContext *)user_data;
- if (!ctx || !ctx->priv ||
- (!ctx->priv->session && !ctx->priv->async_session) ||
- (!ctx->priv->owa_uri))
- return;
-
- if (!e_proxy_require_proxy_for_uri (proxy, ctx->priv->owa_uri))
- proxy_uri = NULL;
- else
- proxy_uri = e_proxy_peek_uri_for (proxy, ctx->priv->owa_uri);
-
- if (ctx->priv->session)
- g_object_set (ctx->priv->session, SOUP_SESSION_PROXY_URI,
- proxy_uri, NULL);
- if (ctx->priv->async_session)
- g_object_set (ctx->priv->async_session, SOUP_SESSION_PROXY_URI,
- proxy_uri, NULL);
-}
-
-static void
-init (GObject *object)
-{
- E2kContext *ctx = E2K_CONTEXT (object);
-
- ctx->priv = g_new0 (E2kContextPrivate, 1);
- ctx->priv->subscriptions_by_id =
- g_hash_table_new (g_str_hash, g_str_equal);
- ctx->priv->subscriptions_by_uri =
- g_hash_table_new (g_str_hash, g_str_equal);
- ctx->priv->proxy = e_proxy_new ();
- e_proxy_setup_proxy (ctx->priv->proxy);
- g_signal_connect (ctx->priv->proxy, "changed", G_CALLBACK (proxy_settings_changed), ctx);
-}
-
-static void
-destroy_sub_list (gpointer uri, gpointer sub_list, gpointer ctx)
-{
- unsubscribe_internal (ctx, uri, sub_list, TRUE);
- g_list_free (sub_list);
-}
-
-static void
-dispose (GObject *object)
-{
- E2kContext *ctx = E2K_CONTEXT (object);
-
- if (ctx->priv) {
- if (ctx->priv->owa_uri)
- g_free (ctx->priv->owa_uri);
- if (ctx->priv->username)
- g_free (ctx->priv->username);
- if (ctx->priv->password)
- g_free (ctx->priv->password);
-
- if (ctx->priv->get_local_address_sock)
- g_object_unref (ctx->priv->get_local_address_sock);
-
- g_hash_table_foreach (ctx->priv->subscriptions_by_uri,
- destroy_sub_list, ctx);
- g_hash_table_destroy (ctx->priv->subscriptions_by_uri);
-
- g_hash_table_destroy (ctx->priv->subscriptions_by_id);
-
- if (ctx->priv->listener_watch_id)
- g_source_remove (ctx->priv->listener_watch_id);
- if (ctx->priv->listener_channel) {
- g_io_channel_shutdown (ctx->priv->listener_channel,
- FALSE, NULL);
- g_io_channel_unref (ctx->priv->listener_channel);
- }
-
- if (ctx->priv->session)
- g_object_unref (ctx->priv->session);
- if (ctx->priv->async_session)
- g_object_unref (ctx->priv->async_session);
-
- g_free (ctx->priv->cookie);
- g_free (ctx->priv->notification_uri);
-
- if (ctx->priv->proxy) {
- g_object_unref (ctx->priv->proxy);
- ctx->priv->proxy = NULL;
- }
- g_free (ctx->priv);
- ctx->priv = NULL;
-
- }
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-class_init (GObjectClass *object_class)
-{
- parent_class = g_type_class_ref (PARENT_TYPE);
-
- /* virtual method override */
- object_class->dispose = dispose;
-
- signals[REDIRECT] =
- g_signal_new ("redirect",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (E2kContextClass, redirect),
- NULL, NULL,
- e2k_marshal_NONE__INT_STRING_STRING,
- G_TYPE_NONE, 3,
- G_TYPE_INT,
- G_TYPE_STRING,
- G_TYPE_STRING);
-
-#ifdef E2K_DEBUG
- e2k_debug = getenv ("E2K_DEBUG");
- if (e2k_debug)
- e2k_debug_level = atoi (e2k_debug);
-#endif
-}
-
-E2K_MAKE_TYPE (e2k_context, E2kContext, class_init, init, PARENT_TYPE)
-
-static void
-renew_sub_list (gpointer key, gpointer value, gpointer data)
-{
- GList *sub_list;
-
- for (sub_list = value; sub_list; sub_list = sub_list->next)
- renew_subscription (sub_list->data);
-}
-
-static void
-got_connection (SoupSocket *sock, guint status, gpointer user_data)
-{
- E2kContext *ctx = user_data;
- SoupAddress *addr;
- struct sockaddr_in sin;
- const gchar *local_ipaddr;
- unsigned short port;
- gint s, ret;
-
- ctx->priv->get_local_address_sock = NULL;
-
- if (status != SOUP_STATUS_OK)
- goto done;
-
- addr = soup_socket_get_local_address (sock);
- local_ipaddr = soup_address_get_physical (addr);
-
- s = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (SOCKET_IS_INVALID (s))
- goto done;
-
- memset (&sin, 0, sizeof (sin));
- sin.sin_family = AF_INET;
-
- port = (short)getpid ();
- do {
- port++;
- if (port < 1024)
- port += 1024;
- sin.sin_port = htons (port);
- ret = bind (s, (struct sockaddr *)&sin, sizeof (sin));
- } while (STATUS_IS_SOCKET_ERROR (ret) && BIND_STATUS_IS_ADDRINUSE ());
-
- if (ret == -1) {
- CLOSE_SOCKET (s);
- goto done;
- }
-
-#ifndef G_OS_WIN32
- ctx->priv->listener_channel = g_io_channel_unix_new (s);
-#else
- ctx->priv->listener_channel = g_io_channel_win32_new_socket (s);
-#endif
- g_io_channel_set_encoding (ctx->priv->listener_channel, NULL, NULL);
- g_io_channel_set_buffered (ctx->priv->listener_channel, FALSE);
-
- ctx->priv->listener_watch_id =
- g_io_add_watch (ctx->priv->listener_channel,
- G_IO_IN, do_notification, ctx);
-
- ctx->priv->notification_uri = g_strdup_printf ("httpu://%s:%u/",
- local_ipaddr,
- port);
-
- g_hash_table_foreach (ctx->priv->subscriptions_by_uri,
- renew_sub_list, ctx);
-
- done:
- if (sock)
- g_object_unref (sock);
- g_object_unref (ctx);
-}
-
-/**
- * e2k_context_new:
- * @uri: OWA uri to connect to
- *
- * Creates a new #E2kContext based at @uri
- *
- * Return value: the new context
- **/
-E2kContext *
-e2k_context_new (const gchar *uri)
-{
- E2kContext *ctx;
- SoupURI *suri;
- SoupAddress *addr;
-
- suri = soup_uri_new (uri);
- if (!suri)
- return NULL;
-
- if (!suri->host) {
- soup_uri_free (suri);
- return NULL;
- }
-
- addr = soup_address_new (suri->host, suri->port);
- soup_uri_free (suri);
-
- ctx = g_object_new (E2K_TYPE_CONTEXT, NULL);
- ctx->priv->owa_uri = g_strdup (uri);
-
- ctx->priv->get_local_address_sock =
- soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, addr,
- NULL);
- soup_socket_connect_async (ctx->priv->get_local_address_sock, NULL,
- got_connection, g_object_ref (ctx));
- g_object_unref (addr);
-
- return ctx;
-}
-
-static void
-session_authenticate (SoupSession *session, SoupMessage *msg,
- SoupAuth *auth, gboolean retrying, gpointer user_data)
-{
- E2kContext *ctx = user_data;
-
- if (!retrying) {
- soup_auth_authenticate (auth, ctx->priv->username,
- ctx->priv->password);
- }
-}
-
-/**
- * e2k_context_set_auth:
- * @ctx: the context
- * @username: the Windows username (not including domain) of the user
- * @domain: the NT domain, or %NULL to use the default (if using NTLM)
- * @authmech: the HTTP Authorization type to use; either "Basic" or "NTLM"
- * @password: the user's password
- *
- * Sets the authentication information on @ctx. This will have the
- * side effect of cancelling any pending requests on @ctx.
- **/
-void
-e2k_context_set_auth (E2kContext *ctx, const gchar *username,
- const gchar *domain, const gchar *authmech,
- const gchar *password)
-{
- guint timeout = E2K_SOUP_SESSION_TIMEOUT;
- SoupURI* uri = NULL;
-#ifdef E2K_DEBUG
- SoupLogger *logger;
- SoupLoggerLogLevel level;
-#endif
-
- g_return_if_fail (E2K_IS_CONTEXT (ctx));
-
- if (username) {
- g_free (ctx->priv->username);
- if (domain) {
- ctx->priv->username =
- g_strdup_printf ("%s\\%s", domain,
- username);
- } else
- ctx->priv->username = g_strdup (username);
- }
-
- if (password) {
- g_free (ctx->priv->password);
- ctx->priv->password = g_strdup (password);
- }
-
- /* Destroy the old sessions so we don't reuse old auths */
- if (ctx->priv->session)
- g_object_unref (ctx->priv->session);
- if (ctx->priv->async_session)
- g_object_unref (ctx->priv->async_session);
-
- /* Set a default timeout value of 30 seconds.
- FIXME: Make timeout configurable
- */
- if (g_getenv ("SOUP_SESSION_TIMEOUT"))
- timeout = atoi (g_getenv ("SOUP_SESSION_TIMEOUT"));
-
- /* Check do we need a proxy to contact the server? */
- if (e_proxy_require_proxy_for_uri (ctx->priv->proxy, ctx->priv->owa_uri))
- uri = e_proxy_peek_uri_for (ctx->priv->proxy, ctx->priv->owa_uri);
-
- ctx->priv->session = soup_session_sync_new_with_options (
- SOUP_SESSION_USE_NTLM, !authmech || !strcmp (authmech, "NTLM"),
- SOUP_SESSION_TIMEOUT, timeout,
- SOUP_SESSION_PROXY_URI, uri,
- NULL);
- g_signal_connect (ctx->priv->session, "authenticate",
- G_CALLBACK (session_authenticate), ctx);
- g_signal_connect (ctx->priv->session, "request_started",
- G_CALLBACK (setup_message), ctx);
-
- ctx->priv->async_session = soup_session_async_new_with_options (
- SOUP_SESSION_USE_NTLM, !authmech || !strcmp (authmech, "NTLM"),
- SOUP_SESSION_PROXY_URI, uri, NULL);
- g_signal_connect (ctx->priv->async_session, "authenticate",
- G_CALLBACK (session_authenticate), ctx);
- g_signal_connect (ctx->priv->async_session, "request_started",
- G_CALLBACK (setup_message), ctx);
-
-#ifdef E2K_DEBUG
- if (e2k_debug_level < 4)
- level = (SoupLoggerLogLevel)e2k_debug_level;
- else
- level = SOUP_LOGGER_LOG_BODY;
- logger = soup_logger_new (level, -1);
- if (level == SOUP_LOGGER_LOG_BODY && e2k_debug_level < 5) {
- soup_logger_set_request_filter (logger, e2k_debug_request_filter, NULL, NULL);
- soup_logger_set_response_filter (logger, e2k_debug_response_filter, NULL, NULL);
- }
- soup_session_add_feature (
- ctx->priv->session, SOUP_SESSION_FEATURE (logger));
- soup_session_add_feature (
- ctx->priv->async_session, SOUP_SESSION_FEATURE (logger));
-#endif
-}
-
-/**
- * e2k_context_get_last_timestamp:
- * @ctx: the context
- *
- * Returns a %time_t corresponding to the last "Date" header
- * received from the server.
- *
- * Return value: the timestamp
- **/
-time_t
-e2k_context_get_last_timestamp (E2kContext *ctx)
-{
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), -1);
-
- return ctx->priv->last_timestamp;
-}
-
-#ifdef E2K_DEBUG
-/* Debug levels:
- * 0 - None
- * 1 - Basic request and response (SOUP_LOGGER_LOG_MINIMAL)
- * 2 - 1 plus all headers (SOUP_LOGGER_LOG_HEADERS)
- * 3 - 2 plus most bodies (SOUP_LOGGER_LOG_BODY with filters)
- * 4 - 3 plus Global Catalog debug too
- * 5 - 4 plus all bodies (SOUP_LOGGER_LOG_BODY)
- */
-
-/* The filters are only used when e2k_debug_level is 3 or 4,
- * meaning we want to show most, but not all, bodies.
- */
-static SoupLoggerLogLevel
-e2k_debug_request_filter (SoupLogger *logger, SoupMessage *msg,
- gpointer user_data)
-{
- if (msg->method == SOUP_METHOD_POST)
- return SOUP_LOGGER_LOG_HEADERS;
- else
- return SOUP_LOGGER_LOG_BODY;
-}
-
-static SoupLoggerLogLevel
-e2k_debug_response_filter (SoupLogger *logger, SoupMessage *msg,
- gpointer user_data)
-{
- const gchar *content_type;
-
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (msg->status_code))
- return SOUP_LOGGER_LOG_HEADERS;
-
- content_type = soup_message_headers_get (msg->response_headers,
- "Content-Type");
- if (!content_type || g_ascii_strncasecmp (content_type, "text/html", 9))
- return SOUP_LOGGER_LOG_BODY;
- else
- return SOUP_LOGGER_LOG_HEADERS;
-}
-#endif
-
-#define E2K_FBA_FLAG_FORCE_DOWNLEVEL "1"
-#define E2K_FBA_FLAG_TRUSTED "4"
-
-/**
- * e2k_context_fba:
- * @ctx: the context
- * @failed_msg: a message that received a 440 status code
- *
- * Attempts to synchronously perform Exchange 2003 forms-based
- * authentication.
- *
- * Return value: %FALSE if authentication failed, %TRUE if it
- * succeeded, in which case @failed_msg can be requeued.
- **/
-gboolean
-e2k_context_fba (E2kContext *ctx, SoupMessage *failed_msg)
-{
- static gboolean in_fba_auth = FALSE;
- gint status, len;
- SoupBuffer *response = NULL;
- gchar *action;
- xmlChar *method, *name, *value;
- xmlDoc *doc = NULL;
- xmlNode *node;
- SoupMessage *post_msg;
- GHashTable *form_data;
- gchar *form_body;
- GString *cookie_str;
- GSList *cookies, *c;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), FALSE);
-
- if (in_fba_auth)
- return FALSE;
-
- if (ctx->priv->cookie) {
- g_free (ctx->priv->cookie);
- ctx->priv->cookie = NULL;
- if (!ctx->priv->cookie_verified) {
- /* New cookie failed on the first try. Must
- * be a bad password.
- */
- return FALSE;
- }
- /* Otherwise, it's just expired. */
- }
-
- if (!ctx->priv->username || !ctx->priv->password)
- return FALSE;
-
- in_fba_auth = TRUE;
-
- status = e2k_context_get_owa (ctx, NULL, ctx->priv->owa_uri,
- FALSE, &response);
- if (!SOUP_STATUS_IS_SUCCESSFUL (status) || response->length == 0) {
- if (response)
- soup_buffer_free (response);
- goto failed;
- }
-
- doc = e2k_parse_html (response->data, response->length);
- soup_buffer_free (response);
-
- node = e2k_xml_find (doc->children, "form");
- if (!node)
- goto failed;
-
- method = xmlGetProp (node, (xmlChar *) "method");
- if (!method || g_ascii_strcasecmp ((gchar *) method, "post") != 0) {
- if (method)
- xmlFree (method);
- goto failed;
- }
- xmlFree (method);
-
- value = xmlGetProp (node, (xmlChar *) "action");
- if (!value || !*value)
- goto failed;
- if (*value == '/') {
- SoupURI *suri;
-
- suri = soup_uri_new (ctx->priv->owa_uri);
- g_free (suri->path);
- suri->path = g_strdup ((gchar *) value);
- action = soup_uri_to_string (suri, FALSE);
- soup_uri_free (suri);
- } else if (xmlStrncmp (value, (xmlChar *) "http", 4) != 0) {
- SoupURI *suri;
- gchar *path_end;
- const gchar *location;
-
- location = soup_message_headers_get (failed_msg->response_headers,
- "Location");
- if (location != NULL) {/*Make sure we can get absolute path*/
- suri = soup_uri_new (location);
- if (suri != NULL) {/*Valid URI*/
- if (!suri->path || strchr (suri->path, '/') == NULL)
- goto failed;
-
- path_end = strrchr (suri->path, '/') + 1;
- *path_end = '\0';
- suri->path = g_realloc (suri->path,
- path_end - suri->path + xmlStrlen (value) + 1);
- strcat (suri->path, (gchar *) value);
- g_free (suri->query);
- suri->query = NULL;
- action = soup_uri_to_string (suri, FALSE);
- soup_uri_free (suri);
- }
- }
- } else
- action = g_strdup ((gchar *) value);
- xmlFree (value);
-
- form_data = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL, g_free);
- while ((node = e2k_xml_find (node, "input"))) {
- name = xmlGetProp (node, (xmlChar *) "name");
- if (!name)
- continue;
- value = xmlGetProp (node, (xmlChar *) "value");
-
- if (!g_ascii_strcasecmp ((gchar *) name, "destination") && value) {
- g_hash_table_insert (
- form_data,
- (gpointer) "destination",
- g_strdup ((gchar *) value));
- } else if (!g_ascii_strcasecmp ((gchar *) name, "flags")) {
- g_hash_table_insert (
- form_data,
- (gpointer) "flags",
- g_strdup (E2K_FBA_FLAG_TRUSTED));
- } else if (!g_ascii_strcasecmp ((gchar *) name, "username")) {
- g_hash_table_insert (
- form_data,
- (gpointer) "username",
- g_strdup (ctx->priv->username));
- } else if (!g_ascii_strcasecmp ((gchar *) name, "password")) {
- g_hash_table_insert (
- form_data,
- (gpointer) "password",
- g_strdup (ctx->priv->password));
- }
-
- if (value)
- xmlFree (value);
- xmlFree (name);
- }
- g_hash_table_insert (
- form_data, (gpointer) "trusted",
- g_strdup (E2K_FBA_FLAG_TRUSTED));
- xmlFreeDoc (doc);
- doc = NULL;
-
- form_body = soup_form_encode_hash (form_data);
- g_hash_table_destroy (form_data);
-
- post_msg = e2k_soup_message_new_full (
- ctx, action, "POST",
- "application/x-www-form-urlencoded",
- SOUP_MEMORY_TAKE,
- form_body, strlen (form_body));
- if (!post_msg)
- goto failed;
-
- soup_message_set_flags (post_msg, SOUP_MESSAGE_NO_REDIRECT);
- e2k_context_send_message (ctx, NULL /* FIXME? */, post_msg);
- g_free (action);
-
- if (!SOUP_STATUS_IS_SUCCESSFUL (post_msg->status_code) &&
- !SOUP_STATUS_IS_REDIRECTION (post_msg->status_code)) {
- g_object_unref (post_msg);
- goto failed;
- }
-
- /* Extract the cookies */
- cookies = e2k_http_get_headers (post_msg->response_headers, "Set-Cookie");
- cookie_str = g_string_new (NULL);
-
- for (c = cookies; c; c = c->next) {
- gchar *string = c->data;
- len = strcspn (string, ";");
-
- if (cookie_str->len)
- g_string_append (cookie_str, "; ");
- g_string_append_len (cookie_str, string, len);
- }
- ctx->priv->cookie = cookie_str->str;
- ctx->priv->cookie_verified = FALSE;
- g_string_free (cookie_str, FALSE);
- g_slist_free (cookies);
- g_object_unref (post_msg);
-
- in_fba_auth = FALSE;
-
- /* Set up the failed message to be requeued */
- soup_message_headers_remove (failed_msg->request_headers, "Cookie");
- soup_message_headers_append (failed_msg->request_headers,
- "Cookie", ctx->priv->cookie);
- return TRUE;
-
- failed:
- in_fba_auth = FALSE;
- if (doc)
- xmlFreeDoc (doc);
- return FALSE;
-}
-
-static void
-fba_timeout_handler (SoupMessage *msg, gpointer user_data)
-{
- E2kContext *ctx = user_data;
-
- if (e2k_context_fba (ctx, msg))
- soup_session_requeue_message (ctx->priv->session, msg);
- else
- soup_message_set_status (msg, SOUP_STATUS_UNAUTHORIZED);
-}
-
-static void
-timestamp_handler (SoupMessage *msg, gpointer user_data)
-{
- E2kContext *ctx = user_data;
- const gchar *date;
-
- date = soup_message_headers_get (msg->response_headers, "Date");
- if (date)
- ctx->priv->last_timestamp = e2k_http_parse_date (date);
-}
-
-static void
-redirect_handler (SoupMessage *msg, gpointer user_data)
-{
- E2kContext *ctx = user_data;
- const gchar *new_uri;
- SoupURI *soup_uri;
- gchar *old_uri;
-
- if (!SOUP_STATUS_IS_REDIRECTION (msg->status_code) ||
- (soup_message_get_flags (msg) & SOUP_MESSAGE_NO_REDIRECT))
- return;
-
- new_uri = soup_message_headers_get (msg->response_headers, "Location");
- soup_uri = soup_uri_copy (soup_message_get_uri (msg));
- old_uri = soup_uri_to_string (soup_uri, FALSE);
-
- g_signal_emit (ctx, signals[REDIRECT], 0,
- msg->status_code, old_uri, new_uri);
- soup_uri_free (soup_uri);
- g_free (old_uri);
-}
-
-static void
-setup_message (SoupSession *session, SoupMessage *msg,
- SoupSocket *socket, gpointer user_data)
-{
- E2kContext *ctx = user_data;
-
- if (ctx->priv->cookie) {
- soup_message_headers_replace (msg->request_headers,
- "Cookie", ctx->priv->cookie);
- }
-
- /* Only do this the first time through */
- if (!soup_message_headers_get (msg->request_headers, "User-Agent")) {
- g_signal_connect (msg, "got-headers",
- G_CALLBACK (timestamp_handler), ctx);
- soup_message_add_header_handler (msg, "got-headers",
- "Location",
- G_CALLBACK (redirect_handler),
- ctx);
- soup_message_add_status_code_handler (msg, "got-headers",
- E2K_HTTP_TIMEOUT,
- G_CALLBACK (fba_timeout_handler),
- ctx);
- soup_message_headers_append (msg->request_headers, "User-Agent",
- "Evolution/" VERSION);
-
- }
-}
-
-/**
- * e2k_soup_message_new:
- * @ctx: the context
- * @uri: the URI
- * @method: the HTTP method
- *
- * Creates a new %SoupMessage for @ctx.
- *
- * Return value: a new %SoupMessage, set up for connector use
- **/
-SoupMessage *
-e2k_soup_message_new (E2kContext *ctx, const gchar *uri, const gchar *method)
-{
- SoupMessage *msg;
-
- if (method[0] == 'B') {
- gchar *slash_uri = e2k_strdup_with_trailing_slash (uri);
- msg = soup_message_new (method, slash_uri);
- if (!msg)
- g_warning ("Invalid uri '%s'", slash_uri ? slash_uri : "[null]");
- g_free (slash_uri);
- } else {
- msg = soup_message_new (method, uri);
- if (!msg)
- g_warning ("Invalid uri '%s'", uri ? uri : "[null]");
- }
-
- return msg;
-}
-
-/**
- * e2k_soup_message_new_full:
- * @ctx: the context
- * @uri: the URI
- * @method: the HTTP method
- * @content_type: MIME Content-Type of @body
- * @use: use policy of @body
- * @body: request body
- * @length: length of @body
- *
- * Creates a new %SoupMessage with the given body.
- *
- * Return value: a new %SoupMessage with a request body, set up for
- * connector use
- **/
-SoupMessage *
-e2k_soup_message_new_full (E2kContext *ctx, const gchar *uri,
- const gchar *method, const gchar *content_type,
- SoupMemoryUse use, const gchar *body,
- gsize length)
-{
- SoupMessage *msg;
-
- msg = e2k_soup_message_new (ctx, uri, method);
- g_return_val_if_fail (msg != NULL, NULL);
- soup_message_set_request (msg, content_type, use, body, length);
-
- return msg;
-}
-
-/**
- * e2k_context_queue_message:
- * @ctx: the context
- * @msg: the message to queue
- * @callback: callback to invoke when @msg is done
- * @user_data: data for @callback
- *
- * Asynchronously queues @msg in @ctx's session.
- **/
-void
-e2k_context_queue_message (E2kContext *ctx, SoupMessage *msg,
- SoupSessionCallback callback,
- gpointer user_data)
-{
- g_return_if_fail (E2K_IS_CONTEXT (ctx));
-
- soup_session_queue_message (ctx->priv->async_session, msg,
- callback, user_data);
-}
-
-static void
-context_canceller (E2kOperation *op, gpointer owner, gpointer data)
-{
- E2kContext *ctx = owner;
- SoupMessage *msg = data;
-
- soup_session_cancel_message (ctx->priv->session, msg,
- SOUP_STATUS_CANCELLED);
-}
-
-/**
- * e2k_context_send_message:
- * @ctx: the context
- * @op: an #E2kOperation to use for cancellation
- * @msg: the message to send
- *
- * Synchronously sends @msg in @ctx's session.
- *
- * Return value: the HTTP status of the message
- **/
-E2kHTTPStatus
-e2k_context_send_message (E2kContext *ctx, E2kOperation *op, SoupMessage *msg)
-{
- E2kHTTPStatus status;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), E2K_HTTP_MALFORMED);
-
- if (e2k_operation_is_cancelled (op)) {
- soup_message_set_status (msg, E2K_HTTP_CANCELLED);
- return E2K_HTTP_CANCELLED;
- }
-
- e2k_operation_start (op, context_canceller, ctx, msg);
- status = soup_session_send_message (ctx->priv->session, msg);
- e2k_operation_finish (op);
-
- return status;
-}
-
-static void
-update_unique_uri (E2kContext *ctx, SoupMessage *msg,
- const gchar *folder_uri, const gchar *encoded_name, gint *count,
- E2kContextTestCallback test_callback, gpointer user_data)
-{
- SoupURI *suri;
- gchar *uri = NULL;
-
- do {
- g_free (uri);
- if (*count == 1) {
- uri = g_strdup_printf ("%s%s.EML", folder_uri,
- encoded_name);
- } else {
- uri = g_strdup_printf ("%s%s-%d.EML", folder_uri,
- encoded_name, *count);
- }
- (*count)++;
- } while (test_callback && !test_callback (ctx, uri, user_data));
-
- suri = soup_uri_new (uri);
- soup_message_set_uri (msg, suri);
- soup_uri_free (suri);
- g_free (uri);
-}
-
-/* GET */
-
-static SoupMessage *
-get_msg (E2kContext *ctx, const gchar *uri, gboolean owa, gboolean claim_ie)
-{
- SoupMessage *msg;
-
- msg = e2k_soup_message_new (ctx, uri, "GET");
- if (!owa)
- soup_message_headers_append (msg->request_headers, "Translate", "F");
- if (claim_ie) {
- soup_message_headers_replace (msg->request_headers, "User-Agent",
- "MSIE 6.0b (Windows NT 5.0; compatible; "
- "Evolution/" VERSION ")");
- }
-
- return msg;
-}
-
-/**
- * e2k_context_get:
- * @ctx: the context
- * @op: pointer to an #E2kOperation to use for cancellation
- * @uri: URI of the object to GET
- * @content_type: if not %NULL, will contain the Content-Type of the
- * response on return.
- * @response: if not %NULL, will contain the response on return
- *
- * Performs a GET on @ctx for @uri. If successful (2xx status code),
- * the Content-Type, and response body will be returned. The body is not
- * terminated by a '\0'. If the GET is not successful, @content_type and
- * @response will be untouched (even if the error response
- * included a body).
- *
- * Return value: the HTTP status
- **/
-E2kHTTPStatus
-e2k_context_get (E2kContext *ctx, E2kOperation *op, const gchar *uri,
- gchar **content_type, SoupBuffer **response)
-{
- SoupMessage *msg;
- E2kHTTPStatus status;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), E2K_HTTP_MALFORMED);
- g_return_val_if_fail (uri != NULL, E2K_HTTP_MALFORMED);
-
- msg = get_msg (ctx, uri, FALSE, FALSE);
- status = e2k_context_send_message (ctx, op, msg);
-
- if (E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
- if (content_type) {
- const gchar *header;
- header = soup_message_headers_get (msg->response_headers,
- "Content-Type");
- *content_type = g_strdup (header);
- }
- if (response)
- *response = soup_message_body_flatten (msg->response_body);
- }
-
- g_object_unref (msg);
- return status;
-}
-
-/**
- * e2k_context_get_owa:
- * @ctx: the context
- * @op: pointer to an #E2kOperation to use for cancellation
- * @uri: URI of the object to GET
- * @claim_ie: whether or not to claim to be IE
- * @response: if not %NULL, will contain the response on return
- *
- * As with e2k_context_get(), but used when you need the HTML or XML
- * data that would be returned to OWA rather than the raw object data.
- *
- * Return value: the HTTP status
- **/
-E2kHTTPStatus
-e2k_context_get_owa (E2kContext *ctx, E2kOperation *op,
- const gchar *uri, gboolean claim_ie,
- SoupBuffer **response)
-{
- SoupMessage *msg;
- E2kHTTPStatus status;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), E2K_HTTP_MALFORMED);
- g_return_val_if_fail (uri != NULL, E2K_HTTP_MALFORMED);
-
- msg = get_msg (ctx, uri, TRUE, claim_ie);
- status = e2k_context_send_message (ctx, op, msg);
-
- if (E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
- if (response)
- *response = soup_message_body_flatten (msg->response_body);
- }
-
- g_object_unref (msg);
- return status;
-}
-
-/* PUT / POST */
-
-static SoupMessage *
-put_msg (E2kContext *ctx, const gchar *uri, const gchar *content_type,
- SoupMemoryUse buffer_type, const gchar *body, gint length)
-{
- SoupMessage *msg;
-
- msg = e2k_soup_message_new_full (ctx, uri, "PUT", content_type,
- buffer_type, body, length);
- soup_message_headers_append (msg->request_headers, "Translate", "f");
-
- return msg;
-}
-
-static SoupMessage *
-post_msg (E2kContext *ctx, const gchar *uri, const gchar *content_type,
- SoupMemoryUse buffer_type, const gchar *body, gint length)
-{
- SoupMessage *msg;
-
- msg = e2k_soup_message_new_full (ctx, uri, "POST", content_type,
- buffer_type, body, length);
- soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT);
-
- return msg;
-}
-
-static void
-extract_put_results (SoupMessage *msg, gchar **location, gchar **repl_uid)
-{
- const gchar *header;
-
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (msg->status_code))
- return;
-
- if (repl_uid) {
- header = soup_message_headers_get (msg->response_headers,
- "Repl-UID");
- *repl_uid = g_strdup (header);
- }
- if (location) {
- header = soup_message_headers_get (msg->response_headers,
- "Location");
- *location = g_strdup (header);
- }
-}
-
-/**
- * e2k_context_put:
- * @ctx: the context
- * @op: pointer to an #E2kOperation to use for cancellation
- * @uri: the URI to PUT to
- * @content_type: MIME Content-Type of the data
- * @body: data to PUT
- * @length: length of @body
- * @repl_uid: if not %NULL, will contain the Repl-UID of the PUT
- * object on return
- *
- * Performs a PUT operation on @ctx for @uri.
- *
- * Return value: the HTTP status
- **/
-E2kHTTPStatus
-e2k_context_put (E2kContext *ctx, E2kOperation *op, const gchar *uri,
- const gchar *content_type, const gchar *body, gint length,
- gchar **repl_uid)
-{
- SoupMessage *msg;
- E2kHTTPStatus status;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), E2K_HTTP_MALFORMED);
- g_return_val_if_fail (uri != NULL, E2K_HTTP_MALFORMED);
- g_return_val_if_fail (content_type != NULL, E2K_HTTP_MALFORMED);
- g_return_val_if_fail (body != NULL, E2K_HTTP_MALFORMED);
-
- msg = put_msg (ctx, uri, content_type,
- SOUP_MEMORY_COPY, body, length);
- status = e2k_context_send_message (ctx, op, msg);
- extract_put_results (msg, NULL, repl_uid);
-
- g_object_unref (msg);
- return status;
-}
-
-/**
- * e2k_context_put_new:
- * @ctx: the context
- * @op: pointer to an #E2kOperation to use for cancellation
- * @folder_uri: the URI of the folder to PUT into
- * @object_name: base name of the new object (not URI-encoded)
- * @test_callback: callback to use to test possible object URIs
- * @user_data: data for @test_callback
- * @content_type: MIME Content-Type of the data
- * @body: data to PUT
- * @length: length of @body
- * @location: if not %NULL, will contain the Location of the PUT
- * object on return
- * @repl_uid: if not %NULL, will contain the Repl-UID of the PUT
- * object on return
- *
- * PUTs data into @folder_uri on @ctx with a new name based on
- * @object_name. If @test_callback is non-%NULL, it will be called
- * with each URI that is considered for the object so that the caller
- * can check its summary data to see if that URI is in use
- * (potentially saving one or more round-trips to the server).
- *
- * Return value: the HTTP status
- **/
-E2kHTTPStatus
-e2k_context_put_new (E2kContext *ctx, E2kOperation *op,
- const gchar *folder_uri, const gchar *object_name,
- E2kContextTestCallback test_callback, gpointer user_data,
- const gchar *content_type, const gchar *body, gint length,
- gchar **location, gchar **repl_uid)
-{
- SoupMessage *msg;
- E2kHTTPStatus status;
- gchar *slash_uri, *encoded_name;
- gint count;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), E2K_HTTP_MALFORMED);
- g_return_val_if_fail (folder_uri != NULL, E2K_HTTP_MALFORMED);
- g_return_val_if_fail (object_name != NULL, E2K_HTTP_MALFORMED);
- g_return_val_if_fail (content_type != NULL, E2K_HTTP_MALFORMED);
- g_return_val_if_fail (body != NULL, E2K_HTTP_MALFORMED);
-
- slash_uri = e2k_strdup_with_trailing_slash (folder_uri);
- encoded_name = e2k_uri_encode (object_name, TRUE, NULL);
-
- /* folder_uri is a dummy here */
- msg = put_msg (ctx, folder_uri, content_type,
- SOUP_MEMORY_COPY, body, length);
- soup_message_headers_append (msg->request_headers, "If-None-Match", "*");
-
- count = 1;
- do {
- update_unique_uri (ctx, msg, slash_uri, encoded_name, &count,
- test_callback, user_data);
- status = e2k_context_send_message (ctx, op, msg);
- } while (status == E2K_HTTP_PRECONDITION_FAILED);
-
- extract_put_results (msg, location, repl_uid);
-
- g_object_unref (msg);
- g_free (slash_uri);
- g_free (encoded_name);
- return status;
-}
-
-/**
- * e2k_context_post:
- * @ctx: the context
- * @op: pointer to an #E2kOperation to use for cancellation
- * @uri: the URI to POST to
- * @content_type: MIME Content-Type of the data
- * @body: data to PUT
- * @length: length of @body
- * @location: if not %NULL, will contain the Location of the POSTed
- * object on return
- * @repl_uid: if not %NULL, will contain the Repl-UID of the POSTed
- * object on return
- *
- * Performs a POST operation on @ctx for @uri.
- *
- * Note that POSTed objects will be irrevocably(?) marked as "unsent",
- * If you open a POSTed message in Outlook, it will open in the
- * composer rather than in the message viewer.
- *
- * Return value: the HTTP status
- **/
-E2kHTTPStatus
-e2k_context_post (E2kContext *ctx, E2kOperation *op, const gchar *uri,
- const gchar *content_type, const gchar *body, gint length,
- gchar **location, gchar **repl_uid)
-{
- SoupMessage *msg;
- E2kHTTPStatus status;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), E2K_HTTP_MALFORMED);
- g_return_val_if_fail (uri != NULL, E2K_HTTP_MALFORMED);
- g_return_val_if_fail (content_type != NULL, E2K_HTTP_MALFORMED);
- g_return_val_if_fail (body != NULL, E2K_HTTP_MALFORMED);
-
- msg = post_msg (ctx, uri, content_type,
- SOUP_MEMORY_COPY, body, length);
-
- status = e2k_context_send_message (ctx, op, msg);
- extract_put_results (msg, location, repl_uid);
-
- g_object_unref (msg);
- return status;
-}
-
-/* PROPPATCH */
-
-static void
-add_namespaces (const gchar *namespace, gchar abbrev, gpointer user_data)
-{
- GString *propxml = user_data;
-
- g_string_append_printf (propxml, " xmlns:%c=\"%s\"", abbrev, namespace);
-}
-
-static void
-write_prop (GString *xml, const gchar *propertyname,
- E2kPropType type, gpointer value, gboolean set)
-{
- const gchar *namespace, *name, *typestr;
- gchar *encoded, abbrev;
- gboolean b64enc, need_type;
- GByteArray *data;
- GPtrArray *array;
- gint i;
-
- if (set && (value == NULL))
- return;
-
- namespace = e2k_prop_namespace_name (propertyname);
- abbrev = e2k_prop_namespace_abbrev (propertyname);
- name = e2k_prop_property_name (propertyname);
-
- g_string_append_printf (xml, "<%c:%s", abbrev, name);
- if (!set) {
- /* This means we are removing the property, so just return
- with ending tag */
- g_string_append (xml, "/>");
- return;
- }
-
- need_type = (strstr (namespace, "/mapi/id/") != NULL);
- if (!need_type)
- g_string_append_c (xml, '>');
-
- switch (type) {
- case E2K_PROP_TYPE_BINARY:
- if (need_type)
- g_string_append (xml, " T:dt=\"bin.base64\">");
- data = value;
- encoded = g_base64_encode (data->data, data->len);
- g_string_append (xml, encoded);
- g_free (encoded);
- break;
-
- case E2K_PROP_TYPE_STRING_ARRAY:
- typestr = " T:dt=\"mv.string\">";
- b64enc = FALSE;
- goto array_common;
-
- case E2K_PROP_TYPE_INT_ARRAY:
- typestr = " T:dt=\"mv.int\">";
- b64enc = FALSE;
- goto array_common;
-
- case E2K_PROP_TYPE_BINARY_ARRAY:
- typestr = " T:dt=\"mv.bin.base64\">";
- b64enc = TRUE;
-
- array_common:
- if (need_type)
- g_string_append (xml, typestr);
- array = value;
- for (i = 0; i < array->len; i++) {
- g_string_append (xml, "<X:v>");
-
- if (b64enc) {
- data = array->pdata[i];
- encoded = g_base64_encode (data->data,
- data->len);
- g_string_append (xml, encoded);
- g_free (encoded);
- } else
- e2k_g_string_append_xml_escaped (xml, array->pdata[i]);
-
- g_string_append (xml, "</X:v>");
- }
- break;
-
- case E2K_PROP_TYPE_XML:
- g_assert_not_reached ();
- break;
-
- case E2K_PROP_TYPE_STRING:
- default:
- if (need_type) {
- switch (type) {
- case E2K_PROP_TYPE_INT:
- typestr = " T:dt=\"int\">";
- break;
- case E2K_PROP_TYPE_BOOL:
- typestr = " T:dt=\"boolean\">";
- break;
- case E2K_PROP_TYPE_FLOAT:
- typestr = " T:dt=\"float\">";
- break;
- case E2K_PROP_TYPE_DATE:
- typestr = " T:dt=\"dateTime.tz\">";
- break;
- default:
- typestr = ">";
- break;
- }
- g_string_append (xml, typestr);
- }
- e2k_g_string_append_xml_escaped (xml, value);
- break;
-
- }
-
- g_string_append_printf (xml, "</%c:%s>", abbrev, name);
-}
-
-static void
-add_set_props (const gchar *propertyname, E2kPropType type,
- gpointer value, gpointer user_data)
-{
- GString **props = user_data;
-
- if (!*props)
- *props = g_string_new (NULL);
-
- write_prop (*props, propertyname, type, value, TRUE);
-}
-
-static void
-add_remove_props (const gchar *propertyname, E2kPropType type,
- gpointer value, gpointer user_data)
-{
- GString **props = user_data;
-
- if (!*props)
- *props = g_string_new (NULL);
-
- write_prop (*props, propertyname, type, value, FALSE);
-}
-
-static SoupMessage *
-patch_msg (E2kContext *ctx, const gchar *uri, const gchar *method,
- const gchar **hrefs, gint nhrefs, E2kProperties *props,
- gboolean create)
-{
- SoupMessage *msg;
- GString *propxml, *subxml;
- gint i;
-
- propxml = g_string_new (E2K_XML_HEADER);
- g_string_append (propxml, "<D:propertyupdate xmlns:D=\"DAV:\"");
-
- /* Iterate over the properties, noting each namespace once,
- * then add them all to the header.
- */
- e2k_properties_foreach_namespace (props, add_namespaces, propxml);
- g_string_append (propxml, ">\r\n");
-
- /* If this is a BPROPPATCH, add the <target> section. */
- if (hrefs) {
- g_string_append (propxml, "<D:target>\r\n");
- for (i = 0; i < nhrefs; i++) {
- g_string_append_printf (propxml, "<D:href>%s</D:href>",
- hrefs[i]);
- }
- g_string_append (propxml, "\r\n</D:target>\r\n");
- }
-
- /* Add <set> properties. */
- subxml = NULL;
- e2k_properties_foreach (props, add_set_props, &subxml);
- if (subxml) {
- g_string_append (propxml, "<D:set><D:prop>\r\n");
- g_string_append (propxml, subxml->str);
- g_string_append (propxml, "\r\n</D:prop></D:set>");
- g_string_free (subxml, TRUE);
- }
-
- /* Add <remove> properties. */
- subxml = NULL;
- e2k_properties_foreach_removed (props, add_remove_props, &subxml);
- if (subxml) {
- g_string_append (propxml, "<D:remove><D:prop>\r\n");
- g_string_append (propxml, subxml->str);
- g_string_append (propxml, "\r\n</D:prop></D:remove>");
- g_string_free (subxml, TRUE);
- }
-
- /* Finish it up */
- g_string_append (propxml, "\r\n</D:propertyupdate>");
-
- /* And build the message. */
- msg = e2k_soup_message_new_full (ctx, uri, method,
- "text/xml", SOUP_MEMORY_TAKE,
- propxml->str, propxml->len);
- g_string_free (propxml, FALSE);
- soup_message_headers_append (msg->request_headers, "Brief", "t");
- if (!create)
- soup_message_headers_append (msg->request_headers, "If-Match", "*");
-
- return msg;
-}
-
-/**
- * e2k_context_proppatch:
- * @ctx: the context
- * @op: pointer to an #E2kOperation to use for cancellation
- * @uri: the URI to PROPPATCH
- * @props: the properties to set/remove
- * @create: whether or not to create @uri if it does not exist
- * @repl_uid: if not %NULL, will contain the Repl-UID of the
- * PROPPATCHed object on return
- *
- * Performs a PROPPATCH operation on @ctx for @uri.
- *
- * If @create is %FALSE and @uri does not already exist, the response
- * code will be %E2K_HTTP_PRECONDITION_FAILED.
- *
- * Return value: the HTTP status
- **/
-E2kHTTPStatus
-e2k_context_proppatch (E2kContext *ctx, E2kOperation *op,
- const gchar *uri, E2kProperties *props,
- gboolean create, gchar **repl_uid)
-{
- SoupMessage *msg;
- E2kHTTPStatus status;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), E2K_HTTP_MALFORMED);
- g_return_val_if_fail (uri != NULL, E2K_HTTP_MALFORMED);
- g_return_val_if_fail (props != NULL, E2K_HTTP_MALFORMED);
-
- msg = patch_msg (ctx, uri, "PROPPATCH", NULL, 0, props, create);
- status = e2k_context_send_message (ctx, op, msg);
- extract_put_results (msg, NULL, repl_uid);
-
- g_object_unref (msg);
- return status;
-}
-
-/**
- * e2k_context_proppatch_new:
- * @ctx: the context
- * @op: pointer to an #E2kOperation to use for cancellation
- * @folder_uri: the URI of the folder to PROPPATCH a new object in
- * @object_name: base name of the new object (not URI-encoded)
- * @test_callback: callback to use to test possible object URIs
- * @user_data: data for @test_callback
- * @props: the properties to set/remove
- * @location: if not %NULL, will contain the Location of the
- * PROPPATCHed object on return
- * @repl_uid: if not %NULL, will contain the Repl-UID of the
- * PROPPATCHed object on return
- *
- * PROPPATCHes data into @folder_uri on @ctx with a new name based on
- * @object_name. If @test_callback is non-%NULL, it will be called
- * with each URI that is considered for the object so that the caller
- * can check its summary data to see if that URI is in use
- * (potentially saving one or more round-trips to the server).
-
- * Return value: the HTTP status
- **/
-E2kHTTPStatus
-e2k_context_proppatch_new (E2kContext *ctx, E2kOperation *op,
- const gchar *folder_uri, const gchar *object_name,
- E2kContextTestCallback test_callback,
- gpointer user_data,
- E2kProperties *props,
- gchar **location, gchar **repl_uid)
-{
- SoupMessage *msg;
- E2kHTTPStatus status;
- gchar *slash_uri, *encoded_name;
- gint count;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), E2K_HTTP_MALFORMED);
- g_return_val_if_fail (folder_uri != NULL, E2K_HTTP_MALFORMED);
- g_return_val_if_fail (object_name != NULL, E2K_HTTP_MALFORMED);
- g_return_val_if_fail (props != NULL, E2K_HTTP_MALFORMED);
-
- slash_uri = e2k_strdup_with_trailing_slash (folder_uri);
- encoded_name = e2k_uri_encode (object_name, TRUE, NULL);
-
- /* folder_uri is a dummy here */
- msg = patch_msg (ctx, folder_uri, "PROPPATCH", NULL, 0, props, TRUE);
- soup_message_headers_append (msg->request_headers, "If-None-Match", "*");
-
- count = 1;
- do {
- update_unique_uri (ctx, msg, slash_uri, encoded_name, &count,
- test_callback, user_data);
- status = e2k_context_send_message (ctx, op, msg);
- } while (status == E2K_HTTP_PRECONDITION_FAILED);
-
- if (location)
- *location = soup_uri_to_string (soup_message_get_uri (msg), FALSE);
- extract_put_results (msg, NULL, repl_uid);
-
- g_object_unref (msg);
- g_free (slash_uri);
- g_free (encoded_name);
- return status;
-}
-
-static E2kHTTPStatus
-bproppatch_fetch (E2kResultIter *iter,
- E2kContext *ctx, E2kOperation *op,
- E2kResult **results, gint *nresults,
- gint *first, gint *total,
- gpointer user_data)
-{
- SoupMessage *msg = user_data;
- E2kHTTPStatus status;
-
- /* We only want to send the BPROPPATCH once. So check if we've
- * already done that.
- */
- if (msg->status_code != 0)
- return E2K_HTTP_OK;
-
- status = e2k_context_send_message (ctx, op, msg);
- if (status == E2K_HTTP_MULTI_STATUS) {
- e2k_results_from_multistatus (msg, results, nresults);
- *total = *nresults;
- }
- return status;
-}
-
-static void
-bproppatch_free (E2kResultIter *iter, gpointer msg)
-{
- g_object_unref (msg);
-}
-
-/**
- * e2k_context_bproppatch_start:
- * @ctx: the context
- * @op: pointer to an #E2kOperation to use for cancellation
- * @uri: the base URI
- * @hrefs: array of URIs, possibly relative to @uri
- * @nhrefs: length of @hrefs
- * @props: the properties to set/remove
- * @create: whether or not to create @uri if it does not exist
- *
- * Begins a BPROPPATCH (bulk PROPPATCH) of @hrefs based at @uri.
- *
- * Return value: an iterator for getting the results of the BPROPPATCH
- **/
-E2kResultIter *
-e2k_context_bproppatch_start (E2kContext *ctx, E2kOperation *op,
- const gchar *uri, const gchar **hrefs, gint nhrefs,
- E2kProperties *props, gboolean create)
-{
- SoupMessage *msg;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), NULL);
- g_return_val_if_fail (uri != NULL, NULL);
- g_return_val_if_fail (props != NULL, NULL);
-
- msg = patch_msg (ctx, uri, "BPROPPATCH", hrefs, nhrefs, props, create);
- return e2k_result_iter_new (ctx, op, TRUE, -1,
- bproppatch_fetch, bproppatch_free,
- msg);
-}
-
-/* PROPFIND */
-
-static SoupMessage *
-propfind_msg (E2kContext *ctx, const gchar *base_uri,
- const gchar **props, gint nprops, const gchar **hrefs, gint nhrefs)
-{
- SoupMessage *msg;
- GString *propxml;
- GData *set_namespaces;
- const gchar *name;
- gchar abbrev;
- gint i;
-
- propxml = g_string_new (E2K_XML_HEADER);
- g_string_append (propxml, "<D:propfind xmlns:D=\"DAV:\"");
-
- set_namespaces = NULL;
- for (i = 0; i < nprops; i++) {
- name = e2k_prop_namespace_name (props[i]);
- abbrev = e2k_prop_namespace_abbrev (props[i]);
-
- if (!g_datalist_get_data (&set_namespaces, name)) {
- g_datalist_set_data (&set_namespaces, name,
- GINT_TO_POINTER (1));
- g_string_append_printf (propxml, " xmlns:%c=\"%s\"",
- abbrev, name);
- }
- }
- g_datalist_clear (&set_namespaces);
- g_string_append (propxml, ">\r\n");
-
- if (hrefs) {
- g_string_append (propxml, "<D:target>\r\n");
- for (i = 0; i < nhrefs; i++) {
- g_string_append_printf (propxml, "<D:href>%s</D:href>",
- hrefs[i]);
- }
- g_string_append (propxml, "\r\n</D:target>\r\n");
- }
-
- g_string_append (propxml, "<D:prop>\r\n");
- for (i = 0; i < nprops; i++) {
- abbrev = e2k_prop_namespace_abbrev (props[i]);
- name = e2k_prop_property_name (props[i]);
- g_string_append_printf (propxml, "<%c:%s/>", abbrev, name);
- }
- g_string_append (propxml, "\r\n</D:prop>\r\n</D:propfind>");
-
- msg = e2k_soup_message_new_full (ctx, base_uri,
- hrefs ? "BPROPFIND" : "PROPFIND",
- "text/xml", SOUP_MEMORY_TAKE,
- propxml->str, propxml->len);
- g_string_free (propxml, FALSE);
- soup_message_headers_append (msg->request_headers, "Brief", "t");
- soup_message_headers_append (msg->request_headers, "Depth", "0");
-
- return msg;
-}
-
-/**
- * e2k_context_propfind:
- * @ctx: the context
- * @op: pointer to an #E2kOperation to use for cancellation
- * @uri: the URI to PROPFIND on
- * @props: array of properties to find
- * @nprops: length of @props
- * @results: on return, the results
- * @nresults: length of @results
- *
- * Performs a PROPFIND operation on @ctx for @uri. If successful, the
- * results are returned as an array of #E2kResult (which you must free
- * with e2k_results_free()), but the array will always have either 0
- * or 1 members.
- *
- * Return value: the HTTP status
- **/
-E2kHTTPStatus
-e2k_context_propfind (E2kContext *ctx, E2kOperation *op,
- const gchar *uri, const gchar **props, gint nprops,
- E2kResult **results, gint *nresults)
-{
- SoupMessage *msg;
- E2kHTTPStatus status;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), E2K_HTTP_MALFORMED);
- g_return_val_if_fail (uri != NULL, E2K_HTTP_MALFORMED);
- g_return_val_if_fail (props != NULL, E2K_HTTP_MALFORMED);
-
- msg = propfind_msg (ctx, uri, props, nprops, NULL, 0);
- status = e2k_context_send_message (ctx, op, msg);
-
- if (msg->status_code == E2K_HTTP_MULTI_STATUS)
- e2k_results_from_multistatus (msg, results, nresults);
- g_object_unref (msg);
- return status;
-}
-
-static E2kHTTPStatus
-bpropfind_fetch (E2kResultIter *iter,
- E2kContext *ctx, E2kOperation *op,
- E2kResult **results, gint *nresults,
- gint *first, gint *total,
- gpointer user_data)
-{
- GSList **msgs = user_data;
- E2kHTTPStatus status;
- SoupMessage *msg;
-
- if (!*msgs)
- return E2K_HTTP_OK;
-
- msg = (*msgs)->data;
- *msgs = g_slist_remove (*msgs, msg);
-
- status = e2k_context_send_message (ctx, op, msg);
- if (status == E2K_HTTP_MULTI_STATUS)
- e2k_results_from_multistatus (msg, results, nresults);
- g_object_unref (msg);
-
- return status;
-}
-
-static void
-bpropfind_free (E2kResultIter *iter, gpointer user_data)
-{
- GSList **msgs = user_data, *m;
-
- for (m = *msgs; m; m = m->next)
- g_object_unref (m->data);
- g_slist_free (*msgs);
- g_free (msgs);
-}
-
-/**
- * e2k_context_bpropfind_start:
- * @ctx: the context
- * @op: pointer to an #E2kOperation to use for cancellation
- * @uri: the base URI
- * @hrefs: array of URIs, possibly relative to @uri
- * @nhrefs: length of @hrefs
- * @props: array of properties to find
- * @nprops: length of @props
- *
- * Begins a BPROPFIND (bulk PROPFIND) operation on @ctx for @hrefs.
- *
- * Return value: an iterator for getting the results
- **/
-E2kResultIter *
-e2k_context_bpropfind_start (E2kContext *ctx, E2kOperation *op,
- const gchar *uri, const gchar **hrefs, gint nhrefs,
- const gchar **props, gint nprops)
-{
- SoupMessage *msg;
- GSList **msgs;
- gint i;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), NULL);
- g_return_val_if_fail (uri != NULL, NULL);
- g_return_val_if_fail (props != NULL, NULL);
- g_return_val_if_fail (hrefs != NULL, NULL);
-
- msgs = g_new0 (GSList *, 1);
- for (i = 0; i < nhrefs; i += E2K_CONTEXT_MAX_BATCH_SIZE) {
- msg = propfind_msg (ctx, uri, props, nprops,
- hrefs + i, MIN (E2K_CONTEXT_MAX_BATCH_SIZE, nhrefs - i));
- *msgs = g_slist_append (*msgs, msg);
- }
-
- return e2k_result_iter_new (ctx, op, TRUE, nhrefs,
- bpropfind_fetch, bpropfind_free,
- msgs);
-}
-
-/* SEARCH */
-
-static SoupMessage *
-search_msg (E2kContext *ctx, const gchar *uri,
- SoupMemoryUse buffer_type, const gchar *searchxml,
- gint size, gboolean ascending, gint offset)
-{
- SoupMessage *msg;
-
- msg = e2k_soup_message_new_full (ctx, uri, "SEARCH", "text/xml",
- buffer_type, searchxml,
- strlen (searchxml));
- soup_message_headers_append (msg->request_headers, "Brief", "t");
-
- if (size) {
- gchar *range;
-
- if (offset == INT_MAX) {
- range = g_strdup_printf ("rows=-%u", size);
- } else {
- range = g_strdup_printf ("rows=%u-%u",
- offset, offset + size - 1);
- }
- soup_message_headers_append (msg->request_headers, "Range", range);
- g_free (range);
- }
-
- return msg;
-}
-
-static gchar *
-search_xml (const gchar **props, gint nprops,
- E2kRestriction *rn, const gchar *orderby)
-{
- GString *xml;
- gchar *ret, *where;
- gint i;
-
- xml = g_string_new (E2K_XML_HEADER);
- g_string_append (xml, "<searchrequest xmlns=\"DAV:\"><sql>\r\n");
- g_string_append (xml, "SELECT ");
-
- for (i = 0; i < nprops; i++) {
- if (i > 0)
- g_string_append (xml, ", ");
- g_string_append_c (xml, '"');
- g_string_append (xml, props[i]);
- g_string_append_c (xml, '"');
- }
-
- if (e2k_restriction_folders_only (rn))
- g_string_append_printf (xml, "\r\nFROM SCOPE('hierarchical traversal of \"\"')\r\n");
- else
- g_string_append (xml, "\r\nFROM \"\"\r\n");
-
- if (rn) {
- where = e2k_restriction_to_sql (rn);
- if (where) {
- e2k_g_string_append_xml_escaped (xml, where);
- g_string_append (xml, "\r\n");
- g_free (where);
- }
- }
-
- if (orderby)
- g_string_append_printf (xml, "ORDER BY \"%s\"\r\n", orderby);
-
- g_string_append (xml, "</sql></searchrequest>");
-
- ret = xml->str;
- g_string_free (xml, FALSE);
-
- return ret;
-}
-
-static gboolean
-search_result_get_range (SoupMessage *msg, gint *first, gint *total)
-{
- const gchar *range, *p;
-
- range = soup_message_headers_get (msg->response_headers,
- "Content-Range");
- if (!range)
- return FALSE;
- p = strstr (range, "rows ");
- if (!p)
- return FALSE;
-
- if (first)
- *first = atoi (p + 5);
-
- if (total) {
- p = strstr (range, "total=");
- if (p)
- *total = atoi (p + 6);
- else
- *total = -1;
- }
-
- return TRUE;
-}
-
-typedef struct {
- gchar *uri, *xml;
- gboolean ascending;
- gint batch_size, next;
-} E2kSearchData;
-
-static E2kHTTPStatus
-search_fetch (E2kResultIter *iter,
- E2kContext *ctx, E2kOperation *op,
- E2kResult **results, gint *nresults,
- gint *first, gint *total,
- gpointer user_data)
-{
- E2kSearchData *search_data = user_data;
- E2kHTTPStatus status;
- SoupMessage *msg;
-
- if (search_data->batch_size == 0)
- return E2K_HTTP_OK;
-
- msg = search_msg (ctx, search_data->uri,
- SOUP_MEMORY_COPY, search_data->xml,
- search_data->batch_size,
- search_data->ascending, search_data->next);
- status = e2k_context_send_message (ctx, op, msg);
- if (msg->status_code == E2K_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE)
- status = E2K_HTTP_OK;
- else if (status == E2K_HTTP_MULTI_STATUS) {
- search_result_get_range (msg, first, total);
- if (*total == 0)
- goto cleanup;
-
- e2k_results_from_multistatus (msg, results, nresults);
- if (*total == -1)
- *total = *first + *nresults;
-
- if (search_data->ascending && *first + *nresults < *total)
- search_data->next = *first + *nresults;
- else if (!search_data->ascending && *first > 0) {
- if (*first >= search_data->batch_size)
- search_data->next = *first - search_data->batch_size;
- else {
- search_data->batch_size = *first;
- search_data->next = 0;
- }
- } else
- search_data->batch_size = 0;
- }
-
- cleanup:
- g_object_unref (msg);
- return status;
-}
-
-static void
-search_free (E2kResultIter *iter, gpointer user_data)
-{
- E2kSearchData *search_data = user_data;
-
- g_free (search_data->uri);
- g_free (search_data->xml);
- g_free (search_data);
-}
-
-/**
- * e2k_context_search_start:
- * @ctx: the context
- * @op: pointer to an #E2kOperation to use for cancellation
- * @uri: the folder to search
- * @props: the properties to search for
- * @nprops: size of @props array
- * @rn: the search restriction
- * @orderby: if non-%NULL, the field to sort the search results by
- * @ascending: %TRUE for an ascending search, %FALSE for descending.
- *
- * Begins a SEARCH on @ctx at @uri.
- *
- * Return value: an iterator for returning the search results
- **/
-E2kResultIter *
-e2k_context_search_start (E2kContext *ctx, E2kOperation *op, const gchar *uri,
- const gchar **props, gint nprops, E2kRestriction *rn,
- const gchar *orderby, gboolean ascending)
-{
- E2kSearchData *search_data;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), NULL);
- g_return_val_if_fail (uri != NULL, NULL);
- g_return_val_if_fail (props != NULL, NULL);
-
- search_data = g_new0 (E2kSearchData, 1);
- search_data->uri = g_strdup (uri);
- search_data->xml = search_xml (props, nprops, rn, orderby);
- search_data->ascending = ascending;
- search_data->batch_size = E2K_CONTEXT_MAX_BATCH_SIZE;
- search_data->next = ascending ? 0 : INT_MAX;
-
- return e2k_result_iter_new (ctx, op, ascending, -1,
- search_fetch, search_free,
- search_data);
-}
-
-/* DELETE */
-
-static SoupMessage *
-delete_msg (E2kContext *ctx, const gchar *uri)
-{
- return e2k_soup_message_new (ctx, uri, "DELETE");
-}
-
-/**
- * e2k_context_delete:
- * @ctx: the context
- * @op: pointer to an #E2kOperation to use for cancellation
- * @uri: URI to DELETE
- *
- * Attempts to DELETE @uri on @ctx.
- *
- * Return value: the HTTP status
- **/
-E2kHTTPStatus
-e2k_context_delete (E2kContext *ctx, E2kOperation *op, const gchar *uri)
-{
- SoupMessage *msg;
- E2kHTTPStatus status;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), E2K_HTTP_MALFORMED);
- g_return_val_if_fail (uri != NULL, E2K_HTTP_MALFORMED);
-
- msg = delete_msg (ctx, uri);
- status = e2k_context_send_message (ctx, op, msg);
-
- g_object_unref (msg);
- return status;
-}
-
-/* BDELETE */
-
-static SoupMessage *
-bdelete_msg (E2kContext *ctx, const gchar *uri, const gchar **hrefs, gint nhrefs)
-{
- SoupMessage *msg;
- GString *xml;
- gint i;
-
- xml = g_string_new (E2K_XML_HEADER "<delete xmlns=\"DAV:\"><target>");
-
- for (i = 0; i < nhrefs; i++) {
- g_string_append (xml, "<href>");
- e2k_g_string_append_xml_escaped (xml, hrefs[i]);
- g_string_append (xml, "</href>");
- }
-
- g_string_append (xml, "</target></delete>");
-
- msg = e2k_soup_message_new_full (ctx, uri, "BDELETE", "text/xml",
- SOUP_MEMORY_TAKE,
- xml->str, xml->len);
- g_string_free (xml, FALSE);
-
- return msg;
-}
-
-static E2kHTTPStatus
-bdelete_fetch (E2kResultIter *iter,
- E2kContext *ctx, E2kOperation *op,
- E2kResult **results, gint *nresults,
- gint *first, gint *total,
- gpointer user_data)
-{
- GSList **msgs = user_data;
- E2kHTTPStatus status;
- SoupMessage *msg;
-
- if (!*msgs)
- return E2K_HTTP_OK;
-
- msg = (*msgs)->data;
- *msgs = g_slist_remove (*msgs, msg);
-
- status = e2k_context_send_message (ctx, op, msg);
- if (status == E2K_HTTP_MULTI_STATUS)
- e2k_results_from_multistatus (msg, results, nresults);
- g_object_unref (msg);
-
- return status;
-}
-
-static void
-bdelete_free (E2kResultIter *iter, gpointer user_data)
-{
- GSList **msgs = user_data, *m;
-
- for (m = (*msgs); m; m = m->next)
- g_object_unref (m->data);
- g_slist_free (*msgs);
- g_free (msgs);
-}
-
-/**
- * e2k_context_bdelete_start:
- * @ctx: the context
- * @op: pointer to an #E2kOperation to use for cancellation
- * @uri: the base URI
- * @hrefs: array of URIs, possibly relative to @uri, to delete
- * @nhrefs: length of @hrefs
- *
- * Begins a BDELETE (bulk DELETE) operation on @ctx for @hrefs.
- *
- * Return value: an iterator for returning the results
- **/
-E2kResultIter *
-e2k_context_bdelete_start (E2kContext *ctx, E2kOperation *op,
- const gchar *uri, const gchar **hrefs, gint nhrefs)
-{
- GSList **msgs;
- gint i, batchsize;
- SoupMessage *msg;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), NULL);
- g_return_val_if_fail (uri != NULL, NULL);
- g_return_val_if_fail (hrefs != NULL, NULL);
-
- batchsize = (nhrefs + 9) / 10;
- if (batchsize < E2K_CONTEXT_MIN_BATCH_SIZE)
- batchsize = E2K_CONTEXT_MIN_BATCH_SIZE;
- else if (batchsize > E2K_CONTEXT_MAX_BATCH_SIZE)
- batchsize = E2K_CONTEXT_MAX_BATCH_SIZE;
-
- msgs = g_new0 (GSList *, 1);
- for (i = 0; i < nhrefs; i += batchsize) {
- batchsize = MIN (batchsize, nhrefs - i);
- msg = bdelete_msg (ctx, uri, hrefs + i, batchsize);
- *msgs = g_slist_prepend (*msgs, msg);
- }
-
- return e2k_result_iter_new (ctx, op, TRUE, nhrefs,
- bdelete_fetch, bdelete_free,
- msgs);
-}
-
-/* MKCOL */
-
-/**
- * e2k_context_mkcol:
- * @ctx: the context
- * @op: pointer to an #E2kOperation to use for cancellation
- * @uri: URI of the new folder
- * @props: properties to set on the new folder, or %NULL
- * @permanent_url: if not %NULL, will contain the permanent URL of the
- * new folder on return
- *
- * Performs a MKCOL operation on @ctx to create @uri, with optional
- * additional properties.
- *
- * Return value: the HTTP status
- **/
-E2kHTTPStatus
-e2k_context_mkcol (E2kContext *ctx, E2kOperation *op,
- const gchar *uri, E2kProperties *props,
- gchar **permanent_url)
-{
- SoupMessage *msg;
- E2kHTTPStatus status;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), E2K_HTTP_MALFORMED);
- g_return_val_if_fail (uri != NULL, E2K_HTTP_MALFORMED);
-
- if (!props)
- msg = e2k_soup_message_new (ctx, uri, "MKCOL");
- else
- msg = patch_msg (ctx, uri, "MKCOL", NULL, 0, props, TRUE);
-
- status = e2k_context_send_message (ctx, op, msg);
- if (E2K_HTTP_STATUS_IS_SUCCESSFUL (status) && permanent_url) {
- const gchar *header;
-
- header = soup_message_headers_get (msg->response_headers,
- "MS-Exchange-Permanent-URL");
- *permanent_url = g_strdup (header);
- }
-
- g_object_unref (msg);
- return status;
-}
-
-/* BMOVE / BCOPY */
-
-static SoupMessage *
-transfer_msg (E2kContext *ctx,
- const gchar *source_uri, const gchar *dest_uri,
- const gchar **source_hrefs, gint nhrefs,
- gboolean delete_originals)
-{
- SoupMessage *msg;
- GString *xml;
- gint i;
-
- xml = g_string_new (E2K_XML_HEADER);
- g_string_append (xml, delete_originals ? "<move" : "<copy");
- g_string_append (xml, " xmlns=\"DAV:\"><target>");
- for (i = 0; i < nhrefs; i++) {
- g_string_append (xml, "<href>");
- e2k_g_string_append_xml_escaped (xml, source_hrefs[i]);
- g_string_append (xml, "</href>");
- }
- g_string_append (xml, "</target></");
- g_string_append (xml, delete_originals ? "move>" : "copy>");
-
- msg = e2k_soup_message_new_full (ctx, source_uri,
- delete_originals ? "BMOVE" : "BCOPY",
- "text/xml",
- SOUP_MEMORY_TAKE,
- xml->str, xml->len);
- soup_message_headers_append (msg->request_headers, "Overwrite", "f");
- soup_message_headers_append (msg->request_headers, "Allow-Rename", "t");
- soup_message_headers_append (msg->request_headers, "Destination", dest_uri);
- g_string_free (xml, FALSE);
-
- return msg;
-}
-
-static E2kHTTPStatus
-transfer_next (E2kResultIter *iter,
- E2kContext *ctx, E2kOperation *op,
- E2kResult **results, gint *nresults,
- gint *first, gint *total,
- gpointer user_data)
-{
- GSList **msgs = user_data;
- SoupMessage *msg;
- E2kHTTPStatus status;
-
- if (!*msgs)
- return E2K_HTTP_OK;
-
- msg = (*msgs)->data;
- *msgs = g_slist_remove (*msgs, msg);
-
- status = e2k_context_send_message (ctx, op, msg);
- if (status == E2K_HTTP_MULTI_STATUS)
- e2k_results_from_multistatus (msg, results, nresults);
-
- g_object_unref (msg);
- return status;
-}
-
-static void
-transfer_free (E2kResultIter *iter, gpointer user_data)
-{
- GSList **msgs = user_data, *m;
-
- for (m = *msgs; m; m = m->next)
- g_object_unref (m->data);
- g_slist_free (*msgs);
- g_free (msgs);
-}
-
-/**
- * e2k_context_transfer_start:
- * @ctx: the context
- * @op: pointer to an #E2kOperation to use for cancellation
- * @source_folder: URI of the source folder
- * @dest_folder: URI of the destination folder
- * @source_hrefs: an array of hrefs to move, relative to @source_folder
- * @delete_originals: whether or not to delete the original objects
- *
- * Starts a BMOVE or BCOPY (depending on @delete_originals) operation
- * on @ctx for @source_folder. The objects in @source_folder described
- * by @source_hrefs will be moved or copied to @dest_folder.
- * e2k_result_iter_next() can be used to check the success or failure
- * of each move/copy. (The #E2K_PR_DAV_LOCATION property for each
- * result will show the new location of the object.)
- *
- * NB: may not work correctly if @source_hrefs contains folders
- *
- * Return value: the iterator for the results
- **/
-E2kResultIter *
-e2k_context_transfer_start (E2kContext *ctx, E2kOperation *op,
- const gchar *source_folder, const gchar *dest_folder,
- GPtrArray *source_hrefs, gboolean delete_originals)
-{
- GSList **msgs;
- SoupMessage *msg;
- gchar *dest_uri;
- const gchar **hrefs;
- gint i;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), NULL);
- g_return_val_if_fail (source_folder != NULL, NULL);
- g_return_val_if_fail (dest_folder != NULL, NULL);
- g_return_val_if_fail (source_hrefs != NULL, NULL);
-
- dest_uri = e2k_strdup_with_trailing_slash (dest_folder);
- if (!dest_uri)
- return NULL;
- hrefs = (const gchar **)source_hrefs->pdata;
-
- msgs = g_new0 (GSList *, 1);
- for (i = 0; i < source_hrefs->len; i += E2K_CONTEXT_MAX_BATCH_SIZE) {
- msg = transfer_msg (ctx, source_folder, dest_uri,
- hrefs + i, MIN (E2K_CONTEXT_MAX_BATCH_SIZE, source_hrefs->len - i),
- delete_originals);
- *msgs = g_slist_append (*msgs, msg);
- }
- g_free (dest_uri);
-
- return e2k_result_iter_new (ctx, op, TRUE, source_hrefs->len,
- transfer_next, transfer_free,
- msgs);
-}
-
-/**
- * e2k_context_transfer_dir:
- * @ctx: the context
- * @op: pointer to an #E2kOperation to use for cancellation
- * @source_href: URI of the source folder
- * @dest_href: URI of the destination folder
- * @delete_original: whether or not to delete the original folder
- * @permanent_url: if not %NULL, will contain the permanent URL of the
- * new folder on return
- *
- * Performs a MOVE or COPY (depending on @delete_original) operation
- * on @ctx for @source_href. The folder itself will be moved, renamed,
- * or copied to @dest_href (which is the name of the new folder
- * itself, not its parent).
- *
- * Return value: the HTTP status
- **/
-E2kHTTPStatus
-e2k_context_transfer_dir (E2kContext *ctx, E2kOperation *op,
- const gchar *source_href, const gchar *dest_href,
- gboolean delete_original,
- gchar **permanent_url)
-{
- SoupMessage *msg;
- E2kHTTPStatus status;
-
- g_return_val_if_fail (E2K_IS_CONTEXT (ctx), E2K_HTTP_MALFORMED);
- g_return_val_if_fail (source_href != NULL, E2K_HTTP_MALFORMED);
- g_return_val_if_fail (dest_href != NULL, E2K_HTTP_MALFORMED);
-
- msg = e2k_soup_message_new (ctx, source_href, delete_original ? "MOVE" : "COPY");
- soup_message_headers_append (msg->request_headers, "Overwrite", "f");
- soup_message_headers_append (msg->request_headers, "Destination", dest_href);
-
- status = e2k_context_send_message (ctx, op, msg);
- if (E2K_HTTP_STATUS_IS_SUCCESSFUL (status) && permanent_url) {
- const gchar *header;
-
- header = soup_message_headers_get (msg->response_headers,
- "MS-Exchange-Permanent-URL");
- *permanent_url = g_strdup (header);
- }
-
- g_object_unref (msg);
- return status;
-}
-
-/* Subscriptions */
-
-typedef struct {
- E2kContext *ctx;
- gchar *uri, *id;
- E2kContextChangeType type;
- gint lifetime, min_interval;
- time_t last_notification;
-
- E2kContextChangeCallback callback;
- gpointer user_data;
-
- guint renew_timeout;
- SoupMessage *renew_msg;
- guint poll_timeout;
- SoupMessage *poll_msg;
- guint notification_timeout;
-} E2kSubscription;
-
-static gboolean
-belated_notification (gpointer user_data)
-{
- E2kSubscription *sub = user_data;
-
- sub->notification_timeout = 0;
- sub->callback (sub->ctx, sub->uri, sub->type, sub->user_data);
- return FALSE;
-}
-
-static void
-maybe_notification (E2kSubscription *sub)
-{
- time_t now = time (NULL);
- gint delay = sub->last_notification + sub->min_interval - now;
-
- if (delay > 0) {
- if (sub->notification_timeout)
- g_source_remove (sub->notification_timeout);
- sub->notification_timeout = g_timeout_add (delay * 1000,
- belated_notification,
- sub);
- return;
- }
- sub->last_notification = now;
-
- sub->callback (sub->ctx, sub->uri, sub->type, sub->user_data);
-}
-
-static void
-polled (SoupSession *session, SoupMessage *msg, gpointer user_data)
-{
- E2kSubscription *sub = user_data;
- E2kContext *ctx = sub->ctx;
- E2kResult *results;
- gint nresults, i;
- xmlNode *ids;
- xmlChar *id;
-
- sub->poll_msg = NULL;
- if (msg->status_code != E2K_HTTP_MULTI_STATUS) {
- g_warning ("Unexpected error %d %s from POLL",
- msg->status_code, msg->reason_phrase);
- return;
- }
-
- e2k_results_from_multistatus (msg, &results, &nresults);
- for (i = 0; i < nresults; i++) {
- if (results[i].status != E2K_HTTP_OK)
- continue;
-
- ids = e2k_properties_get_prop (results[i].props, E2K_PR_SUBSCRIPTION_ID);
- if (!ids)
- continue;
- for (ids = ids->xmlChildrenNode; ids; ids = ids->next) {
- if (xmlStrcmp (ids->name, (xmlChar *) "li") != 0 ||
- !ids->xmlChildrenNode ||
- !ids->xmlChildrenNode->content)
- continue;
- id = ids->xmlChildrenNode->content;
- sub = g_hash_table_lookup (ctx->priv->subscriptions_by_id, id);
- if (sub)
- maybe_notification (sub);
- }
- }
- e2k_results_free (results, nresults);
-}
-
-static gboolean
-timeout_notification (gpointer user_data)
-{
- E2kSubscription *sub = user_data, *sub2;
- E2kContext *ctx = sub->ctx;
- GList *sub_list;
- GString *subscription_ids;
-
- sub->poll_timeout = 0;
- subscription_ids = g_string_new (sub->id);
-
- /* Find all subscriptions at this URI that are awaiting a
- * POLL so we can POLL them all at once.
- */
- sub_list = g_hash_table_lookup (ctx->priv->subscriptions_by_uri,
- sub->uri);
- for (; sub_list; sub_list = sub_list->next) {
- sub2 = sub_list->data;
- if (sub2 == sub)
- continue;
- if (!sub2->poll_timeout)
- continue;
- g_source_remove (sub2->poll_timeout);
- sub2->poll_timeout = 0;
- g_string_append_printf (subscription_ids, ",%s", sub2->id);
- }
-
- sub->poll_msg = e2k_soup_message_new (ctx, sub->uri, "POLL");
- soup_message_headers_append (sub->poll_msg->request_headers,
- "Subscription-id", subscription_ids->str);
- e2k_context_queue_message (ctx, sub->poll_msg, polled, sub);
-
- g_string_free (subscription_ids, TRUE);
- return FALSE;
-}
-
-static gboolean
-do_notification (GIOChannel *source, GIOCondition condition, gpointer data)
-{
- E2kContext *ctx = data;
- E2kSubscription *sub;
- gchar buffer[1024], *id, *lasts;
- gsize len;
- GIOStatus status;
-
- status = g_io_channel_read_chars (source, buffer, sizeof (buffer) - 1, &len, NULL);
- if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN) {
- g_warning ("do_notification I/O error: %d (%s)", status,
- g_strerror (errno));
- return FALSE;
- }
- buffer[len] = '\0';
-
-#ifdef E2K_DEBUG
- if (e2k_debug_level) {
- if (e2k_debug_level == 1) {
- fwrite (buffer, 1, strcspn (buffer, "\r\n"), stdout);
- fputs ("\n\n", stdout);
- } else
- fputs (buffer, stdout);
- }
-#endif
-
- if (g_ascii_strncasecmp (buffer, "NOTIFY ", 7) != 0)
- return TRUE;
-
- id = buffer;
- while (1) {
- id = strchr (id, '\n');
- if (!id++)
- return TRUE;
- if (g_ascii_strncasecmp (id, "Subscription-id: ", 17) == 0)
- break;
- }
- id += 17;
-
- for (id = strtok_r (id, ",\r", &lasts); id; id = strtok_r (NULL, ",\r", &lasts)) {
- sub = g_hash_table_lookup (ctx->priv->subscriptions_by_id, id);
- if (!sub)
- continue;
-
- /* We don't want to POLL right away in case there are
- * several changes in a row. So we just bump up the
- * timeout to be one second from now. (Using an idle
- * handler here doesn't actually work to prevent
- * multiple POLLs.)
- */
- if (sub->poll_timeout)
- g_source_remove (sub->poll_timeout);
- sub->poll_timeout =
- g_timeout_add (1000, timeout_notification, sub);
- }
-
- return TRUE;
-}
-
-static void
-renew_cb (SoupSession *session, SoupMessage *msg, gpointer user_data)
-{
- E2kSubscription *sub = user_data;
-
- sub->renew_msg = NULL;
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- g_warning ("renew_subscription: %d %s", msg->status_code,
- msg->reason_phrase);
- return;
- }
-
- if (sub->id) {
- g_hash_table_remove (sub->ctx->priv->subscriptions_by_id, sub->id);
- g_free (sub->id);
- }
- sub->id = g_strdup (soup_message_headers_get (msg->response_headers,
- "Subscription-id"));
- g_return_if_fail (sub->id != NULL);
- g_hash_table_insert (sub->ctx->priv->subscriptions_by_id,
- sub->id, sub);
-}
-
-#define E2K_SUBSCRIPTION_INITIAL_LIFETIME 3600 /* 1 hour */
-#define E2K_SUBSCRIPTION_MAX_LIFETIME 57600 /* 16 hours */
-
-/* This must be kept in sync with E2kSubscriptionType */
-static const gchar *subscription_type[] = {
- "update", /* E2K_SUBSCRIPTION_OBJECT_CHANGED */
- "update/newmember", /* E2K_SUBSCRIPTION_OBJECT_ADDED */
- "delete", /* E2K_SUBSCRIPTION_OBJECT_REMOVED */
- "move" /* E2K_SUBSCRIPTION_OBJECT_MOVED */
-};
-
-static gboolean
-renew_subscription (gpointer user_data)
-{
- E2kSubscription *sub = user_data;
- E2kContext *ctx = sub->ctx;
- gchar ltbuf[80];
-
- if (!ctx->priv->notification_uri)
- return FALSE;
-
- if (sub->lifetime < E2K_SUBSCRIPTION_MAX_LIFETIME)
- sub->lifetime *= 2;
-
- sub->renew_msg = e2k_soup_message_new (ctx, sub->uri, "SUBSCRIBE");
- sprintf (ltbuf, "%d", sub->lifetime);
- soup_message_headers_append (sub->renew_msg->request_headers,
- "Subscription-lifetime", ltbuf);
- soup_message_headers_append (sub->renew_msg->request_headers,
- "Notification-type",
- subscription_type[sub->type]);
- if (sub->min_interval > 1) {
- sprintf (ltbuf, "%d", sub->min_interval);
- soup_message_headers_append (sub->renew_msg->request_headers,
- "Notification-delay", ltbuf);
- }
- soup_message_headers_append (sub->renew_msg->request_headers,
- "Call-back", ctx->priv->notification_uri);
-
- e2k_context_queue_message (ctx, sub->renew_msg, renew_cb, sub);
- sub->renew_timeout = g_timeout_add ((sub->lifetime - 60) * 1000,
- renew_subscription, sub);
- return FALSE;
-}
-
-/**
- * e2k_context_subscribe:
- * @ctx: the context
- * @uri: the folder URI to subscribe to notifications on
- * @type: the type of notification to subscribe to
- * @min_interval: the minimum interval (in seconds) between
- * notifications.
- * @callback: the callback to call when a notification has been
- * received
- * @user_data: data to pass to @callback.
- *
- * This subscribes to change notifications of the given @type on @uri.
- * @callback will (eventually) be invoked any time the folder changes
- * in the given way: whenever an object is added to it for
- * %E2K_CONTEXT_OBJECT_ADDED, whenever an object is deleted (but
- * not moved) from it (or the folder itself is deleted) for
- * %E2K_CONTEXT_OBJECT_REMOVED, whenever an object is moved in or
- * out of the folder for %E2K_CONTEXT_OBJECT_MOVED, and whenever
- * any of the above happens, or the folder or one of its items is
- * modified, for %E2K_CONTEXT_OBJECT_CHANGED. (This means that if
- * you subscribe to both CHANGED and some other notification on the
- * same folder that multiple callbacks may be invoked every time an
- * object is added/removed/moved/etc.)
- *
- * Notifications can be used *only* to discover changes made by other
- * clients! The code cannot assume that it will receive a notification
- * for every change that it makes to the server, for two reasons:
- *
- * First, if multiple notifications occur within @min_interval seconds
- * of each other, the later ones will be suppressed, to avoid
- * excessive traffic between the client and the server as the client
- * tries to sync. Second, if there is a firewall between the client
- * and the server, it is possible that all notifications will be lost.
- **/
-void
-e2k_context_subscribe (E2kContext *ctx, const gchar *uri,
- E2kContextChangeType type, gint min_interval,
- E2kContextChangeCallback callback,
- gpointer user_data)
-{
- E2kSubscription *sub;
- GList *sub_list;
- gpointer key, value;
-
- g_return_if_fail (E2K_IS_CONTEXT (ctx));
-
- sub = g_new0 (E2kSubscription, 1);
- sub->ctx = ctx;
- sub->uri = g_strdup (uri);
- sub->type = type;
- sub->lifetime = E2K_SUBSCRIPTION_INITIAL_LIFETIME / 2;
- sub->min_interval = min_interval;
- sub->callback = callback;
- sub->user_data = user_data;
-
- if (g_hash_table_lookup_extended (ctx->priv->subscriptions_by_uri,
- uri, &key, &value)) {
- sub_list = value;
- sub_list = g_list_prepend (sub_list, sub);
- g_hash_table_insert (ctx->priv->subscriptions_by_uri,
- key, sub_list);
- } else {
- g_hash_table_insert (ctx->priv->subscriptions_by_uri,
- sub->uri, g_list_prepend (NULL, sub));
- }
-
- renew_subscription (sub);
-}
-
-static void
-free_subscription (E2kSubscription *sub)
-{
- SoupSession *session = sub->ctx->priv->session;
-
- if (sub->renew_timeout)
- g_source_remove (sub->renew_timeout);
- if (sub->renew_msg) {
- soup_session_cancel_message (session, sub->renew_msg,
- SOUP_STATUS_CANCELLED);
- }
- if (sub->poll_timeout)
- g_source_remove (sub->poll_timeout);
- if (sub->notification_timeout)
- g_source_remove (sub->notification_timeout);
- if (sub->poll_msg) {
- soup_session_cancel_message (session, sub->poll_msg,
- SOUP_STATUS_CANCELLED);
- }
- g_free (sub->uri);
- g_free (sub->id);
- g_free (sub);
-}
-
-static void
-unsubscribed (SoupSession *session, SoupMessage *msg, gpointer user_data)
-{
- ;
-}
-
-static void
-unsubscribe_internal (E2kContext *ctx, const gchar *puri, GList *sub_list, gboolean destrying)
-{
- GList *l;
- E2kSubscription *sub;
- SoupMessage *msg;
- GString *subscription_ids = NULL;
- gchar *uri = g_strdup (puri);
- /* puri comes from sub->uri, but we are using it after sub is freed, thus making copy here */
-
- for (l = sub_list; l; l = l->next) {
- sub = l->data;
- if (sub->id) {
- /* do not send messages when destroying, because they are server on idle,
- when the context itself already gone */
- if (!destrying) {
- if (!subscription_ids)
- subscription_ids = g_string_new (sub->id);
- else {
- g_string_append_printf (subscription_ids,
- ",%s", sub->id);
- }
- }
- g_hash_table_remove (ctx->priv->subscriptions_by_id, sub->id);
- }
- free_subscription (sub);
- }
-
- if (subscription_ids) {
- msg = e2k_soup_message_new (ctx, uri, "UNSUBSCRIBE");
- if (msg) {
- soup_message_headers_append (msg->request_headers,
- "Subscription-id",
- subscription_ids->str);
- e2k_context_queue_message (ctx, msg, unsubscribed, NULL);
- }
- g_string_free (subscription_ids, TRUE);
- }
-
- g_free (uri);
-}
-
-/**
- * e2k_context_unsubscribe:
- * @ctx: the context
- * @uri: the URI to unsubscribe from
- *
- * Unsubscribes to all notifications on @ctx for @uri.
- **/
-void
-e2k_context_unsubscribe (E2kContext *ctx, const gchar *uri)
-{
- GList *sub_list;
-
- g_return_if_fail (E2K_IS_CONTEXT (ctx));
-
- sub_list = g_hash_table_lookup (ctx->priv->subscriptions_by_uri, uri);
- g_hash_table_remove (ctx->priv->subscriptions_by_uri, uri);
- unsubscribe_internal (ctx, uri, sub_list, FALSE);
- g_list_free (sub_list);
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __E2K_CONTEXT_H__
-#define __E2K_CONTEXT_H__
-
-#include <libsoup/soup-message.h>
-#include <libsoup/soup-session.h>
-#include <sys/time.h>
-
-#include <glib-object.h>
-
-#include "e2k-types.h"
-#include "e2k-operation.h"
-#include "e2k-http-utils.h"
-#include "e2k-result.h"
-
-G_BEGIN_DECLS
-
-#define E2K_TYPE_CONTEXT (e2k_context_get_type ())
-#define E2K_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E2K_TYPE_CONTEXT, E2kContext))
-#define E2K_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E2K_TYPE_CONTEXT, E2kContextClass))
-#define E2K_IS_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E2K_TYPE_CONTEXT))
-#define E2K_IS_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E2K_TYPE_CONTEXT))
-
-struct _E2kContext {
- GObject parent;
-
- E2kContextPrivate *priv;
-};
-
-struct _E2kContextClass {
- GObjectClass parent_class;
-
- /* signals */
- void (*redirect) (E2kContext *ctx, E2kHTTPStatus status,
- const gchar *old_uri, const gchar *new_uri);
-};
-
-GType e2k_context_get_type (void);
-
-E2kContext *e2k_context_new (const gchar *uri);
-void e2k_context_set_auth (E2kContext *ctx,
- const gchar *username,
- const gchar *domain,
- const gchar *authmech,
- const gchar *password);
-gboolean e2k_context_fba (E2kContext *ctx,
- SoupMessage *failed_msg);
-
-time_t e2k_context_get_last_timestamp (E2kContext *ctx);
-
-typedef gboolean (*E2kContextTestCallback) (E2kContext *ctx,
- const gchar *test_name,
- gpointer user_data);
-
-E2kHTTPStatus e2k_context_get (E2kContext *ctx,
- E2kOperation *op,
- const gchar *uri,
- gchar **content_type,
- SoupBuffer **response);
-E2kHTTPStatus e2k_context_get_owa (E2kContext *ctx,
- E2kOperation *op,
- const gchar *uri,
- gboolean claim_ie,
- SoupBuffer **response);
-
-E2kHTTPStatus e2k_context_put (E2kContext *ctx,
- E2kOperation *op,
- const gchar *uri,
- const gchar *content_type,
- const gchar *body, gint length,
- gchar **repl_uid);
-E2kHTTPStatus e2k_context_put_new (E2kContext *ctx,
- E2kOperation *op,
- const gchar *folder_uri,
- const gchar *object_name,
- E2kContextTestCallback test_callback,
- gpointer user_data,
- const gchar *content_type,
- const gchar *body, gint length,
- gchar **location,
- gchar **repl_uid);
-E2kHTTPStatus e2k_context_post (E2kContext *ctx,
- E2kOperation *op,
- const gchar *uri,
- const gchar *content_type,
- const gchar *body, gint length,
- gchar **location,
- gchar **repl_uid);
-
-E2kHTTPStatus e2k_context_proppatch (E2kContext *ctx,
- E2kOperation *op,
- const gchar *uri,
- E2kProperties *props,
- gboolean create,
- gchar **repl_uid);
-E2kHTTPStatus e2k_context_proppatch_new (E2kContext *ctx,
- E2kOperation *op,
- const gchar *folder_uri,
- const gchar *object_name,
- E2kContextTestCallback test_callback,
- gpointer user_data,
- E2kProperties *props,
- gchar **location,
- gchar **repl_uid);
-E2kResultIter *e2k_context_bproppatch_start (E2kContext *ctx,
- E2kOperation *op,
- const gchar *uri,
- const gchar **hrefs,
- gint nhrefs,
- E2kProperties *props,
- gboolean create);
-
-E2kHTTPStatus e2k_context_propfind (E2kContext *ctx,
- E2kOperation *op,
- const gchar *uri,
- const gchar **props,
- gint nprops,
- E2kResult **results,
- gint *nresults);
-E2kResultIter *e2k_context_bpropfind_start (E2kContext *ctx,
- E2kOperation *op,
- const gchar *uri,
- const gchar **hrefs,
- gint nhrefs,
- const gchar **props,
- gint nprops);
-
-E2kResultIter *e2k_context_search_start (E2kContext *ctx,
- E2kOperation *op,
- const gchar *uri,
- const gchar **props,
- gint nprops,
- E2kRestriction *rn,
- const gchar *orderby,
- gboolean ascending);
-
-E2kHTTPStatus e2k_context_delete (E2kContext *ctx,
- E2kOperation *op,
- const gchar *uri);
-
-E2kResultIter *e2k_context_bdelete_start (E2kContext *ctx,
- E2kOperation *op,
- const gchar *uri,
- const gchar **hrefs,
- gint nhrefs);
-
-E2kHTTPStatus e2k_context_mkcol (E2kContext *ctx,
- E2kOperation *op,
- const gchar *uri,
- E2kProperties *props,
- gchar **permanent_url);
-
-E2kResultIter *e2k_context_transfer_start (E2kContext *ctx,
- E2kOperation *op,
- const gchar *source_folder,
- const gchar *dest_folder,
- GPtrArray *source_hrefs,
- gboolean delete_originals);
-E2kHTTPStatus e2k_context_transfer_dir (E2kContext *ctx,
- E2kOperation *op,
- const gchar *source_href,
- const gchar *dest_href,
- gboolean delete_original,
- gchar **permanent_url);
-
-/* Subscriptions */
-typedef enum {
- E2K_CONTEXT_OBJECT_CHANGED,
- E2K_CONTEXT_OBJECT_ADDED,
- E2K_CONTEXT_OBJECT_REMOVED,
- E2K_CONTEXT_OBJECT_MOVED
-} E2kContextChangeType;
-
-typedef void (*E2kContextChangeCallback) (E2kContext *ctx,
- const gchar *uri,
- E2kContextChangeType type,
- gpointer user_data);
-
-void e2k_context_subscribe (E2kContext *ctx,
- const gchar *uri,
- E2kContextChangeType type,
- gint min_interval,
- E2kContextChangeCallback callback,
- gpointer user_data);
-void e2k_context_unsubscribe (E2kContext *ctx,
- const gchar *uri);
-
-/*
- * Utility functions
- */
-SoupMessage *e2k_soup_message_new (E2kContext *ctx,
- const gchar *uri,
- const gchar *method);
-SoupMessage *e2k_soup_message_new_full (E2kContext *ctx,
- const gchar *uri,
- const gchar *method,
- const gchar *content_type,
- SoupMemoryUse use,
- const gchar *body,
- gsize length);
-void e2k_context_queue_message (E2kContext *ctx,
- SoupMessage *msg,
- SoupSessionCallback callback,
- gpointer user_data);
-E2kHTTPStatus e2k_context_send_message (E2kContext *ctx,
- E2kOperation *op,
- SoupMessage *msg);
-
-G_END_DECLS
-
-#endif /* __E2K_CONTEXT_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2002-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* e2k-freebusy.c: routines for manipulating Exchange free/busy data */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e2k-freebusy.h"
-#include "e2k-propnames.h"
-#include "e2k-restriction.h"
-#include "e2k-uri.h"
-#include "e2k-utils.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <libedataserver/e-time-utils.h>
-
-/**
- * e2k_freebusy_destroy:
- * @fb: the #E2kFreebusy
- *
- * Frees @fb and all associated data.
- **/
-void
-e2k_freebusy_destroy (E2kFreebusy *fb)
-{
- gint i;
-
- g_object_unref (fb->ctx);
- for (i = 0; i < E2K_BUSYSTATUS_MAX; i++)
- g_array_free (fb->events[i], TRUE);
- g_free (fb->uri);
- g_free (fb->dn);
- g_free (fb);
-}
-
-static gchar *
-fb_uri_for_dn (const gchar *public_uri, const gchar *dn)
-{
- gchar *uri, *div, *org;
- GString *str;
-
- for (div = strchr (dn, '/'); div; div = strchr (div + 1, '/')) {
- if (!g_ascii_strncasecmp (div, "/cn=", 4))
- break;
- }
- g_return_val_if_fail (div, NULL);
-
- org = g_strndup (dn, div - dn);
-
- str = g_string_new (public_uri);
- g_string_append (str, "/NON_IPM_SUBTREE/SCHEDULE%2B%20FREE%20BUSY/EX:");
- e2k_uri_append_encoded (str, org, TRUE, NULL);
- g_string_append (str, "/USER-");
- e2k_uri_append_encoded (str, div, TRUE, NULL);
- g_string_append (str, ".EML");
-
- uri = str->str;
- g_string_free (str, FALSE);
- g_free (org);
-
- return uri;
-}
-
-static void
-merge_events (GArray *events)
-{
- E2kFreebusyEvent evt, evt2;
- gint i;
-
- if (events->len < 2)
- return;
-
- evt = g_array_index (events, E2kFreebusyEvent, 0);
- for (i = 1; i < events->len; i++) {
- evt2 = g_array_index (events, E2kFreebusyEvent, i);
- if (evt.end >= evt2.start) {
- if (evt2.end > evt.end)
- evt.end = evt2.end;
- g_array_remove_index (events, i--);
- } else
- evt = evt2;
- }
-}
-
-static void
-add_data_for_status (E2kFreebusy *fb, GPtrArray *monthyears, GPtrArray *fbdatas, GArray *events)
-{
- E2kFreebusyEvent evt;
- gint i, monthyear;
- GByteArray *fbdata;
- guchar *p;
- struct tm tm;
-
- if (!monthyears || !fbdatas)
- return;
-
- memset (&tm, 0, sizeof (tm));
- for (i = 0; i < monthyears->len && i < fbdatas->len; i++) {
- monthyear = atoi (monthyears->pdata[i]);
- fbdata = fbdatas->pdata[i];
-
- tm.tm_year = (monthyear >> 4) - 1900;
- tm.tm_mon = (monthyear & 0xF) - 1;
-
- for (p = fbdata->data; p + 3 < fbdata->data + fbdata->len; p += 4) {
- tm.tm_mday = 1;
- tm.tm_hour = 0;
- tm.tm_min = p[0] + p[1] * 256;
- evt.start = e_mktime_utc (&tm);
-
- tm.tm_mday = 1;
- tm.tm_hour = 0;
- tm.tm_min = p[2] + p[3] * 256;
- evt.end = e_mktime_utc (&tm);
-
- g_array_append_val (events, evt);
- }
- }
- merge_events (events);
-}
-
-static const gchar *public_freebusy_props[] = {
- PR_FREEBUSY_START_RANGE,
- PR_FREEBUSY_END_RANGE,
- PR_FREEBUSY_ALL_MONTHS,
- PR_FREEBUSY_ALL_EVENTS,
- PR_FREEBUSY_TENTATIVE_MONTHS,
- PR_FREEBUSY_TENTATIVE_EVENTS,
- PR_FREEBUSY_BUSY_MONTHS,
- PR_FREEBUSY_BUSY_EVENTS,
- PR_FREEBUSY_OOF_MONTHS,
- PR_FREEBUSY_OOF_EVENTS
-};
-static const gint n_public_freebusy_props = sizeof (public_freebusy_props) / sizeof (public_freebusy_props[0]);
-
-/**
- * e2k_freebusy_new:
- * @ctx: an #E2kContext
- * @public_uri: the URI of the MAPI public folder tree
- * @dn: the legacy Exchange DN of a user
- *
- * Creates a new #E2kFreebusy, filled in with information from the
- * indicated user's published free/busy information. This uses the
- * public free/busy folder; the caller does not need permission to
- * access the @dn's Calendar.
- *
- * Note that currently, this will fail and return %NULL if the user
- * does not already have free/busy information stored on the server.
- *
- * Return value: the freebusy information
- **/
-E2kFreebusy *
-e2k_freebusy_new (E2kContext *ctx, const gchar *public_uri, const gchar *dn)
-{
- E2kFreebusy *fb;
- gchar *uri, *time;
- GPtrArray *monthyears, *fbdatas;
- E2kHTTPStatus status;
- E2kResult *results;
- gint nresults = 0, i;
-
- uri = fb_uri_for_dn (public_uri, dn);
- g_return_val_if_fail (uri, NULL);
-
- status = e2k_context_propfind (ctx, NULL, uri,
- public_freebusy_props,
- n_public_freebusy_props,
- &results, &nresults);
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status) || nresults == 0) {
- /* FIXME: create it */
- g_free (uri);
- return NULL;
- }
-
- fb = g_new0 (E2kFreebusy, 1);
- fb->uri = uri;
- fb->dn = g_strdup (dn);
- fb->ctx = ctx;
- g_object_ref (ctx);
-
- for (i = 0; i < E2K_BUSYSTATUS_MAX; i++)
- fb->events[i] = g_array_new (FALSE, FALSE, sizeof (E2kFreebusyEvent));
-
- time = e2k_properties_get_prop (
- results[0].props, PR_FREEBUSY_START_RANGE);
- fb->start = time ? e2k_systime_to_time_t (strtol (time, NULL, 10)) : 0;
- time = e2k_properties_get_prop (
- results[0].props, PR_FREEBUSY_END_RANGE);
- fb->end = time ? e2k_systime_to_time_t (strtol (time, NULL, 10)) : 0;
-
- monthyears = e2k_properties_get_prop (
- results[0].props, PR_FREEBUSY_ALL_MONTHS);
- fbdatas = e2k_properties_get_prop (
- results[0].props, PR_FREEBUSY_ALL_EVENTS);
- add_data_for_status (fb, monthyears, fbdatas, fb->events[E2K_BUSYSTATUS_ALL]);
-
- monthyears = e2k_properties_get_prop (
- results[0].props, PR_FREEBUSY_TENTATIVE_MONTHS);
- fbdatas = e2k_properties_get_prop (
- results[0].props, PR_FREEBUSY_TENTATIVE_EVENTS);
- add_data_for_status (fb, monthyears, fbdatas, fb->events[E2K_BUSYSTATUS_TENTATIVE]);
-
- monthyears = e2k_properties_get_prop (
- results[0].props, PR_FREEBUSY_BUSY_MONTHS);
- fbdatas = e2k_properties_get_prop (
- results[0].props, PR_FREEBUSY_BUSY_EVENTS);
- add_data_for_status (fb, monthyears, fbdatas, fb->events[E2K_BUSYSTATUS_BUSY]);
-
- monthyears = e2k_properties_get_prop (
- results[0].props, PR_FREEBUSY_OOF_MONTHS);
- fbdatas = e2k_properties_get_prop (
- results[0].props, PR_FREEBUSY_OOF_EVENTS);
- add_data_for_status (fb, monthyears, fbdatas, fb->events[E2K_BUSYSTATUS_OOF]);
-
- e2k_results_free (results, nresults);
- return fb;
-}
-
-/**
- * e2k_freebusy_reset:
- * @fb: an #E2kFreebusy
- * @nmonths: the number of months of info @fb will store
- *
- * Clears all existing data in @fb and resets the start and end times
- * to a span of @nmonths around the current date.
- **/
-void
-e2k_freebusy_reset (E2kFreebusy *fb, gint nmonths)
-{
- time_t now;
- struct tm tm;
- gint i;
-
- /* Remove all existing events */
- for (i = 0; i < E2K_BUSYSTATUS_MAX; i++)
- g_array_set_size (fb->events[i], 0);
-
- /* Set the start and end times appropriately: from the beginning
- * of the current month until nmonths later.
- * FIXME: Use default timezone, not local time.
- */
- now = time (NULL);
- tm = *gmtime (&now);
- tm.tm_mday = 1;
- tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
-
- tm.tm_isdst = -1;
- fb->start = mktime (&tm);
-
- tm.tm_mon += nmonths;
- tm.tm_isdst = -1;
- fb->end = mktime (&tm);
-}
-
-/**
- * e2k_freebusy_add_interval:
- * @fb: an #E2kFreebusy
- * @busystatus: the busy status of the interval
- * @start: the start of the interval
- * @end: the end of the interval
- *
- * This adds an interval of type @busystatus to @fb.
- **/
-void
-e2k_freebusy_add_interval (E2kFreebusy *fb, E2kBusyStatus busystatus,
- time_t start, time_t end)
-{
- E2kFreebusyEvent evt, *events;
- gint i;
-
- if (busystatus == E2K_BUSYSTATUS_FREE)
- return;
-
- /* Clip to the fb's range */
- if (start < fb->start)
- start = fb->start;
- if (end > fb->end)
- end = fb->end;
- if (end <= start)
- return;
-
- events = (E2kFreebusyEvent *)(fb->events[busystatus]->data);
-
- for (i = 0; i < fb->events[busystatus]->len; i++) {
- if (events[i].end >= start)
- break;
- }
-
- evt.start = start;
- evt.end = end;
-
- if (i == fb->events[busystatus]->len)
- g_array_append_val (fb->events[busystatus], evt);
- else {
- /* events[i] is the first event that is not completely
- * before evt, meaning it is either completely after it,
- * or they overlap/abut.
- */
- if (events[i].start > end) {
- /* No overlap. Insert evt before events[i]. */
- g_array_insert_val (fb->events[busystatus], i, evt);
- } else {
- /* They overlap or abut. Merge them. */
- events[i].start = MIN (events[i].start, start);
- events[i].end = MAX (events[i].end, end);
- }
- }
-}
-
-/**
- * e2k_freebusy_clear_interval:
- * @fb: an #E2kFreebusy
- * @start: the start of the interval
- * @end: the end of the interval
- *
- * This removes any events between @start and @end in @fb.
- **/
-void
-e2k_freebusy_clear_interval (E2kFreebusy *fb, time_t start, time_t end)
-{
- E2kFreebusyEvent *evt;
- gint busystatus, i;
-
- for (busystatus = 0; busystatus < E2K_BUSYSTATUS_MAX; busystatus++) {
- for (i = 0; i < fb->events[busystatus]->len; i++) {
- evt = &g_array_index (fb->events[busystatus], E2kFreebusyEvent, i);
- if (evt->end < start || evt->start > end)
- continue;
-
- /* evt overlaps the interval. Truncate or
- * remove it.
- */
-
- if (evt->start > start /* && evt->start <= end */)
- evt->start = end;
- if (evt->end < end /* && evt->end >= start */)
- evt->end = start;
-
- if (evt->start >= evt->end)
- g_array_remove_index (fb->events[busystatus], i--);
- }
- }
-}
-
-static const gchar *freebusy_props[] = {
- E2K_PR_CALENDAR_DTSTART,
- E2K_PR_CALENDAR_DTEND,
- E2K_PR_CALENDAR_BUSY_STATUS
-};
-static const gint n_freebusy_props = sizeof (freebusy_props) / sizeof (freebusy_props[0]);
-
-/**
- * e2k_freebusy_add_from_calendar_uri:
- * @fb: an #E2kFreebusy
- * @uri: the URI of a calendar folder
- * @start_tt: start of the range to add
- * @end_tt: end of the range to add
- *
- * This queries the server for events between @start_tt and @end_tt in
- * the calendar at @uri (which the caller must have permission to
- * read) and adds them @fb. Any previously-existing events during that
- * range are removed.
- *
- * Return value: an HTTP status code.
- **/
-E2kHTTPStatus
-e2k_freebusy_add_from_calendar_uri (E2kFreebusy *fb, const gchar *uri,
- time_t start_tt, time_t end_tt)
-{
- gchar *start, *end, *busystatus;
- E2kBusyStatus busy;
- E2kRestriction *rn;
- E2kResultIter *iter;
- E2kResult *result;
-
- e2k_freebusy_clear_interval (fb, start_tt, end_tt);
-
- start = e2k_make_timestamp (start_tt);
- end = e2k_make_timestamp (end_tt);
-
- rn = e2k_restriction_andv (
- e2k_restriction_prop_string (E2K_PR_DAV_CONTENT_CLASS,
- E2K_RELOP_EQ,
- "urn:content-classes:appointment"),
- e2k_restriction_prop_date (E2K_PR_CALENDAR_DTEND,
- E2K_RELOP_GT, start),
- e2k_restriction_prop_date (E2K_PR_CALENDAR_DTSTART,
- E2K_RELOP_LT, end),
- e2k_restriction_prop_string (E2K_PR_CALENDAR_BUSY_STATUS,
- E2K_RELOP_NE, "FREE"),
- NULL);
-
- iter = e2k_context_search_start (fb->ctx, NULL, uri,
- freebusy_props, n_freebusy_props,
- rn, NULL, TRUE);
- e2k_restriction_unref (rn);
- g_free (start);
- g_free (end);
-
- while ((result = e2k_result_iter_next (iter))) {
- start = e2k_properties_get_prop (result->props,
- E2K_PR_CALENDAR_DTSTART);
- end = e2k_properties_get_prop (result->props,
- E2K_PR_CALENDAR_DTEND);
- busystatus = e2k_properties_get_prop (result->props,
- E2K_PR_CALENDAR_BUSY_STATUS);
- if (!start || !end || !busystatus)
- continue;
-
- if (!strcmp (busystatus, "TENTATIVE"))
- busy = E2K_BUSYSTATUS_TENTATIVE;
- else if (!strcmp (busystatus, "OUTOFOFFICE"))
- busy = E2K_BUSYSTATUS_OOF;
- else
- busy = E2K_BUSYSTATUS_BUSY;
-
- e2k_freebusy_add_interval (fb, busy,
- e2k_parse_timestamp (start),
- e2k_parse_timestamp (end));
-
- }
-
- return e2k_result_iter_free (iter);
-}
-
-static void
-add_events (GArray *events_array, E2kProperties *props,
- const gchar *month_list_prop, const gchar *data_list_prop)
-{
- E2kFreebusyEvent *events = (E2kFreebusyEvent *)events_array->data;
- gint i, evt_start, evt_end, monthyear;
- struct tm start_tm, end_tm;
- time_t start, end;
- GPtrArray *monthyears, *datas;
- GByteArray *data;
- gchar startend[4];
-
- if (!events_array->len) {
- e2k_properties_remove (props, month_list_prop);
- e2k_properties_remove (props, data_list_prop);
- return;
- }
-
- monthyears = g_ptr_array_new ();
- start_tm = *gmtime (&events[0].start);
- end_tm = *gmtime (&events[events_array->len - 1].end);
- while (start_tm.tm_year <= end_tm.tm_year ||
- start_tm.tm_mon <= end_tm.tm_mon) {
- monthyear = ((start_tm.tm_year + 1900) * 16) +
- (start_tm.tm_mon + 1);
- g_ptr_array_add (monthyears, g_strdup_printf ("%d", monthyear));
-
- start_tm.tm_mon++;
- if (start_tm.tm_mon == 12) {
- start_tm.tm_year++;
- start_tm.tm_mon = 0;
- }
- }
- e2k_properties_set_int_array (props, month_list_prop, monthyears);
-
- datas = g_ptr_array_new ();
- start = events[0].start;
- i = 0;
- while (i < events_array->len) {
- start_tm = *gmtime (&start);
- start_tm.tm_mon++;
- end = e_mktime_utc (&start_tm);
-
- data = g_byte_array_new ();
- while (i << events_array->len &&
- events[i].end > start && events[i].start < end) {
- if (events[i].start < start)
- evt_start = 0;
- else
- evt_start = (events[i].start - start) / 60;
- if (events[i].end > end)
- evt_end = (end - start) / 60;
- else
- evt_end = (events[i].end - start) / 60;
-
- startend[0] = evt_start & 0xFF;
- startend[1] = evt_start >> 8;
- startend[2] = evt_end & 0xFF;
- startend[3] = evt_end >> 8;
- g_byte_array_append (data, (guint8 *) startend, 4);
- i++;
- }
-
- g_ptr_array_add (datas, data);
- start = end;
- }
- e2k_properties_set_binary_array (props, data_list_prop, datas);
-}
-
-/**
- * e2k_freebusy_save:
- * @fb: an #E2kFreebusy
- *
- * Saves the data in @fb back to the server.
- *
- * Return value: a libsoup or HTTP status code
- **/
-E2kHTTPStatus
-e2k_freebusy_save (E2kFreebusy *fb)
-{
- E2kProperties *props;
- gchar *timestamp;
- E2kHTTPStatus status;
-
- props = e2k_properties_new ();
- e2k_properties_set_string (props, E2K_PR_EXCHANGE_MESSAGE_CLASS,
- g_strdup ("IPM.Post"));
- e2k_properties_set_int (props, PR_FREEBUSY_START_RANGE, fb->start);
- e2k_properties_set_int (props, PR_FREEBUSY_END_RANGE, fb->end);
- e2k_properties_set_string (props, PR_FREEBUSY_EMAIL_ADDRESS,
- g_strdup (fb->dn));
-
- add_events (fb->events[E2K_BUSYSTATUS_ALL], props,
- PR_FREEBUSY_ALL_MONTHS, PR_FREEBUSY_ALL_EVENTS);
- add_events (fb->events[E2K_BUSYSTATUS_TENTATIVE], props,
- PR_FREEBUSY_TENTATIVE_MONTHS, PR_FREEBUSY_TENTATIVE_EVENTS);
- add_events (fb->events[E2K_BUSYSTATUS_BUSY], props,
- PR_FREEBUSY_BUSY_MONTHS, PR_FREEBUSY_BUSY_EVENTS);
- add_events (fb->events[E2K_BUSYSTATUS_OOF], props,
- PR_FREEBUSY_OOF_MONTHS, PR_FREEBUSY_OOF_EVENTS);
-
- timestamp = e2k_make_timestamp (e2k_context_get_last_timestamp (fb->ctx));
- e2k_properties_set_date (props, PR_FREEBUSY_LAST_MODIFIED, timestamp);
-
- status = e2k_context_proppatch (fb->ctx, NULL, fb->uri, props,
- TRUE, NULL);
- e2k_properties_free (props);
-
- return status;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2002-2004 Novell, Inc. */
-
-#ifndef __E2K_FREEBUSY_H__
-#define __E2K_FREEBUSY_H__
-
-#include "e2k-context.h"
-
-G_BEGIN_DECLS
-
-typedef enum {
- E2K_BUSYSTATUS_FREE = 0,
- E2K_BUSYSTATUS_TENTATIVE = 1,
- E2K_BUSYSTATUS_BUSY = 2,
- E2K_BUSYSTATUS_OOF = 3,
-
- E2K_BUSYSTATUS_MAX,
-
- /* Alias for internal use */
- E2K_BUSYSTATUS_ALL = E2K_BUSYSTATUS_FREE
-} E2kBusyStatus;
-
-typedef struct {
- /*< private >*/
- time_t start, end;
-} E2kFreebusyEvent;
-
-typedef struct {
- /*< private >*/
- E2kContext *ctx;
- gchar *dn, *uri;
-
- time_t start, end;
-
- GArray *events[E2K_BUSYSTATUS_MAX];
-} E2kFreebusy;
-
-E2kFreebusy *e2k_freebusy_new (E2kContext *ctx,
- const gchar *public_uri,
- const gchar *dn);
-
-void e2k_freebusy_reset (E2kFreebusy *fb,
- gint nmonths);
-
-void e2k_freebusy_add_interval (E2kFreebusy *fb,
- E2kBusyStatus busystatus,
- time_t start,
- time_t end);
-void e2k_freebusy_clear_interval (E2kFreebusy *fb,
- time_t start,
- time_t end);
-
-E2kHTTPStatus e2k_freebusy_add_from_calendar_uri (E2kFreebusy *fb,
- const gchar *uri,
- time_t start_tt,
- time_t end_tt);
-
-E2kHTTPStatus e2k_freebusy_save (E2kFreebusy *fb);
-
-void e2k_freebusy_destroy (E2kFreebusy *fb);
-
-G_END_DECLS
-
-#endif /* __E2K_FREEBUSY_H__ */
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __E2K_GLOBAL_CATALOG_LDAP_H__
-#define __E2K_GLOBAL_CATALOG_LDAP_H__
-
-#include <glib.h>
-#ifndef G_OS_WIN32
-#include <ldap.h>
-#else
-#define interface windows_interface
-#include <windows.h>
-#undef interface
-#include <winldap.h>
-#define LDAP_ROOT_DSE ""
-#define LDAP_RANGE(n,x,y) (((x) <= (n)) && ((n) <= (y)))
-#define LDAP_NAME_ERROR(n) LDAP_RANGE((n),0x20,0x24) /* 32-34,36 */
-#define ldap_msgtype(lm) (lm)->lm_msgtype
-#define ldap_msgid(lm) (lm)->lm_msgid
-#endif
-#include "e2k-global-catalog.h"
-
-G_BEGIN_DECLS
-
-LDAP *e2k_global_catalog_get_ldap (E2kGlobalCatalog *gc,
- E2kOperation *op,
- gint *ldap_error);
-
-G_END_DECLS
-
-#endif /* __E2K_GLOBAL_CATALOG_LDAP_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2001-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "e2k-global-catalog-ldap.h"
-#include "e2k-sid.h"
-#include "e2k-utils.h"
-
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-
-#ifdef HAVE_LDAP_NTLM_BIND
-#include "xntlm.h"
-#endif
-
-#ifdef E2K_DEBUG
-static gboolean e2k_gc_debug = FALSE;
-#define E2K_GC_DEBUG_MSG(x) if (e2k_gc_debug) printf x
-#else
-#define E2K_GC_DEBUG_MSG(x)
-#endif
-
-struct _E2kGlobalCatalogPrivate {
- GMutex *ldap_lock;
- LDAP *ldap;
-
- GPtrArray *entries;
- GHashTable *entry_cache, *server_cache;
-
- gchar *server, *user, *nt_domain, *password;
- E2kAutoconfigGalAuthPref auth;
-};
-
-#define PARENT_TYPE G_TYPE_OBJECT
-static GObjectClass *parent_class = NULL;
-
-static void finalize (GObject *);
-static gint get_gc_connection (E2kGlobalCatalog *gc, E2kOperation *op);
-
-static void
-class_init (GObjectClass *object_class)
-{
-#ifdef E2K_DEBUG
- gchar *e2k_debug = getenv ("E2K_DEBUG");
-
- if (e2k_debug && atoi (e2k_debug) > 3)
- e2k_gc_debug = TRUE;
-#endif
-
- /* For some reason, sasl_client_init (called by ldap_init
- * below) takes a *really* long time to scan the sasl modules
- * when running under gdb. We're not using sasl anyway, so...
- */
- g_setenv ("SASL_PATH", "", TRUE);
-
- parent_class = g_type_class_ref (PARENT_TYPE);
-
- /* virtual method override */
- object_class->finalize = finalize;
-}
-
-static void
-init (GObject *object)
-{
- E2kGlobalCatalog *gc = E2K_GLOBAL_CATALOG (object);
-
- gc->priv = g_new0 (E2kGlobalCatalogPrivate, 1);
- gc->priv->ldap_lock = g_mutex_new ();
- gc->priv->entries = g_ptr_array_new ();
- gc->priv->entry_cache = g_hash_table_new (e2k_ascii_strcase_hash,
- e2k_ascii_strcase_equal);
- gc->priv->server_cache = g_hash_table_new (g_str_hash, g_str_equal);
-}
-
-static void
-free_entry (E2kGlobalCatalogEntry *entry)
-{
- gint i;
-
- g_free (entry->dn);
- g_free (entry->display_name);
-
- if (entry->sid)
- g_object_unref (entry->sid);
-
- g_free (entry->email);
- g_free (entry->mailbox);
-
- if (entry->delegates) {
- for (i = 0; i < entry->delegates->len; i++)
- g_free (entry->delegates->pdata[i]);
- g_ptr_array_free (entry->delegates, TRUE);
- }
- if (entry->delegators) {
- for (i = 0; i < entry->delegators->len; i++)
- g_free (entry->delegators->pdata[i]);
- g_ptr_array_free (entry->delegators, TRUE);
- }
-
- g_free (entry);
-}
-
-static void
-free_server (gpointer key, gpointer value, gpointer data)
-{
- g_free (key);
- g_free (value);
-}
-
-static void
-finalize (GObject *object)
-{
- E2kGlobalCatalog *gc = E2K_GLOBAL_CATALOG (object);
- gint i;
-
- if (gc->priv) {
- if (gc->priv->ldap)
- ldap_unbind (gc->priv->ldap);
-
- for (i = 0; i < gc->priv->entries->len; i++)
- free_entry (gc->priv->entries->pdata[i]);
- g_ptr_array_free (gc->priv->entries, TRUE);
-
- g_hash_table_foreach (gc->priv->server_cache, free_server, NULL);
- g_hash_table_destroy (gc->priv->server_cache);
-
- g_free (gc->priv->server);
- g_free (gc->priv->user);
- g_free (gc->priv->nt_domain);
- if (gc->priv->password) {
- memset (gc->priv->password, 0, strlen (gc->priv->password));
- g_free (gc->priv->password);
- }
-
- g_mutex_free (gc->priv->ldap_lock);
-
- g_free (gc->priv);
- gc->priv = NULL;
- }
-
- g_free (gc->domain);
- gc->domain = NULL;
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-E2K_MAKE_TYPE (e2k_global_catalog, E2kGlobalCatalog, class_init, init, PARENT_TYPE)
-
-static gint
-gc_ldap_result (LDAP *ldap, E2kOperation *op,
- gint msgid, LDAPMessage **msg)
-{
- struct timeval tv;
- gint status, ldap_error;
-
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- *msg = NULL;
- do {
- status = ldap_result (ldap, msgid, TRUE, &tv, msg);
- if (status == -1) {
- ldap_get_option (ldap, LDAP_OPT_ERROR_NUMBER,
- &ldap_error);
- return ldap_error;
- }
- } while (status == 0 && !e2k_operation_is_cancelled (op));
-
- if (e2k_operation_is_cancelled (op)) {
- ldap_abandon (ldap, msgid);
- return LDAP_USER_CANCELLED;
- } else
- return LDAP_SUCCESS;
-}
-
-static gint
-gc_search (E2kGlobalCatalog *gc, E2kOperation *op,
- const gchar *base, gint scope, const gchar *filter,
- const gchar **attrs, LDAPMessage **msg)
-{
- gint ldap_error, msgid, try;
-
- for (try = 0; try < 2; try++) {
- ldap_error = get_gc_connection (gc, op);
- if (ldap_error != LDAP_SUCCESS)
- return ldap_error;
- ldap_error = ldap_search_ext (gc->priv->ldap, base, scope,
- filter, (gchar **)attrs,
- FALSE, NULL, NULL, NULL, 0,
- &msgid);
- if (ldap_error == LDAP_SERVER_DOWN)
- continue;
- else if (ldap_error != LDAP_SUCCESS)
- return ldap_error;
-
- ldap_error = gc_ldap_result (gc->priv->ldap, op, msgid, msg);
- if (ldap_error == LDAP_SERVER_DOWN)
- continue;
- else if (ldap_error != LDAP_SUCCESS)
- return ldap_error;
-
- return LDAP_SUCCESS;
- }
-
- return LDAP_SERVER_DOWN;
-}
-
-#ifdef HAVE_LDAP_NTLM_BIND
-static gint
-ntlm_bind (E2kGlobalCatalog *gc, E2kOperation *op, LDAP *ldap)
-{
- LDAPMessage *msg;
- gint ldap_error, msgid, err;
- gchar *nonce, *default_domain;
- GByteArray *ba;
- struct berval ldap_buf;
-
- /* Create and send NTLM request */
- ba = xntlm_negotiate ();
- ldap_buf.bv_len = ba->len;
- ldap_buf.bv_val = (gchar *) ba->data;
- ldap_error = ldap_ntlm_bind (ldap, "NTLM", LDAP_AUTH_NTLM_REQUEST,
- &ldap_buf, NULL, NULL, &msgid);
- g_byte_array_free (ba, TRUE);
- if (ldap_error != LDAP_SUCCESS) {
- E2K_GC_DEBUG_MSG(("GC: Failure sending first NTLM bind message: 0x%02x\n", ldap_error));
- return ldap_error;
- }
-
- /* Extract challenge */
- ldap_error = gc_ldap_result (ldap, op, msgid, &msg);
- if (ldap_error != LDAP_SUCCESS) {
- E2K_GC_DEBUG_MSG(("GC: Could not parse first NTLM bind response\n"));
- return ldap_error;
- }
- ldap_error = ldap_parse_ntlm_bind_result (ldap, msg, &ldap_buf);
- ldap_msgfree (msg);
- if (ldap_error != LDAP_SUCCESS) {
- E2K_GC_DEBUG_MSG(("GC: Could not parse NTLM bind response: 0x%02x\n", ldap_error));
- return ldap_error;
- }
-
- if (!xntlm_parse_challenge (ldap_buf.bv_val, ldap_buf.bv_len,
- &nonce, &default_domain,
- &gc->domain)) {
- E2K_GC_DEBUG_MSG(("GC: Could not find nonce in NTLM bind response\n"));
- ber_memfree (ldap_buf.bv_val);
-
- return LDAP_DECODING_ERROR;
- }
- ber_memfree (ldap_buf.bv_val);
-
- /* Create and send response */
- ba = xntlm_authenticate (nonce, gc->priv->nt_domain ? gc->priv->nt_domain : default_domain,
- gc->priv->user, gc->priv->password, NULL);
- ldap_buf.bv_len = ba->len;
- ldap_buf.bv_val = (gchar *) ba->data;
- ldap_error = ldap_ntlm_bind (ldap, "NTLM", LDAP_AUTH_NTLM_RESPONSE,
- &ldap_buf, NULL, NULL, &msgid);
- g_byte_array_free (ba, TRUE);
- g_free (nonce);
- g_free (default_domain);
- if (ldap_error != LDAP_SUCCESS) {
- E2K_GC_DEBUG_MSG(("GC: Failure sending second NTLM bind message: 0x%02x\n", ldap_error));
- return ldap_error;
- }
-
- /* And get the final result */
- ldap_error = gc_ldap_result (ldap, op, msgid, &msg);
- if (ldap_error != LDAP_SUCCESS) {
- E2K_GC_DEBUG_MSG(("GC: Could not parse second NTLM bind response\n"));
- return ldap_error;
- }
- ldap_error = ldap_parse_result (ldap, msg, &err, NULL, NULL,
- NULL, NULL, TRUE);
- if (ldap_error != LDAP_SUCCESS) {
- E2K_GC_DEBUG_MSG(("GC: Could not parse second NTLM bind response: 0x%02x\n", ldap_error));
- return ldap_error;
- }
-
- return err;
-}
-#endif
-
-static gint
-connect_ldap (E2kGlobalCatalog *gc, E2kOperation *op, LDAP *ldap)
-{
- gint ldap_error;
- gchar *nt_name;
-#ifdef G_OS_WIN32
- SEC_WINNT_AUTH_IDENTITY_W auth;
-#endif
-
- /* authenticate */
-#ifdef HAVE_LDAP_NTLM_BIND
- if ((gc->priv->auth == E2K_AUTOCONFIG_USE_GAL_DEFAULT || gc->priv->auth == E2K_AUTOCONFIG_USE_GAL_NTLM)) {
- ldap_error = ntlm_bind (gc, op, ldap);
- if (ldap_error == LDAP_SUCCESS) {
- E2K_GC_DEBUG_MSG(("GC: connected via NTLM\n\n"));
- return LDAP_SUCCESS;
- } else if (gc->priv->auth == E2K_AUTOCONFIG_USE_GAL_NTLM) {
- E2K_GC_DEBUG_MSG(("GC: user setup NTLM, but it failed 0x%02x\n", ldap_error));
- return ldap_error;
- }
- }
-#endif
-
- if (gc->priv->auth == E2K_AUTOCONFIG_USE_GAL_NTLM) {
- E2K_GC_DEBUG_MSG(("GC: user setup NTLM, but we do not have it\n"));
- /* a little hack */
- return LDAP_AUTH_METHOD_NOT_SUPPORTED;
- }
-
- nt_name = gc->priv->nt_domain ?
- g_strdup_printf ("%s\\%s", gc->priv->nt_domain, gc->priv->user) :
- g_strdup (gc->priv->user);
-#ifndef G_OS_WIN32
- ldap_error = ldap_simple_bind_s (ldap, nt_name, gc->priv->password);
-#else
- auth.User = g_utf8_to_utf16 (gc->priv->user, -1, NULL, NULL, NULL);
- auth.UserLength = wcslen (auth.User);
- auth.Domain = gc->priv->nt_domain ?
- g_utf8_to_utf16 (gc->priv->nt_domain, -1, NULL, NULL, NULL) :
- g_utf8_to_utf16 ("", -1, NULL, NULL, NULL);
- auth.DomainLength = wcslen (auth.Domain);
- auth.Password = g_utf8_to_utf16 (gc->priv->password, -1, NULL, NULL, NULL);
- auth.PasswordLength = wcslen (auth.Password);
- auth.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
- ldap_error = ldap_bind_s (ldap, nt_name, &auth, gc->priv->auth == E2K_AUTOCONFIG_USE_GAL_BASIC ? LDAP_AUTH_SIMPLE : LDAP_AUTH_NTLM);
- g_free (auth.Password);
- g_free (auth.Domain);
- g_free (auth.User);
-#endif
- g_free (nt_name);
-
- if (ldap_error != LDAP_SUCCESS)
- g_warning ("LDAP authentication failed (0x%02x (%s))", ldap_error, ldap_err2string (ldap_error) ? ldap_err2string (ldap_error) : "Unknown error");
- else
- E2K_GC_DEBUG_MSG(("GC: connected\n\n"));
-
- return ldap_error;
-}
-
-static gint
-get_ldap_connection (E2kGlobalCatalog *gc, E2kOperation *op,
- const gchar *server, gint port,
- LDAP **ldap)
-{
- gint ldap_opt, ldap_error;
-
- E2K_GC_DEBUG_MSG(("\nGC: Connecting to ldap://%s:%d/\n", server, port));
-
- *ldap = ldap_init (server, port);
- if (!*ldap) {
- E2K_GC_DEBUG_MSG(("GC: failed\n\n"));
- g_warning ("Could not connect to ldap://%s:%d/",
- server, port);
- return LDAP_SERVER_DOWN;
- }
-
- /* Set options */
- ldap_opt = LDAP_DEREF_ALWAYS;
- ldap_set_option (*ldap, LDAP_OPT_DEREF, &ldap_opt);
- ldap_opt = gc->response_limit;
- ldap_set_option (*ldap, LDAP_OPT_SIZELIMIT, &ldap_opt);
- ldap_opt = LDAP_VERSION3;
- ldap_set_option (*ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_opt);
-
- ldap_error = connect_ldap (gc, op, *ldap);
- if (ldap_error != LDAP_SUCCESS) {
- ldap_unbind (*ldap);
- *ldap = NULL;
- }
- return ldap_error;
-}
-
-static gint
-get_gc_connection (E2kGlobalCatalog *gc, E2kOperation *op)
-{
- gint err;
-
- if (gc->priv->ldap) {
- ldap_get_option (gc->priv->ldap, LDAP_OPT_ERROR_NUMBER, &err);
- if (err != LDAP_SERVER_DOWN)
- return LDAP_SUCCESS;
-
- return connect_ldap (gc, op, gc->priv->ldap);
- } else {
- return get_ldap_connection (gc, op,
- gc->priv->server, 3268,
- &gc->priv->ldap);
- }
-}
-
-/**
- * e2k_global_catalog_get_ldap:
- * @gc: the global catalog
- * @op: pointer to an initialized #E2kOperation to use for cancellation
- * @ldap_error: set the value returned from get_ldap_connection if not NULL
- *
- * Returns a new LDAP handle. The caller must ldap_unbind() it when it
- * is done.
- *
- * Return value: an LDAP handle, or %NULL if it can't connect
- **/
-LDAP *
-e2k_global_catalog_get_ldap (E2kGlobalCatalog *gc, E2kOperation *op, gint *ldap_error)
-{
- LDAP *ldap;
- gint err;
-
- g_return_val_if_fail (E2K_IS_GLOBAL_CATALOG (gc), NULL);
-
- err = get_ldap_connection (gc, op, gc->priv->server, 3268, &ldap);
-
- if (ldap_error)
- *ldap_error = err;
-
- return ldap;
-}
-
-/**
- * e2k_global_catalog_new:
- * @server: the GC server name
- * @response_limit: the maximum number of responses to return from a search
- * @user: username to authenticate with
- * @domain: NT domain of @user, or %NULL to autodetect.
- * @password: password to authenticate with
- *
- * Create an object for communicating with the Windows Global Catalog
- * via LDAP.
- *
- * Return value: the new E2kGlobalCatalog. (This call will always succeed.
- * If the passed-in data is bad, it will fail on a later call.)
- **/
-E2kGlobalCatalog *
-e2k_global_catalog_new (const gchar *server, gint response_limit,
- const gchar *user, const gchar *domain,
- const gchar *password, E2kAutoconfigGalAuthPref use_auth)
-{
- E2kGlobalCatalog *gc;
-
- gc = g_object_new (E2K_TYPE_GLOBAL_CATALOG, NULL);
- gc->priv->server = g_strdup (server);
- gc->priv->auth = use_auth;
- gc->priv->user = g_strdup (user);
- gc->priv->nt_domain = g_strdup (domain);
- gc->priv->password = g_strdup (password);
- gc->response_limit = response_limit;
-
- return gc;
-}
-
-static const gchar *
-lookup_mta (E2kGlobalCatalog *gc, E2kOperation *op, const gchar *mta_dn)
-{
- gchar *hostname, **values;
- const gchar *attrs[2];
- LDAPMessage *resp;
- gint ldap_error, i;
-
- /* Skip over "CN=Microsoft MTA," */
- mta_dn = strchr (mta_dn, ',');
- if (!mta_dn)
- return NULL;
- mta_dn++;
-
- hostname = g_hash_table_lookup (gc->priv->server_cache, mta_dn);
- if (hostname)
- return hostname;
-
- E2K_GC_DEBUG_MSG(("GC: Finding hostname for %s\n", mta_dn));
-
- attrs[0] = "networkAddress";
- attrs[1] = NULL;
-
- ldap_error = gc_search (gc, op, mta_dn, LDAP_SCOPE_BASE,
- NULL, attrs, &resp);
- if (ldap_error != LDAP_SUCCESS) {
- E2K_GC_DEBUG_MSG(("GC: lookup failed (0x%02x)\n", ldap_error));
- return NULL;
- }
-
- values = ldap_get_values (gc->priv->ldap, resp, "networkAddress");
- ldap_msgfree (resp);
- if (!values) {
- E2K_GC_DEBUG_MSG(("GC: entry has no networkAddress\n"));
- return NULL;
- }
-
- hostname = NULL;
- for (i = 0; values[i]; i++) {
- if (strstr (values[i], "_tcp")) {
- hostname = strchr (values[i], ':');
- break;
- }
- }
- if (!hostname) {
- E2K_GC_DEBUG_MSG(("GC: host is not availble by TCP?\n"));
- ldap_value_free (values);
- return NULL;
- }
-
- hostname = g_strdup (hostname + 1);
- g_hash_table_insert (gc->priv->server_cache, g_strdup (mta_dn), hostname);
- ldap_value_free (values);
-
- E2K_GC_DEBUG_MSG(("GC: %s\n", hostname));
- return hostname;
-}
-
-static void
-get_sid_values (E2kGlobalCatalog *gc, E2kOperation *op,
- LDAPMessage *msg, E2kGlobalCatalogEntry *entry)
-{
- gchar **values;
- struct berval **bsid_values;
- E2kSidType type;
-
- values = ldap_get_values (gc->priv->ldap, msg, "displayName");
- if (values) {
- E2K_GC_DEBUG_MSG(("GC: displayName %s\n", values[0]));
- entry->display_name = g_strdup (values[0]);
- ldap_value_free (values);
- }
-
- bsid_values = ldap_get_values_len (gc->priv->ldap, msg, "objectSid");
- if (!bsid_values)
- return;
- if (bsid_values[0]->bv_len < 2 ||
- bsid_values[0]->bv_len != E2K_SID_BINARY_SID_LEN (bsid_values[0]->bv_val)) {
- E2K_GC_DEBUG_MSG(("GC: invalid SID\n"));
- return;
- }
-
- values = ldap_get_values (gc->priv->ldap, msg, "objectCategory");
- if (values && values[0] && !g_ascii_strncasecmp (values[0], "CN=Group", 8))
- type = E2K_SID_TYPE_GROUP;
- else if (values && values[0] && !g_ascii_strncasecmp (values[0], "CN=Foreign", 10))
- type = E2K_SID_TYPE_WELL_KNOWN_GROUP;
- else /* FIXME? */
- type = E2K_SID_TYPE_USER;
- if (values)
- ldap_value_free (values);
-
- entry->sid = e2k_sid_new_from_binary_sid (
- type, (guint8 *) bsid_values[0]->bv_val, entry->display_name);
- entry->mask |= E2K_GLOBAL_CATALOG_LOOKUP_SID;
-
- ldap_value_free_len (bsid_values);
-}
-
-static void
-get_mail_values (E2kGlobalCatalog *gc, E2kOperation *op,
- LDAPMessage *msg, E2kGlobalCatalogEntry *entry)
-{
- gchar **values, **mtavalues;
-
- values = ldap_get_values (gc->priv->ldap, msg, "mail");
- if (values) {
- E2K_GC_DEBUG_MSG(("GC: mail %s\n", values[0]));
- entry->email = g_strdup (values[0]);
- g_hash_table_insert (gc->priv->entry_cache,
- entry->email, entry);
- entry->mask |= E2K_GLOBAL_CATALOG_LOOKUP_EMAIL;
- ldap_value_free (values);
- }
-
- values = ldap_get_values (gc->priv->ldap, msg, "mailNickname");
- mtavalues = ldap_get_values (gc->priv->ldap, msg, "homeMTA");
- if (values && mtavalues) {
- E2K_GC_DEBUG_MSG(("GC: mailNickname %s\n", values[0]));
- E2K_GC_DEBUG_MSG(("GC: homeMTA %s\n", mtavalues[0]));
- entry->exchange_server = (gchar *)lookup_mta (gc, op, mtavalues[0]);
- ldap_value_free (mtavalues);
- if (entry->exchange_server)
- entry->mailbox = g_strdup (values[0]);
- ldap_value_free (values);
- entry->mask |= E2K_GLOBAL_CATALOG_LOOKUP_MAILBOX;
- }
-
- values = ldap_get_values (gc->priv->ldap, msg, "legacyExchangeDN");
- if (values) {
- E2K_GC_DEBUG_MSG(("GC: legacyExchangeDN %s\n", values[0]));
- entry->legacy_exchange_dn = g_strdup (values[0]);
- g_hash_table_insert (gc->priv->entry_cache,
- entry->legacy_exchange_dn,
- entry);
- entry->mask |= E2K_GLOBAL_CATALOG_LOOKUP_LEGACY_EXCHANGE_DN;
- ldap_value_free (values);
- }
-}
-
-static void
-get_delegation_values (E2kGlobalCatalog *gc, E2kOperation *op,
- LDAPMessage *msg, E2kGlobalCatalogEntry *entry)
-{
- gchar **values;
- gint i;
-
- values = ldap_get_values (gc->priv->ldap, msg, "publicDelegates");
- if (values) {
- E2K_GC_DEBUG_MSG(("GC: publicDelegates\n"));
- entry->delegates = g_ptr_array_new ();
- for (i = 0; values[i]; i++) {
- E2K_GC_DEBUG_MSG(("GC: %s\n", values[i]));
- g_ptr_array_add (entry->delegates,
- g_strdup (values[i]));
- }
- entry->mask |= E2K_GLOBAL_CATALOG_LOOKUP_DELEGATES;
- ldap_value_free (values);
- }
- values = ldap_get_values (gc->priv->ldap, msg, "publicDelegatesBL");
- if (values) {
- E2K_GC_DEBUG_MSG(("GC: publicDelegatesBL\n"));
- entry->delegators = g_ptr_array_new ();
- for (i = 0; values[i]; i++) {
- E2K_GC_DEBUG_MSG(("GC: %s\n", values[i]));
- g_ptr_array_add (entry->delegators,
- g_strdup (values[i]));
- }
- entry->mask |= E2K_GLOBAL_CATALOG_LOOKUP_DELEGATORS;
- ldap_value_free (values);
- }
-}
-
-static void
-get_quota_values (E2kGlobalCatalog *gc, E2kOperation *op,
- LDAPMessage *msg, E2kGlobalCatalogEntry *entry)
-{
- gchar **quota_setting_values, **quota_limit_values;
-
- /* Check if mailbox store default values are used */
- quota_setting_values = ldap_get_values (gc->priv->ldap, msg, "mDBUseDefaults");
- if (!quota_setting_values) {
- entry->quota_warn = entry->quota_nosend = entry->quota_norecv = 0;
- return;
- }
-
- entry->mask |= E2K_GLOBAL_CATALOG_LOOKUP_QUOTA;
- E2K_GC_DEBUG_MSG(("GC: mDBUseDefaults %s\n", quota_setting_values[0]));
-
- if (!strcmp (quota_setting_values[0], "TRUE")) {
- /* use global mailbox store settings */
- E2K_GC_DEBUG_MSG(("GC: Using global mailbox store limits\n"));
- }
- ldap_value_free (quota_setting_values);
-
- quota_limit_values = ldap_get_values (gc->priv->ldap, msg, "mDBStorageQuota");
- if (quota_limit_values) {
- entry->quota_warn = atoi(quota_limit_values[0]);
- E2K_GC_DEBUG_MSG(("GC: mDBStorageQuota %s\n", quota_limit_values[0]));
- ldap_value_free (quota_limit_values);
- }
-
- quota_limit_values = ldap_get_values (gc->priv->ldap, msg, "mDBOverQuotaLimit");
- if (quota_limit_values) {
- entry->quota_nosend = atoi(quota_limit_values[0]);
- E2K_GC_DEBUG_MSG(("GC: mDBOverQuotaLimit %s\n", quota_limit_values[0]));
- ldap_value_free (quota_limit_values);
- }
-
- quota_limit_values = ldap_get_values (gc->priv->ldap, msg, "mDBOverHardQuotaLimit");
- if (quota_limit_values) {
- entry->quota_norecv = atoi(quota_limit_values[0]);
- E2K_GC_DEBUG_MSG(("GC: mDBHardQuotaLimit %s\n", quota_limit_values[0]));
- ldap_value_free (quota_limit_values);
- }
-}
-
-static void
-get_account_control_values (E2kGlobalCatalog *gc, E2kOperation *op,
- LDAPMessage *msg, E2kGlobalCatalogEntry *entry)
-{
- gchar **values;
-
- values = ldap_get_values (gc->priv->ldap, msg, "userAccountControl");
- if (values) {
- entry->user_account_control = atoi(values[0]);
- E2K_GC_DEBUG_MSG(("GC: userAccountControl %s\n", values[0]));
- entry->mask |= E2K_GLOBAL_CATALOG_LOOKUP_ACCOUNT_CONTROL;
- ldap_value_free (values);
- }
-
-}
-
-/**
- * e2k_global_catalog_lookup:
- * @gc: the global catalog
- * @op: pointer to an #E2kOperation to use for cancellation
- * @type: the type of information in @key
- * @key: email address or DN to look up
- * @flags: the information to look up
- * @entry_p: pointer to a variable to return the entry in.
- *
- * Look up the indicated user in the global catalog and
- * return their information in *@entry_p.
- *
- * Return value: the status of the lookup
- **/
-E2kGlobalCatalogStatus
-e2k_global_catalog_lookup (E2kGlobalCatalog *gc,
- E2kOperation *op,
- E2kGlobalCatalogLookupType type,
- const gchar *key,
- E2kGlobalCatalogLookupFlags flags,
- E2kGlobalCatalogEntry **entry_p)
-{
- E2kGlobalCatalogEntry *entry;
- GPtrArray *attrs;
- E2kGlobalCatalogLookupFlags lookup_flags, need_flags = 0;
- const gchar *base = NULL;
- gchar *filter = NULL, *dn;
- gint scope = LDAP_SCOPE_BASE, ldap_error;
- E2kGlobalCatalogStatus status;
- LDAPMessage *msg, *resp;
-
- g_return_val_if_fail (E2K_IS_GLOBAL_CATALOG (gc), E2K_GLOBAL_CATALOG_ERROR);
- g_return_val_if_fail (key != NULL, E2K_GLOBAL_CATALOG_ERROR);
-
- g_mutex_lock (gc->priv->ldap_lock);
-
- entry = g_hash_table_lookup (gc->priv->entry_cache, key);
- if (!entry)
- entry = g_new0 (E2kGlobalCatalogEntry, 1);
-
- attrs = g_ptr_array_new ();
-
- if (!entry->display_name)
- g_ptr_array_add (attrs, (guint8 *) "displayName");
- if (!entry->email) {
- g_ptr_array_add (attrs, (guint8 *) "mail");
- if (flags & E2K_GLOBAL_CATALOG_LOOKUP_EMAIL)
- need_flags |= E2K_GLOBAL_CATALOG_LOOKUP_EMAIL;
- }
- if (!entry->legacy_exchange_dn) {
- g_ptr_array_add (attrs, (guint8 *) "legacyExchangeDN");
- if (flags & E2K_GLOBAL_CATALOG_LOOKUP_LEGACY_EXCHANGE_DN)
- need_flags |= E2K_GLOBAL_CATALOG_LOOKUP_LEGACY_EXCHANGE_DN;
- }
-
- lookup_flags = flags & ~entry->mask;
-
- if (lookup_flags & E2K_GLOBAL_CATALOG_LOOKUP_SID) {
- g_ptr_array_add (attrs, (guint8 *) "objectSid");
- g_ptr_array_add (attrs, (guint8 *) "objectCategory");
- need_flags |= E2K_GLOBAL_CATALOG_LOOKUP_SID;
- }
- if (lookup_flags & E2K_GLOBAL_CATALOG_LOOKUP_MAILBOX) {
- g_ptr_array_add (attrs, (guint8 *) "mailNickname");
- g_ptr_array_add (attrs, (guint8 *) "homeMTA");
- need_flags |= E2K_GLOBAL_CATALOG_LOOKUP_MAILBOX;
- }
- if (lookup_flags & E2K_GLOBAL_CATALOG_LOOKUP_DELEGATES)
- g_ptr_array_add (attrs, (guint8 *) "publicDelegates");
- if (lookup_flags & E2K_GLOBAL_CATALOG_LOOKUP_DELEGATORS)
- g_ptr_array_add (attrs, (guint8 *) "publicDelegatesBL");
- if (lookup_flags & E2K_GLOBAL_CATALOG_LOOKUP_QUOTA) {
- g_ptr_array_add (attrs, (guint8 *) "mDBUseDefaults");
- g_ptr_array_add (attrs, (guint8 *) "mDBStorageQuota");
- g_ptr_array_add (attrs, (guint8 *) "mDBOverQuotaLimit");
- g_ptr_array_add (attrs, (guint8 *) "mDBOverHardQuotaLimit");
- }
- if (lookup_flags & E2K_GLOBAL_CATALOG_LOOKUP_ACCOUNT_CONTROL)
- g_ptr_array_add (attrs, (guint8 *) "userAccountControl");
-
- if (attrs->len == 0) {
- E2K_GC_DEBUG_MSG(("\nGC: returning cached info for %s\n", key));
- goto lookedup;
- }
-
- E2K_GC_DEBUG_MSG(("\nGC: looking up info for %s\n", key));
- g_ptr_array_add (attrs, NULL);
-
- switch (type) {
- case E2K_GLOBAL_CATALOG_LOOKUP_BY_EMAIL:
- filter = g_strdup_printf ("(mail=%s)", key);
- base = LDAP_ROOT_DSE;
- scope = LDAP_SCOPE_SUBTREE;
- break;
-
- case E2K_GLOBAL_CATALOG_LOOKUP_BY_DN:
- filter = NULL;
- base = key;
- scope = LDAP_SCOPE_BASE;
- break;
-
- case E2K_GLOBAL_CATALOG_LOOKUP_BY_LEGACY_EXCHANGE_DN:
- filter = g_strdup_printf ("(legacyExchangeDN=%s)", key);
- base = LDAP_ROOT_DSE;
- scope = LDAP_SCOPE_SUBTREE;
- break;
- }
-
- ldap_error = gc_search (gc, op, base, scope, filter,
- (const gchar **)attrs->pdata, &msg);
- if (ldap_error == LDAP_USER_CANCELLED) {
- E2K_GC_DEBUG_MSG(("GC: ldap_search cancelled"));
- status = E2K_GLOBAL_CATALOG_CANCELLED;
- goto done;
- } else if (ldap_error == LDAP_INVALID_CREDENTIALS) {
- E2K_GC_DEBUG_MSG(("GC: ldap_search auth failed"));
- status = E2K_GLOBAL_CATALOG_AUTH_FAILED;
- goto done;
- } else if (ldap_error != LDAP_SUCCESS) {
- E2K_GC_DEBUG_MSG(("GC: ldap_search failed: 0x%02x\n\n", ldap_error));
- status = E2K_GLOBAL_CATALOG_ERROR;
- goto done;
- }
-
- resp = ldap_first_entry (gc->priv->ldap, msg);
- if (!resp) {
- E2K_GC_DEBUG_MSG(("GC: no such user\n\n"));
- status = E2K_GLOBAL_CATALOG_NO_SUCH_USER;
- ldap_msgfree (msg);
- goto done;
- }
-
- if (!entry->dn) {
- dn = ldap_get_dn (gc->priv->ldap, resp);
- entry->dn = g_strdup (dn);
- E2K_GC_DEBUG_MSG(("GC: dn = %s\n\n", dn));
- ldap_memfree (dn);
- g_ptr_array_add (gc->priv->entries, entry);
- g_hash_table_insert (gc->priv->entry_cache,
- entry->dn, entry);
- }
-
- get_sid_values (gc, op, resp, entry);
- get_mail_values (gc, op, resp, entry);
- get_delegation_values (gc, op, resp, entry);
- get_quota_values (gc, op, resp, entry);
- get_account_control_values (gc, op, resp, entry);
- ldap_msgfree (msg);
-
- lookedup:
- if (need_flags & ~entry->mask) {
- E2K_GC_DEBUG_MSG(("GC: no data\n\n"));
- status = E2K_GLOBAL_CATALOG_NO_DATA;
- } else {
- E2K_GC_DEBUG_MSG(("\n"));
- status = E2K_GLOBAL_CATALOG_OK;
- entry->mask |= lookup_flags;
- *entry_p = entry;
- }
-
- done:
- g_free (filter);
- g_ptr_array_free (attrs, TRUE);
-
- if (status != E2K_GLOBAL_CATALOG_OK && !entry->dn)
- g_free (entry);
-
- g_mutex_unlock (gc->priv->ldap_lock);
- return status;
-}
-
-struct async_lookup_data {
- E2kGlobalCatalog *gc;
- E2kOperation *op;
- E2kGlobalCatalogLookupType type;
- gchar *key;
- E2kGlobalCatalogLookupFlags flags;
- E2kGlobalCatalogCallback callback;
- gpointer user_data;
-
- E2kGlobalCatalogEntry *entry;
- E2kGlobalCatalogStatus status;
-};
-
-static gboolean
-idle_lookup_result (gpointer user_data)
-{
- struct async_lookup_data *ald = user_data;
-
- ald->callback (ald->gc, ald->status, ald->entry, ald->user_data);
- g_object_unref (ald->gc);
- g_free (ald->key);
- g_free (ald);
- return FALSE;
-}
-
-static gpointer
-do_lookup_thread (gpointer user_data)
-{
- struct async_lookup_data *ald = user_data;
-
- ald->status = e2k_global_catalog_lookup (ald->gc, ald->op, ald->type,
- ald->key, ald->flags,
- &ald->entry);
- g_idle_add (idle_lookup_result, ald);
- return NULL;
-}
-
-/**
- * e2k_global_catalog_async_lookup:
- * @gc: the global catalog
- * @op: pointer to an #E2kOperation to use for cancellation
- * @type: the type of information in @key
- * @key: email address or DN to look up
- * @flags: the information to look up
- * @callback: the callback to invoke after finding the user
- * @user_data: data to pass to callback
- *
- * Asynchronously look up the indicated user in the global catalog and
- * return the requested information to the callback.
- **/
-void
-e2k_global_catalog_async_lookup (E2kGlobalCatalog *gc,
- E2kOperation *op,
- E2kGlobalCatalogLookupType type,
- const gchar *key,
- E2kGlobalCatalogLookupFlags flags,
- E2kGlobalCatalogCallback callback,
- gpointer user_data)
-{
- struct async_lookup_data *ald;
- pthread_t pth;
-
- ald = g_new0 (struct async_lookup_data, 1);
- ald->gc = g_object_ref (gc);
- ald->op = op;
- ald->type = type;
- ald->key = g_strdup (key);
- ald->flags = flags;
- ald->callback = callback;
- ald->user_data = user_data;
-
- if (pthread_create (&pth, NULL, do_lookup_thread, ald) == -1) {
- g_warning ("Could not create lookup thread\n");
- ald->status = E2K_GLOBAL_CATALOG_ERROR;
- g_idle_add (idle_lookup_result, ald);
- }
-}
-
-static const gchar *
-lookup_controlling_ad_server (E2kGlobalCatalog *gc, E2kOperation *op,
- const gchar *dn)
-{
- gchar *hostname, **values, *ad_dn;
- const gchar *attrs[2];
- LDAPMessage *resp;
- gint ldap_error;
-
- while (g_ascii_strncasecmp (dn, "DC=", 3) != 0) {
- dn = strchr (dn, ',');
- if (!dn)
- return NULL;
- dn++;
- }
-
- hostname = g_hash_table_lookup (gc->priv->server_cache, dn);
- if (hostname)
- return hostname;
-
- E2K_GC_DEBUG_MSG(("GC: Finding AD server for %s\n", dn));
-
- attrs[0] = "masteredBy";
- attrs[1] = NULL;
-
- ldap_error = gc_search (gc, op, dn, LDAP_SCOPE_BASE, NULL, attrs, &resp);
- if (ldap_error != LDAP_SUCCESS) {
- E2K_GC_DEBUG_MSG(("GC: ldap_search failed: 0x%02x\n", ldap_error));
- return NULL;
- }
-
- values = ldap_get_values (gc->priv->ldap, resp, "masteredBy");
- ldap_msgfree (resp);
- if (!values) {
- E2K_GC_DEBUG_MSG(("GC: no known AD server\n\n"));
- return NULL;
- }
-
- /* Skip over "CN=NTDS Settings," */
- ad_dn = strchr (values[0], ',');
- if (!ad_dn) {
- E2K_GC_DEBUG_MSG(("GC: bad dn %s\n\n", values[0]));
- ldap_value_free (values);
- return NULL;
- }
- ad_dn++;
-
- attrs[0] = "dNSHostName";
- attrs[1] = NULL;
-
- ldap_error = gc_search (gc, op, ad_dn, LDAP_SCOPE_BASE, NULL, attrs, &resp);
- ldap_value_free (values);
-
- if (ldap_error != LDAP_SUCCESS) {
- E2K_GC_DEBUG_MSG(("GC: ldap_search failed: 0x%02x\n\n", ldap_error));
- return NULL;
- }
-
- values = ldap_get_values (gc->priv->ldap, resp, "dNSHostName");
- ldap_msgfree (resp);
- if (!values) {
- E2K_GC_DEBUG_MSG(("GC: entry has no dNSHostName\n\n"));
- return NULL;
- }
-
- hostname = g_strdup (values[0]);
- ldap_value_free (values);
-
- g_hash_table_insert (gc->priv->server_cache, g_strdup (dn), hostname);
-
- E2K_GC_DEBUG_MSG(("GC: %s\n", hostname));
- return hostname;
-}
-
-static gchar *
-find_domain_dn (gchar *domain)
-{
- GString *dn_value = g_string_new (NULL);
- gchar *dn;
- gchar *sub_domain=NULL;
-
- sub_domain = strtok (domain, ".");
- while (sub_domain != NULL) {
- g_string_append (dn_value, "DC=");
- g_string_append (dn_value, sub_domain);
- g_string_append (dn_value, ",");
- sub_domain = strtok (NULL, ".");
- }
- if (dn_value->str[0])
- dn = g_strndup (dn_value->str, strlen(dn_value->str) - 1);
- else
- dn = NULL;
- g_string_free (dn_value, TRUE);
- return dn;
-}
-
-gdouble
-lookup_passwd_max_age (E2kGlobalCatalog *gc, E2kOperation *op)
-{
- gchar **values = NULL, *filter = NULL, *val=NULL;
- const gchar *attrs[2];
- LDAP *ldap;
- LDAPMessage *msg=NULL;
- gint ldap_error, msgid;
- gdouble maxAge=0;
- gchar *dn=NULL;
-
- attrs[0] = "maxPwdAge";
- attrs[1] = NULL;
-
- filter = g_strdup("objectClass=domainDNS");
-
- dn = find_domain_dn (gc->domain);
-
- ldap_error = get_ldap_connection (gc, op, gc->priv->server, LDAP_PORT, &ldap);
- if (ldap_error != LDAP_SUCCESS) {
- E2K_GC_DEBUG_MSG(("GC: Establishing ldap connection failed : 0x%02x\n\n",
- ldap_error));
- return -1;
- }
-
- ldap_error = ldap_search_ext (ldap, dn, LDAP_SCOPE_BASE, filter, (gchar **)attrs,
- FALSE, NULL, NULL, NULL, 0, &msgid);
- if (!ldap_error) {
- ldap_error = gc_ldap_result (ldap, op, msgid, &msg);
- if (ldap_error) {
- E2K_GC_DEBUG_MSG(("GC: ldap_result failed: 0x%02x\n\n", ldap_error));
- return -1;
- }
- }
- else {
- E2K_GC_DEBUG_MSG(("GC: ldap_search failed:0x%02x \n\n", ldap_error));
- return -1;
- }
-
- values = ldap_get_values (ldap, msg, "maxPwdAge");
- if (!values) {
- E2K_GC_DEBUG_MSG(("GC: couldn't retrieve maxPwdAge\n"));
- return -1;
- }
-
- if (values[0]) {
- val = values[0];
- if (*val == '-')
- ++val;
- maxAge = strtod (val, NULL);
- }
-
- /*g_hash_table_insert (gc->priv->server_cache, g_strdup (dn), hostname); FIXME? */
-
- E2K_GC_DEBUG_MSG(("GC: maxPwdAge = %f\n", maxAge));
-
- if (msg)
- ldap_msgfree (msg);
- if (values)
- ldap_value_free (values);
- ldap_unbind (ldap);
- g_free (filter);
- g_free (dn);
- return maxAge;
-}
-
-static E2kGlobalCatalogStatus
-do_delegate_op (E2kGlobalCatalog *gc, E2kOperation *op, gint deleg_op,
- const gchar *self_dn, const gchar *delegate_dn)
-{
- LDAP *ldap;
- LDAPMod *mods[2], mod;
- const gchar *ad_server;
- gchar *values[2];
- gint ldap_error, msgid;
-
- g_return_val_if_fail (E2K_IS_GLOBAL_CATALOG (gc), E2K_GLOBAL_CATALOG_ERROR);
- g_return_val_if_fail (self_dn != NULL, E2K_GLOBAL_CATALOG_ERROR);
- g_return_val_if_fail (delegate_dn != NULL, E2K_GLOBAL_CATALOG_ERROR);
-
- ad_server = lookup_controlling_ad_server (gc, op, self_dn);
- if (!ad_server) {
- if (e2k_operation_is_cancelled (op))
- return E2K_GLOBAL_CATALOG_CANCELLED;
- else
- return E2K_GLOBAL_CATALOG_ERROR;
- }
-
- ldap_error = get_ldap_connection (gc, op, ad_server, LDAP_PORT, &ldap);
- if (ldap_error == LDAP_USER_CANCELLED)
- return E2K_GLOBAL_CATALOG_CANCELLED;
- else if (ldap_error != LDAP_SUCCESS)
- return E2K_GLOBAL_CATALOG_ERROR;
-
- mod.mod_op = deleg_op;
- mod.mod_type = (gchar *) "publicDelegates";
- mod.mod_values = values;
- values[0] = (gchar *)delegate_dn;
- values[1] = NULL;
-
- mods[0] = &mod;
- mods[1] = NULL;
-
- ldap_error = ldap_modify_ext (ldap, self_dn, mods, NULL, NULL, &msgid);
- if (ldap_error == LDAP_SUCCESS) {
- LDAPMessage *msg;
-
- ldap_error = gc_ldap_result (ldap, op, msgid, &msg);
- if (ldap_error == LDAP_SUCCESS) {
- ldap_parse_result (ldap, msg, &ldap_error, NULL, NULL,
- NULL, NULL, TRUE);
- }
- }
- ldap_unbind (ldap);
-
- switch (ldap_error) {
- case LDAP_SUCCESS:
- E2K_GC_DEBUG_MSG(("\n"));
- return E2K_GLOBAL_CATALOG_OK;
-
- case LDAP_NO_SUCH_OBJECT:
- E2K_GC_DEBUG_MSG(("GC: no such user\n\n"));
- return E2K_GLOBAL_CATALOG_NO_SUCH_USER;
-
- case LDAP_NO_SUCH_ATTRIBUTE:
- E2K_GC_DEBUG_MSG(("GC: no such delegate\n\n"));
- return E2K_GLOBAL_CATALOG_NO_DATA;
-
- case LDAP_CONSTRAINT_VIOLATION:
- E2K_GC_DEBUG_MSG(("GC: bad delegate\n\n"));
- return E2K_GLOBAL_CATALOG_BAD_DATA;
-
- case LDAP_TYPE_OR_VALUE_EXISTS:
- E2K_GC_DEBUG_MSG(("GC: delegate already exists\n\n"));
- return E2K_GLOBAL_CATALOG_EXISTS;
-
- case LDAP_USER_CANCELLED:
- E2K_GC_DEBUG_MSG(("GC: cancelled\n\n"));
- return E2K_GLOBAL_CATALOG_CANCELLED;
-
- default:
- E2K_GC_DEBUG_MSG(("GC: ldap_modify failed: 0x%02x\n\n", ldap_error));
- return E2K_GLOBAL_CATALOG_ERROR;
- }
-}
-
-/**
- * e2k_global_catalog_add_delegate:
- * @gc: the global catalog
- * @op: pointer to an #E2kOperation to use for cancellation
- * @self_dn: Active Directory DN of the user to add a delegate to
- * @delegate_dn: Active Directory DN of the new delegate
- *
- * Attempts to make @delegate_dn a delegate of @self_dn.
- *
- * Return value: %E2K_GLOBAL_CATALOG_OK on success,
- * %E2K_GLOBAL_CATALOG_NO_SUCH_USER if @self_dn is invalid,
- * %E2K_GLOBAL_CATALOG_BAD_DATA if @delegate_dn is invalid,
- * %E2K_GLOBAL_CATALOG_EXISTS if @delegate_dn is already a delegate,
- * %E2K_GLOBAL_CATALOG_ERROR on other errors.
- **/
-E2kGlobalCatalogStatus
-e2k_global_catalog_add_delegate (E2kGlobalCatalog *gc,
- E2kOperation *op,
- const gchar *self_dn,
- const gchar *delegate_dn)
-{
- E2K_GC_DEBUG_MSG(("\nGC: adding %s as delegate for %s\n", delegate_dn, self_dn));
-
- return do_delegate_op (gc, op, LDAP_MOD_ADD, self_dn, delegate_dn);
-}
-
-/**
- * e2k_global_catalog_remove_delegate:
- * @gc: the global catalog
- * @op: pointer to an #E2kOperation to use for cancellation
- * @self_dn: Active Directory DN of the user to remove a delegate from
- * @delegate_dn: Active Directory DN of the delegate to remove
- *
- * Attempts to remove @delegate_dn as a delegate of @self_dn.
- *
- * Return value: %E2K_GLOBAL_CATALOG_OK on success,
- * %E2K_GLOBAL_CATALOG_NO_SUCH_USER if @self_dn is invalid,
- * %E2K_GLOBAL_CATALOG_NO_DATA if @delegate_dn is not a delegate of @self_dn,
- * %E2K_GLOBAL_CATALOG_ERROR on other errors.
- **/
-E2kGlobalCatalogStatus
-e2k_global_catalog_remove_delegate (E2kGlobalCatalog *gc,
- E2kOperation *op,
- const gchar *self_dn,
- const gchar *delegate_dn)
-{
- E2K_GC_DEBUG_MSG(("\nGC: removing %s as delegate for %s\n", delegate_dn, self_dn));
-
- return do_delegate_op (gc, op, LDAP_MOD_DELETE, self_dn, delegate_dn);
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __E2K_GLOBAL_CATALOG_H__
-#define __E2K_GLOBAL_CATALOG_H__
-
-#include <glib-object.h>
-#include "e2k-types.h"
-#include "e2k-operation.h"
-#include "e2k-validate.h"
-
-G_BEGIN_DECLS
-
-#define E2K_TYPE_GLOBAL_CATALOG (e2k_global_catalog_get_type ())
-#define E2K_GLOBAL_CATALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E2K_TYPE_GLOBAL_CATALOG, E2kGlobalCatalog))
-#define E2K_GLOBAL_CATALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E2K_TYPE_GLOBAL_CATALOG, E2kGlobalCatalogClass))
-#define E2K_IS_GLOBAL_CATALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E2K_TYPE_GLOBAL_CATALOG))
-#define E2K_IS_GLOBAL_CATALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E2K_TYPE_GLOBAL_CATALOG))
-
-struct _E2kGlobalCatalog {
- GObject parent;
-
- gchar *domain;
- gint response_limit;
-
- E2kGlobalCatalogPrivate *priv;
-};
-
-struct _E2kGlobalCatalogClass {
- GObjectClass parent_class;
-
-};
-
-GType e2k_global_catalog_get_type (void);
-E2kGlobalCatalog *e2k_global_catalog_new (const gchar *server,
- gint response_limit,
- const gchar *user,
- const gchar *domain,
- const gchar *password,
- E2kAutoconfigGalAuthPref use_auth);
-
-typedef enum {
- E2K_GLOBAL_CATALOG_OK,
- E2K_GLOBAL_CATALOG_NO_SUCH_USER,
- E2K_GLOBAL_CATALOG_NO_DATA,
- E2K_GLOBAL_CATALOG_BAD_DATA,
- E2K_GLOBAL_CATALOG_EXISTS,
- E2K_GLOBAL_CATALOG_AUTH_FAILED,
- E2K_GLOBAL_CATALOG_CANCELLED,
- E2K_GLOBAL_CATALOG_ERROR
-} E2kGlobalCatalogStatus;
-
-typedef enum {
- E2K_GLOBAL_CATALOG_LOOKUP_BY_EMAIL,
- E2K_GLOBAL_CATALOG_LOOKUP_BY_DN,
- E2K_GLOBAL_CATALOG_LOOKUP_BY_LEGACY_EXCHANGE_DN
-} E2kGlobalCatalogLookupType;
-
-typedef enum {
- E2K_GLOBAL_CATALOG_LOOKUP_SID = (1 << 0),
- E2K_GLOBAL_CATALOG_LOOKUP_EMAIL = (1 << 1),
- E2K_GLOBAL_CATALOG_LOOKUP_MAILBOX = (1 << 2),
- E2K_GLOBAL_CATALOG_LOOKUP_LEGACY_EXCHANGE_DN = (1 << 3),
- E2K_GLOBAL_CATALOG_LOOKUP_DELEGATES = (1 << 4),
- E2K_GLOBAL_CATALOG_LOOKUP_DELEGATORS = (1 << 5),
- E2K_GLOBAL_CATALOG_LOOKUP_QUOTA = (1 << 6),
- E2K_GLOBAL_CATALOG_LOOKUP_ACCOUNT_CONTROL = (1 << 7)
-} E2kGlobalCatalogLookupFlags;
-
-typedef struct {
- gchar *dn, *display_name;
- E2kSid *sid;
- gchar *email, *exchange_server, *mailbox, *legacy_exchange_dn;
- GPtrArray *delegates, *delegators;
- gint quota_warn, quota_nosend, quota_norecv;
- gint user_account_control;
-
- E2kGlobalCatalogLookupFlags mask;
-} E2kGlobalCatalogEntry;
-
-E2kGlobalCatalogStatus e2k_global_catalog_lookup (E2kGlobalCatalog *gc,
- E2kOperation *op,
- E2kGlobalCatalogLookupType type,
- const gchar *key,
- E2kGlobalCatalogLookupFlags flags,
- E2kGlobalCatalogEntry **entry_p);
-
-typedef void (*E2kGlobalCatalogCallback) (E2kGlobalCatalog *gc,
- E2kGlobalCatalogStatus status,
- E2kGlobalCatalogEntry *entry,
- gpointer user_data);
-
-void e2k_global_catalog_async_lookup (E2kGlobalCatalog *gc,
- E2kOperation *op,
- E2kGlobalCatalogLookupType type,
- const gchar *key,
- E2kGlobalCatalogLookupFlags flags,
- E2kGlobalCatalogCallback callback,
- gpointer user_data);
-
-gdouble lookup_passwd_max_age (E2kGlobalCatalog *gc,
- E2kOperation *op);
-
-#define e2k_global_catalog_entry_free(gc, entry)
-
-E2kGlobalCatalogStatus e2k_global_catalog_add_delegate (E2kGlobalCatalog *gc,
- E2kOperation *op,
- const gchar *self_dn,
- const gchar *delegate_dn);
-E2kGlobalCatalogStatus e2k_global_catalog_remove_delegate (E2kGlobalCatalog *gc,
- E2kOperation *op,
- const gchar *self_dn,
- const gchar *delegate_dn);
-
-G_END_DECLS
-
-#endif /* __E2K_GLOBAL_CATALOG_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2001-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "e2k-http-utils.h"
-
-#include <libedataserver/e-time-utils.h>
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-extern const gchar *e2k_rfc822_months [];
-
-/**
- * e2k_http_parse_date:
- * @date: an HTTP Date header, returned from Exchange
- *
- * Converts an HTTP Date header into a time_t value. Doesn't
- * do much sanity checking on the format since we know IIS always
- * returns the date in RFC 1123 format, not either of the other two
- * allowable formats.
- *
- * Return value: a %time_t corresponding to @date.
- **/
-time_t
-e2k_http_parse_date (const gchar *date)
-{
- struct tm tm;
- gchar *p;
-
- if (strlen (date) < 29 || date[3] != ',' || date[4] != ' ')
- return -1;
-
- memset (&tm, 0, sizeof (tm));
- p = (gchar *)date + 5;
-
- tm.tm_mday = strtol (p, &p, 10);
- p++;
- for (tm.tm_mon = 0; tm.tm_mon < 12; tm.tm_mon++) {
- if (!strncmp (p, e2k_rfc822_months[tm.tm_mon], 3))
- break;
- }
- p += 3;
-
- tm.tm_year = strtol (p, &p, 10) - 1900;
-
- tm.tm_hour = strtol (p, &p, 10);
- p++;
- tm.tm_min = strtol (p, &p, 10);
- p++;
- tm.tm_sec = strtol (p, &p, 10);
-
- return e_mktime_utc (&tm);
-}
-
-/**
- * e2k_http_parse_status:
- * @status_line: an HTTP Status-Line
- *
- * Parses an HTTP Status-Line and returns the Status-Code
- *
- * Return value: the Status-Code portion of @status_line
- **/
-E2kHTTPStatus
-e2k_http_parse_status (const gchar *status_line)
-{
- if (strncmp (status_line, "HTTP/1.", 7) != 0 ||
- !isdigit (status_line[7]) ||
- status_line[8] != ' ')
- return E2K_HTTP_MALFORMED;
-
- return atoi (status_line + 9);
-}
-
-/**
- * e2k_http_accept_language:
- *
- * Generates an Accept-Language value to send to the Exchange server.
- * The user's default folders (Inbox, Calendar, etc) are not created
- * until the user connects to Exchange for the first time, and in that
- * case, it needs to know what language to name the folders in.
- * libexchange users are responsible for setting the Accept-Language
- * header on any request that could be the first-ever request to a
- * mailbox. (Exchange will return 401 Unauthorized if it receives a
- * request with no Accept-Language header for an uninitialized
- * mailbox.)
- *
- * Return value: an Accept-Language string.
- **/
-const gchar *
-e2k_http_accept_language (void)
-{
- static gchar *accept = NULL;
-
- if (!accept) {
- GString *buf;
- const gchar *lang, *sub;
- gint baselen;
-
- buf = g_string_new (NULL);
-
- lang = getenv ("LANG");
- if (!lang || !strcmp (lang, "C") || !strcmp (lang, "POSIX"))
- lang = "en";
-
- /* lang is "language[_territory][.codeset][@modifier]",
- * eg "fr" or "de_AT.utf8@euro". The Accept-Language
- * header should be a comma-separated list of
- * "language[-territory]". For the above cases we'd
- * generate "fr, en" and "de-AT, de, en". (We always
- * include "en" in case the server doesn't support the
- * user's preferred locale.)
- */
-
- baselen = strcspn (lang, "_.@");
- g_string_append_len (buf, lang, baselen);
- if (lang[baselen] == '_') {
- sub = lang + baselen + 1;
- g_string_append_c (buf, '-');
- g_string_append_len (buf, sub, strcspn (sub, ".@"));
-
- g_string_append (buf, ", ");
- g_string_append_len (buf, lang, baselen);
- }
-
- if (baselen != 2 || strncmp (lang, "en", 2) != 0)
- g_string_append (buf, ", en");
-
- accept = buf->str;
- g_string_free (buf, FALSE);
- }
-
- return accept;
-}
-
-typedef struct {
- const gchar *wanted_header;
- GSList *matches;
-} GetHeadersData;
-
-static void
-maybe_append_header (const gchar *header_name, const gchar *value, gpointer data)
-{
- GetHeadersData *ghd = data;
-
- if (!g_ascii_strcasecmp (header_name, ghd->wanted_header))
- ghd->matches = g_slist_append (ghd->matches, (gchar *)value);
-}
-
-/* This is a cheat to recreate the behavior of libsoup 2.2's
- * soup_message_get_header_list. See the docs for
- * soup_message_headers_get() for an explanation of why we shouldn't
- * be doing this...
- */
-GSList *
-e2k_http_get_headers (SoupMessageHeaders *hdrs, const gchar *header_name)
-{
- GetHeadersData ghd;
-
- ghd.wanted_header = header_name;
- ghd.matches = NULL;
- soup_message_headers_foreach (hdrs, maybe_append_header, &ghd);
- return ghd.matches;
-}
-
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __E2K_HTTP_UTILS_H__
-#define __E2K_HTTP_UTILS_H__
-
-#include "e2k-types.h"
-#include <time.h>
-#include <libsoup/soup-status.h>
-#include <libsoup/soup-message-headers.h>
-
-typedef guint E2kHTTPStatus;
-
-time_t e2k_http_parse_date (const gchar *date);
-E2kHTTPStatus e2k_http_parse_status (const gchar *status_line);
-
-const gchar *e2k_http_accept_language (void);
-
-GSList *e2k_http_get_headers (SoupMessageHeaders *hdrs,
- const gchar *header_name);
-
-#define E2K_HTTP_STATUS_IS_TRANSPORT_ERROR(status) SOUP_STATUS_IS_TRANSPORT_ERROR(status)
-#define E2K_HTTP_CANCELLED SOUP_STATUS_CANCELLED
-#define E2K_HTTP_CANT_RESOLVE SOUP_STATUS_CANT_RESOLVE
-#define E2K_HTTP_CANT_CONNECT SOUP_STATUS_CANT_CONNECT
-#define E2K_HTTP_SSL_FAILED SOUP_STATUS_SSL_FAILED
-#define E2K_HTTP_IO_ERROR SOUP_STATUS_IO_ERROR
-#define E2K_HTTP_MALFORMED SOUP_STATUS_MALFORMED
-
-#define E2K_HTTP_STATUS_IS_INFORMATIONAL(status) SOUP_STATUS_IS_INFORMATIONAL(status)
-#define E2K_HTTP_CONTINUE 100
-
-#define E2K_HTTP_STATUS_IS_SUCCESSFUL(status) SOUP_STATUS_IS_SUCCESSFUL(status)
-#define E2K_HTTP_OK 200
-#define E2K_HTTP_CREATED 201
-#define E2K_HTTP_ACCEPTED 202
-#define E2K_HTTP_NO_CONTENT 204
-#define E2K_HTTP_MULTI_STATUS 207
-
-#define E2K_HTTP_STATUS_IS_REDIRECTION(status) SOUP_STATUS_IS_REDIRECTION(status)
-
-#define E2K_HTTP_STATUS_IS_CLIENT_ERROR(status) SOUP_STATUS_IS_CLIENT_ERROR(status)
-#define E2K_HTTP_BAD_REQUEST 400
-#define E2K_HTTP_UNAUTHORIZED 401
-#define E2K_HTTP_FORBIDDEN 403
-#define E2K_HTTP_NOT_FOUND 404
-#define E2K_HTTP_METHOD_NOT_ALLOWED 405
-#define E2K_HTTP_CONFLICT 409
-#define E2K_HTTP_PRECONDITION_FAILED 412
-#define E2K_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE 416
-#define E2K_HTTP_UNPROCESSABLE_ENTITY 422
-#define E2K_HTTP_LOCKED 423
-#define E2K_HTTP_INSUFFICIENT_SPACE_ON_RESOURCE 425
-#define E2K_HTTP_TIMEOUT 440
-
-#define E2K_HTTP_STATUS_IS_SERVER_ERROR(status) SOUP_STATUS_IS_SERVER_ERROR(status)
-#define E2K_HTTP_INTERNAL_SERVER_ERROR 500
-#define E2K_HTTP_BAD_GATEWAY 502
-
-G_END_DECLS
-
-#endif /* __E2K_HTTP_UTILS_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ctype.h>
-#include <glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "e2k-kerberos.h"
-#include <krb5.h>
-
-static krb5_context
-e2k_kerberos_context_new (const gchar *domain)
-{
- krb5_context ctx;
- gchar *realm;
-
- if (krb5_init_context (&ctx) != 0)
- return NULL;
-
- realm = g_ascii_strup (domain, strlen (domain));
- krb5_set_default_realm (ctx, realm);
- g_free (realm);
-
- return ctx;
-}
-
-static E2kKerberosResult
-krb5_result_to_e2k_kerberos_result (gint result)
-{
- switch (result) {
- case 0:
- return E2K_KERBEROS_OK;
-
- case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
- return E2K_KERBEROS_USER_UNKNOWN;
-
- case KRB5KRB_AP_ERR_BAD_INTEGRITY:
- case KRB5KDC_ERR_PREAUTH_FAILED:
- return E2K_KERBEROS_PASSWORD_INCORRECT;
-
- case KRB5KDC_ERR_KEY_EXP:
- return E2K_KERBEROS_PASSWORD_EXPIRED;
-
- case KRB5_KDC_UNREACH:
- return E2K_KERBEROS_KDC_UNREACHABLE;
-
- case KRB5KRB_AP_ERR_SKEW:
- return E2K_KERBEROS_TIME_SKEW;
-
- default:
- g_warning ("Unexpected kerberos error %d", result);
- return E2K_KERBEROS_FAILED;
- }
-}
-
-static E2kKerberosResult
-get_init_cred (krb5_context ctx, const gchar *usr_name, const gchar *passwd,
- const gchar *in_tkt_service, krb5_creds *cred)
-{
- krb5_principal principal;
- krb5_get_init_creds_opt opt;
- krb5_error_code result;
-
- result = krb5_parse_name (ctx, usr_name, &principal);
- if (result)
- return E2K_KERBEROS_USER_UNKNOWN;
-
- krb5_get_init_creds_opt_init (&opt);
- krb5_get_init_creds_opt_set_tkt_life (&opt, 5*60);
- krb5_get_init_creds_opt_set_renew_life (&opt, 0);
- krb5_get_init_creds_opt_set_forwardable (&opt, 0);
- krb5_get_init_creds_opt_set_proxiable (&opt, 0);
-
- result = krb5_get_init_creds_password (ctx, cred, principal,
- (gchar *) passwd,
- NULL, NULL, 0,
- (gchar *) in_tkt_service, &opt);
- krb5_free_principal (ctx, principal);
-
- return krb5_result_to_e2k_kerberos_result (result);
-}
-
-/**
- * e2k_kerberos_change_password
- * @user: username
- * @domain: Windows (2000) domain name
- * @old_password: currrent password
- * @new_password: password to be changed to
- *
- * Changes the password for the given user
- *
- * Return value: an #E2kKerberosResult
- **/
-E2kKerberosResult
-e2k_kerberos_change_password (const gchar *user, const gchar *domain,
- const gchar *old_password, const gchar *new_password)
-{
- krb5_context ctx;
- krb5_creds creds;
- krb5_data res_code_string, res_string;
- E2kKerberosResult result;
- gint res_code;
-
- ctx = e2k_kerberos_context_new (domain);
- if (!ctx)
- return E2K_KERBEROS_FAILED;
-
- result = get_init_cred (ctx, user, old_password,
- "kadmin/changepw", &creds);
- if (result != E2K_KERBEROS_OK) {
- krb5_free_context (ctx);
- return result;
- }
-
- result = krb5_change_password (ctx, &creds, (gchar *)new_password,
- &res_code, &res_code_string, &res_string);
- krb5_free_cred_contents (ctx, &creds);
- krb5_free_data_contents (ctx, &res_code_string);
- krb5_free_data_contents (ctx, &res_string);
- krb5_free_context (ctx);
-
- if (result != 0)
- return krb5_result_to_e2k_kerberos_result (result);
- else if (res_code != 0)
- return E2K_KERBEROS_FAILED;
- else
- return E2K_KERBEROS_OK;
-}
-
-/**
- * e2k_kerberos_check_password:
- * @user: username
- * @domain: Windows (2000) domain name
- * @password: current password
- *
- * Checks if the password is valid, invalid, or expired
- *
- * Return value: %E2K_KERBEROS_OK, %E2K_KERBEROS_USER_UNKNOWN,
- * %E2K_KERBEROS_PASSWORD_INCORRECT, %E2K_KERBEROS_PASSWORD_EXPIRED,
- * or %E2K_KERBEROS_FAILED (for unknown errors)
- **/
-E2kKerberosResult
-e2k_kerberos_check_password (const gchar *user, const gchar *domain,
- const gchar *password)
-{
- krb5_context ctx;
- krb5_creds creds;
- E2kKerberosResult result;
-
- ctx = e2k_kerberos_context_new (domain);
- if (!ctx)
- return E2K_KERBEROS_FAILED;
-
- result = get_init_cred (ctx, user, password, NULL, &creds);
-
- krb5_free_context (ctx);
- if (result == E2K_KERBEROS_OK)
- krb5_free_cred_contents (ctx, &creds);
-
- return result;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2004 Novell, Inc. */
-
-#ifndef __E2K_KERBEROS_H__
-#define __E2K_KERBEROS_H__
-
-G_BEGIN_DECLS
-
-typedef enum {
- E2K_KERBEROS_OK,
- E2K_KERBEROS_USER_UNKNOWN,
- E2K_KERBEROS_PASSWORD_INCORRECT,
- E2K_KERBEROS_PASSWORD_EXPIRED,
- E2K_KERBEROS_PASSWORD_TOO_WEAK,
-
- E2K_KERBEROS_KDC_UNREACHABLE,
- E2K_KERBEROS_TIME_SKEW,
-
- E2K_KERBEROS_FAILED
-} E2kKerberosResult;
-
-E2kKerberosResult e2k_kerberos_check_password (const gchar *user,
- const gchar *domain,
- const gchar *password);
-
-E2kKerberosResult e2k_kerberos_change_password (const gchar *user,
- const gchar *domain,
- const gchar *old_password,
- const gchar *new_password);
-
-G_END_DECLS
-
-#endif /* __E2K_FREEBUSY_H__ */
+++ /dev/null
-NONE:INT,INT
-NONE:INT,STRING,STRING
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2003, 2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* e2k-operation.c: Cancellable operations */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include "e2k-operation.h"
-
-static GStaticMutex op_mutex = G_STATIC_MUTEX_INIT;
-static GHashTable *active_ops = NULL;
-
-/**
- * e2k_operation_init:
- * @op: an #E2kOperation
- *
- * This initializes the #E2kOperation pointed to by @op.
- * This should be called before passing @op to a cancellable function.
- **/
-void
-e2k_operation_init (E2kOperation *op)
-{
- g_return_if_fail (op != NULL);
-
- memset (op, 0, sizeof (E2kOperation));
-
- g_static_mutex_lock (&op_mutex);
- if (!active_ops)
- active_ops = g_hash_table_new (NULL, NULL);
- g_hash_table_insert (active_ops, op, op);
- g_static_mutex_unlock (&op_mutex);
-}
-
-/**
- * e2k_operation_free:
- * @op: an #E2kOperation
- *
- * This frees @op and removes it from the list of active operations.
- * It should be called after the function it was passed to returns.
- **/
-void
-e2k_operation_free (E2kOperation *op)
-{
- g_return_if_fail (op != NULL);
-
- g_static_mutex_lock (&op_mutex);
- g_hash_table_remove (active_ops, op);
- g_static_mutex_unlock (&op_mutex);
-}
-
-/**
- * e2k_operation_start:
- * @op: an #E2kOperation, or %NULL
- * @canceller: the callback to invoke if @op is cancelled
- * @owner: object that owns the operation
- * @data: data to pass to @canceller
- *
- * This starts a single cancellable operation using @op. If @op has
- * already been cancelled, this will invoke @canceller immediately.
- *
- * (If @op is %NULL, e2k_operation_start() is a no-op.)
- **/
-void
-e2k_operation_start (E2kOperation *op,
- E2kOperationCancelFunc canceller,
- gpointer owner,
- gpointer data)
-{
- if (!op)
- return;
-
- g_static_mutex_lock (&op_mutex);
-
- op->canceller = canceller;
- op->owner = owner;
- op->data = data;
-
- if (op->cancelled && op->canceller) {
- g_static_mutex_unlock (&op_mutex);
- op->canceller (op, op->owner, op->data);
- return;
- }
-
- g_static_mutex_unlock (&op_mutex);
-}
-
-/**
- * e2k_operation_finish:
- * @op: an #E2kOperation, or %NULL
- *
- * This finishes the current cancellable operation on @op. Attempting
- * to cancel @op after this point will have no effect until another
- * operation is started on it.
- *
- * (If @op is %NULL, e2k_operation_finish() is a no-op.)
- **/
-void
-e2k_operation_finish (E2kOperation *op)
-{
- if (!op)
- return;
-
- g_static_mutex_lock (&op_mutex);
- op->canceller = NULL;
- op->owner = NULL;
- op->data = NULL;
- g_static_mutex_unlock (&op_mutex);
-}
-
-/**
- * e2k_operation_cancel:
- * @op: an #E2kOperation
- *
- * This cancels @op, invoking its cancellation callback. If @op is not
- * an active operation, or has already been cancelled, this has no
- * effect.
- **/
-void
-e2k_operation_cancel (E2kOperation *op)
-{
- g_return_if_fail (op != NULL);
-
- g_static_mutex_lock (&op_mutex);
-
- if (!g_hash_table_lookup (active_ops, op) || op->cancelled) {
- g_static_mutex_unlock (&op_mutex);
- return;
- }
-
- g_hash_table_remove (active_ops, op);
- op->cancelled = TRUE;
- g_static_mutex_unlock (&op_mutex);
-
- if (op->canceller)
- op->canceller (op, op->owner, op->data);
-}
-
-/**
- * e2k_operation_is_cancelled:
- * @op: an #E2kOperation (or %NULL)
- *
- * Checks if @op has been cancelled. Should only be called while @op
- * is active.
- *
- * Return value: whether or not @op has been cancelled.
- **/
-gboolean
-e2k_operation_is_cancelled (E2kOperation *op)
-{
- return op && op->cancelled;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2003, 2004 Novell, Inc. */
-
-#ifndef __E2K_OPERATION_H__
-#define __E2K_OPERATION_H__
-
-#include <string.h>
-#include "e2k-types.h"
-
-G_BEGIN_DECLS
-
-typedef void (*E2kOperationCancelFunc) (E2kOperation *op, gpointer owner, gpointer data);
-
-struct _E2kOperation {
- /*< private >*/
- gboolean cancelled;
-
- E2kOperationCancelFunc canceller;
- gpointer owner, data;
-};
-
-/* These are called by the caller of the cancellable function. */
-void e2k_operation_init (E2kOperation *op);
-void e2k_operation_free (E2kOperation *op);
-
-/* These are called by the cancellable function itself. */
-void e2k_operation_start (E2kOperation *op,
- E2kOperationCancelFunc canceller,
- gpointer owner,
- gpointer data);
-void e2k_operation_finish (E2kOperation *op);
-
-void e2k_operation_cancel (E2kOperation *op);
-gboolean e2k_operation_is_cancelled (E2kOperation *op);
-
-G_END_DECLS
-
-#endif /* __E2k_OPERATION_H__ */
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-path.c
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include <config.h>
-
-#include <sys/types.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-
-#include "e2k-path.h"
-
-#define SUBFOLDER_DIR_NAME "subfolders"
-#define SUBFOLDER_DIR_NAME_LEN 10
-
-/**
- * e_path_to_physical:
- * @prefix: a prefix to prepend to the path, or %NULL
- * @path: the virtual path to convert to a filesystem path.
- *
- * This converts the "virtual" path @path into an expanded form that
- * allows a given name to refer to both a file and a directory. The
- * expanded path will have a "subfolders" directory inserted between
- * each path component. If the path ends with "/", the returned
- * physical path will end with "/subfolders"
- *
- * If @prefix is non-%NULL, it will be prepended to the returned path.
- *
- * Return value: the expanded path
- **/
-gchar *
-e_path_to_physical (const gchar *prefix, const gchar *vpath)
-{
- const gchar *p, *newp;
- gchar *dp;
- gchar *ppath;
- gint ppath_len;
- gint prefix_len;
-
- while (*vpath == '/')
- vpath++;
- if (!prefix)
- prefix = "";
-
- /* Calculate the length of the real path. */
- ppath_len = strlen (vpath);
- ppath_len++; /* For the ending zero. */
-
- prefix_len = strlen (prefix);
- ppath_len += prefix_len;
- ppath_len++; /* For the separating slash. */
-
- /* Take account of the fact that we need to translate every
- * separator into `subfolders/'.
- */
- p = vpath;
- while (1) {
- newp = strchr (p, '/');
- if (newp == NULL)
- break;
-
- ppath_len += SUBFOLDER_DIR_NAME_LEN;
- ppath_len++; /* For the separating slash. */
-
- /* Skip consecutive slashes. */
- while (*newp == '/')
- newp++;
-
- p = newp;
- };
-
- ppath = g_malloc (ppath_len);
- dp = ppath;
-
- memcpy (dp, prefix, prefix_len);
- dp += prefix_len;
- *(dp++) = '/';
-
- /* Copy the mangled path. */
- p = vpath;
- while (1) {
- newp = strchr (p, '/');
- if (newp == NULL) {
- strcpy (dp, p);
- break;
- }
-
- memcpy (dp, p, newp - p + 1); /* `+ 1' to copy the slash too. */
- dp += newp - p + 1;
-
- memcpy (dp, SUBFOLDER_DIR_NAME, SUBFOLDER_DIR_NAME_LEN);
- dp += SUBFOLDER_DIR_NAME_LEN;
-
- *(dp++) = '/';
-
- /* Skip consecutive slashes. */
- while (*newp == '/')
- newp++;
-
- p = newp;
- }
-
- return ppath;
-}
-
-static gboolean
-find_folders_recursive (const gchar *physical_path, const gchar *path,
- EPathFindFoldersCallback callback, gpointer data)
-{
- GDir *dir;
- gchar *subfolder_directory_path;
- gboolean ok;
-
- if (*path) {
- if (!callback (physical_path, path, data))
- return FALSE;
-
- subfolder_directory_path = g_strdup_printf ("%s/%s", physical_path, SUBFOLDER_DIR_NAME);
- } else {
- /* On the top level, we have no folders and,
- * consequently, no subfolder directory.
- */
-
- subfolder_directory_path = g_strdup (physical_path);
- }
-
- /* Now scan the subfolders and load them. */
- dir = g_dir_open (subfolder_directory_path, 0, NULL);
- if (dir == NULL) {
- g_free (subfolder_directory_path);
- return TRUE;
- }
-
- ok = TRUE;
- while (ok) {
- struct stat file_stat;
- const gchar *dirent;
- gchar *file_path;
- gchar *new_path;
-
- dirent = g_dir_read_name (dir);
- if (dirent == NULL)
- break;
-
- file_path = g_strdup_printf ("%s/%s", subfolder_directory_path,
- dirent);
-
- if (g_stat (file_path, &file_stat) < 0 ||
- ! S_ISDIR (file_stat.st_mode)) {
- g_free (file_path);
- continue;
- }
-
- new_path = g_strdup_printf ("%s/%s", path, dirent);
-
- ok = find_folders_recursive (file_path, new_path, callback, data);
-
- g_free (file_path);
- g_free (new_path);
- }
-
- g_dir_close (dir);
- g_free (subfolder_directory_path);
-
- return ok;
-}
-
-/**
- * e_path_find_folders:
- * @prefix: directory to start from
- * @callback: Callback to invoke on each folder
- * @data: Data for @callback
- *
- * Walks the folder tree starting at @prefix and calls @callback
- * on each folder.
- *
- * Return value: %TRUE on success, %FALSE if an error occurs at any point
- **/
-gboolean
-e_path_find_folders (const gchar *prefix,
- EPathFindFoldersCallback callback,
- gpointer data)
-{
- return find_folders_recursive (prefix, "", callback, data);
-}
-
-/**
- * e_path_rmdir:
- * @prefix: a prefix to prepend to the path, or %NULL
- * @path: the virtual path to convert to a filesystem path.
- *
- * This removes the directory pointed to by @prefix and @path
- * and attempts to remove its parent "subfolders" directory too
- * if it's empty.
- *
- * Return value: -1 (with errno set) if it failed to rmdir the
- * specified directory. 0 otherwise, whether or not it removed
- * the parent directory.
- **/
-gint
-e_path_rmdir (const gchar *prefix, const gchar *vpath)
-{
- gchar *physical_path, *p;
-
- /* Remove the directory itself */
- physical_path = e_path_to_physical (prefix, vpath);
- if (g_rmdir (physical_path) == -1) {
- g_free (physical_path);
- return -1;
- }
-
- /* Attempt to remove its parent "subfolders" directory,
- * ignoring errors since it might not be empty.
- */
-
- p = strrchr (physical_path, '/');
- if (p[1] == '\0') {
- g_free (physical_path);
- return 0;
- }
- *p = '\0';
- p = strrchr (physical_path, '/');
- if (!p || strcmp (p + 1, SUBFOLDER_DIR_NAME) != 0) {
- g_free (physical_path);
- return 0;
- }
-
- g_rmdir (physical_path);
- g_free (physical_path);
- return 0;
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef __E_PATH__
-#define __E_PATH__
-
-#include <glib.h>
-
-/* FIXME: deprecated
- This is used exclusively for the legacy imap cache code. DO NOT use this in any new code */
-
-typedef gboolean (*EPathFindFoldersCallback) (const gchar *physical_path,
- const gchar *path,
- gpointer user_data);
-
-gchar * e_path_to_physical (const gchar *prefix, const gchar *vpath);
-
-gboolean e_path_find_folders (const gchar *prefix,
- EPathFindFoldersCallback callback,
- gpointer data);
-
-gint e_path_rmdir (const gchar *prefix, const gchar *vpath);
-#endif /* __E_PATH__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2001-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "e2k-properties.h"
-#include "e2k-propnames.h"
-#include "e2k-utils.h"
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <libxml/xmlmemory.h>
-
-struct E2kProperties {
- GHashTable *set, *removed;
-};
-
-typedef struct {
- gchar *name;
- const gchar *namespace;
- const gchar *short_name;
-
- E2kPropType type;
- guint32 proptag;
-} E2kPropInfo;
-
-static GHashTable *known_properties;
-static GStaticMutex known_properties_lock = G_STATIC_MUTEX_INIT;
-
-/**
- * e2k_properties_new:
- *
- * Creates a new (empty) #E2kProperties structure
- *
- * Return value: the structure
- **/
-E2kProperties *
-e2k_properties_new (void)
-{
- E2kProperties *props;
-
- props = g_new0 (E2kProperties, 1);
- props->set = g_hash_table_new (g_str_hash, g_str_equal);
- props->removed = g_hash_table_new (g_str_hash, g_str_equal);
-
- return props;
-}
-
-static void
-copy_prop (gpointer key, gpointer value, gpointer data)
-{
- const gchar *name = key;
- GHashTable *props_copy = data;
- gpointer value_copy;
- E2kPropInfo *pi;
-
- g_static_mutex_lock (&known_properties_lock);
- pi = g_hash_table_lookup (known_properties, name);
- g_static_mutex_unlock (&known_properties_lock);
-
- switch (pi->type) {
- case E2K_PROP_TYPE_BINARY_ARRAY:
- {
- GPtrArray *orig = value, *copy;
- GByteArray *new, *old;
- gint i;
-
- copy = g_ptr_array_new ();
- for (i = 0; i < orig->len; i++) {
- old = orig->pdata[i];
- new = g_byte_array_new ();
- g_byte_array_append (new, old->data, old->len);
- g_ptr_array_add (copy, new);
- }
- value_copy = copy;
- break;
- }
-
- case E2K_PROP_TYPE_STRING_ARRAY:
- {
- GPtrArray *orig = value, *copy;
- gint i;
-
- copy = g_ptr_array_new ();
- for (i = 0; i < orig->len; i++)
- g_ptr_array_add (copy, g_strdup (orig->pdata[i]));
- value_copy = copy;
- break;
- }
-
- case E2K_PROP_TYPE_BINARY:
- {
- GByteArray *orig = value, *copy;
-
- copy = g_byte_array_new ();
- g_byte_array_append (copy, orig->data, orig->len);
- value_copy = copy;
- break;
- }
-
- case E2K_PROP_TYPE_XML:
- value_copy = xmlCopyNode (value, TRUE);
- break;
-
- case E2K_PROP_TYPE_STRING:
- default:
- value_copy = g_strdup (value);
- break;
- }
-
- g_hash_table_insert (props_copy, pi->name, value_copy);
-}
-
-/**
- * e2k_properties_copy:
- * @props: an #E2kProperties
- *
- * Performs a deep copy of @props
- *
- * Return value: a new copy of @props
- **/
-E2kProperties *
-e2k_properties_copy (E2kProperties *props)
-{
- E2kProperties *copy;
-
- g_return_val_if_fail (props != NULL, NULL);
-
- copy = e2k_properties_new ();
- g_hash_table_foreach (props->set, copy_prop, copy->set);
- g_hash_table_foreach (props->removed, copy_prop, copy->removed);
- return copy;
-}
-
-static void
-free_prop (E2kPropInfo *pi, gpointer value)
-{
- if (!value)
- return;
-
- switch (pi->type) {
- case E2K_PROP_TYPE_BINARY_ARRAY:
- {
- GPtrArray *array = value;
- gint i;
-
- for (i = 0; i < array->len; i++)
- g_byte_array_free (array->pdata[i], TRUE);
- g_ptr_array_free (array, TRUE);
- break;
- }
-
- case E2K_PROP_TYPE_STRING_ARRAY:
- case E2K_PROP_TYPE_INT_ARRAY:
- {
- GPtrArray *array = value;
- gint i;
-
- for (i = 0; i < array->len; i++)
- g_free (array->pdata[i]);
- g_ptr_array_free (array, TRUE);
- break;
- }
-
- case E2K_PROP_TYPE_BINARY:
- g_byte_array_free (value, TRUE);
- break;
-
- case E2K_PROP_TYPE_XML:
- xmlFreeNode (value);
- break;
-
- case E2K_PROP_TYPE_STRING:
- default:
- g_free (value);
- break;
- }
-}
-
-static void
-properties_free_cb (gpointer key, gpointer value, gpointer data)
-{
- E2kPropInfo *pi;
-
- g_static_mutex_lock (&known_properties_lock);
- pi = g_hash_table_lookup (known_properties, key);
- g_static_mutex_unlock (&known_properties_lock);
- if (pi)
- free_prop (pi, value);
-}
-
-/**
- * e2k_properties_free:
- * @props: an #E2kProperties
- *
- * Frees @props and all of the properties it contains.
- **/
-void
-e2k_properties_free (E2kProperties *props)
-{
- g_return_if_fail (props != NULL);
-
- g_hash_table_foreach (props->set, properties_free_cb, NULL);
- g_hash_table_destroy (props->set);
- g_hash_table_destroy (props->removed);
- g_free (props);
-}
-
-/**
- * e2k_properties_get_prop:
- * @props: an #E2kProperties
- * @propname: a property name
- *
- * Retrieves the value of @propname in @props.
- *
- * Return value: the value of @propname in @props, or %NULL if it is
- * not set. The caller should not free the value; it is owned by
- * @props.
- **/
-gpointer
-e2k_properties_get_prop (E2kProperties *props, const gchar *propname)
-{
- g_return_val_if_fail (props != NULL, NULL);
-
- return g_hash_table_lookup (props->set, propname);
-}
-
-/**
- * e2k_properties_empty:
- * @props: an #E2kProperties
- *
- * Tests if @props is empty.
- *
- * Return value: %TRUE if @props has no properties set, %FALSE if it
- * has at least one value set.
- **/
-gboolean
-e2k_properties_empty (E2kProperties *props)
-{
- g_return_val_if_fail (props != NULL, TRUE);
-
- return g_hash_table_size (props->set) == 0;
-}
-
-extern gchar e2k_des_key[8];
-
-static E2kPropInfo *
-get_propinfo (const gchar *propname, E2kPropType type)
-{
- E2kPropInfo *pi;
-
- g_static_mutex_lock (&known_properties_lock);
- if (!known_properties)
- known_properties = g_hash_table_new (g_str_hash, g_str_equal);
-
- pi = g_hash_table_lookup (known_properties, propname);
- if (pi) {
- if (pi->type == E2K_PROP_TYPE_UNKNOWN)
- pi->type = type;
- g_static_mutex_unlock (&known_properties_lock);
- return pi;
- }
-
- pi = g_new (E2kPropInfo, 1);
- pi->name = g_strdup (propname);
- pi->namespace = e2k_prop_namespace_name (pi->name);
- pi->short_name = e2k_prop_property_name (pi->name);
- pi->type = type;
-
- if (pi->short_name[0] == 'x')
- pi->proptag = strtoul (pi->short_name + 1, NULL, 16);
- else
- pi->proptag = 0;
-
- g_hash_table_insert (known_properties, pi->name, pi);
-
- g_static_mutex_unlock (&known_properties_lock);
-
- return pi;
-}
-
-/**
- * e2k_properties_set_string:
- * @props: an #E2kProperties
- * @propname: the name of a property
- * @value: an allocated string
- *
- * Sets @propname in @props to @value. @props assumes ownership of
- * @value.
- **/
-
-/**
- * e2k_properties_set_string_array:
- * @props: an #E2kProperties
- * @propname: the name of a property
- * @value: an array of allocated strings
- *
- * Sets @propname in @props to @value. @props assumes ownership of
- * @value.
- **/
-
-/**
- * e2k_properties_set_binary:
- * @props: an #E2kProperties
- * @propname: the name of a property
- * @value: a byte array
- *
- * Sets @propname in @props to @value. @props assumes ownership of
- * @value.
- **/
-
-/**
- * e2k_properties_set_binary_array:
- * @props: an #E2kProperties
- * @propname: the name of a property
- * @value: an array of byte arrays
- *
- * Sets @propname in @props to @value. @props assumes ownership of
- * @value.
- **/
-
-/**
- * e2k_properties_set_xml:
- * @props: an #E2kProperties
- * @propname: the name of a property
- * @value: an #xmlNode
- *
- * Sets @propname in @props to @value. @props assumes ownership of
- * @value.
- **/
-
-/**
- * e2k_properties_set_int:
- * @props: an #E2kProperties
- * @propname: the name of a property
- * @value: an integer
- *
- * Sets @propname in @props to @value.
- **/
-
-/**
- * e2k_properties_set_int_array:
- * @props: an #E2kProperties
- * @propname: the name of a property
- * @value: an array of integers
- *
- * Sets @propname in @props to @value. @props assumes ownership of
- * @value.
- **/
-
-/**
- * e2k_properties_set_float:
- * @props: an #E2kProperties
- * @propname: the name of a property
- * @value: a floating-point value
- *
- * Sets @propname in @props to @value.
- **/
-
-/**
- * e2k_properties_set_bool:
- * @props: an #E2kProperties
- * @propname: the name of a property
- * @value: a boolean value
- *
- * Sets @propname in @props to @value.
- **/
-
-/**
- * e2k_properties_set_date:
- * @props: an #E2kProperties
- * @propname: the name of a property
- * @value: an allocated string containing an Exchange timestamp
- *
- * Sets @propname in @props to @value. @props assumes ownership of
- * @value.
- **/
-
-#define E2K_PROPERTIES_SETTER(fname, valuetype, pitype, data) \
-void \
-e2k_properties_set_ ## fname (E2kProperties *props, \
- const gchar *propname, \
- valuetype value) \
-{ \
- E2kPropInfo *pi; \
- \
- pi = get_propinfo (propname, E2K_PROP_TYPE_ ## pitype); \
- free_prop (pi, g_hash_table_lookup (props->set, pi->name)); \
- g_hash_table_insert (props->set, pi->name, data); \
- g_hash_table_remove (props->removed, pi->name); \
-}
-
-E2K_PROPERTIES_SETTER (string, gchar *, STRING, value)
-E2K_PROPERTIES_SETTER (string_array, GPtrArray *, STRING_ARRAY, value)
-E2K_PROPERTIES_SETTER (binary, GByteArray *, BINARY, value)
-E2K_PROPERTIES_SETTER (binary_array, GPtrArray *, BINARY_ARRAY, value)
-E2K_PROPERTIES_SETTER (xml, xmlNode *, XML, value)
-
-E2K_PROPERTIES_SETTER (int, int, INT, g_strdup_printf ("%d", value))
-E2K_PROPERTIES_SETTER (int_array, GPtrArray *, INT_ARRAY, value)
-E2K_PROPERTIES_SETTER (float, float, FLOAT, g_strdup_printf ("%f", value))
-E2K_PROPERTIES_SETTER (bool, gboolean, BOOL, g_strdup_printf ("%d", value != FALSE))
-E2K_PROPERTIES_SETTER (date, gchar *, DATE, value)
-
-/**
- * e2k_properties_set_type_as_string:
- * @props: an #E2kProperties
- * @propname: the name of a property
- * @type: the type of @value
- * @value: an allocated string
- *
- * Sets @propname in @props to @value, but with type @type. @props
- * assumes ownership of @value.
- **/
-
-/**
- * e2k_properties_set_type_as_string_array:
- * @props: an #E2kProperties
- * @propname: the name of a property
- * @type: the type of @value
- * @value: an array of allocated strings
- *
- * Sets @propname in @props to @value, but with type @type. @props
- * assumes ownership of @value.
- **/
-
-#define E2K_PROPERTIES_SETTER_AS(fname, valuetype) \
-void \
-e2k_properties_set_type_as_ ## fname (E2kProperties *props, \
- const gchar *propname, \
- E2kPropType type, \
- valuetype value) \
-{ \
- E2kPropInfo *pi; \
- \
- pi = get_propinfo (propname, type); \
- free_prop (pi, g_hash_table_lookup (props->set, pi->name)); \
- g_hash_table_insert (props->set, pi->name, value); \
- g_hash_table_remove (props->removed, pi->name); \
-}
-
-E2K_PROPERTIES_SETTER_AS (string, gchar *)
-E2K_PROPERTIES_SETTER_AS (string_array, GPtrArray *)
-
-/**
- * e2k_properties_remove:
- * @props: an #E2kProperties
- * @propname: the name of a property
- *
- * Marks @propname removed in @props, so that the corresponding
- * property will be removed from the object on the server if @props is
- * used in a PROPPATCH. If the property was formerly set in @props,
- * this frees the old value.
- **/
-void
-e2k_properties_remove (E2kProperties *props, const gchar *propname)
-{
- E2kPropInfo *pi;
-
- pi = get_propinfo (propname, E2K_PROP_TYPE_UNKNOWN);
- free_prop (pi, g_hash_table_lookup (props->set, pi->name));
- g_hash_table_remove (props->set, pi->name);
- g_hash_table_insert (props->removed, pi->name, NULL);
-}
-
-struct foreach_data {
- E2kPropertiesForeachFunc callback;
- gpointer user_data;
-};
-
-static void
-foreach_callback (gpointer key, gpointer value, gpointer data)
-{
- struct foreach_data *fd = data;
- E2kPropInfo *pi;
-
- g_static_mutex_lock (&known_properties_lock);
- pi = g_hash_table_lookup (known_properties, key);
- g_static_mutex_unlock (&known_properties_lock);
- if (pi)
- fd->callback (pi->name, pi->type, value, fd->user_data);
-}
-
-/**
- * e2k_properties_foreach:
- * @props: an #E2kProperties
- * @callback: callback function to call for each set property
- * @user_data: data to pass to @callback
- *
- * Calls @callback once for each property that is set in @props (in
- * unspecified order), passing it the name of the property, the
- * property's type, its value, and @user_data.
- **/
-void
-e2k_properties_foreach (E2kProperties *props,
- E2kPropertiesForeachFunc callback,
- gpointer user_data)
-{
- struct foreach_data fd;
-
- g_return_if_fail (props != NULL);
-
- fd.callback = callback;
- fd.user_data = user_data;
-
- g_hash_table_foreach (props->set, foreach_callback, &fd);
-}
-
-/**
- * e2k_properties_foreach_removed:
- * @props: an #E2kProperties
- * @callback: callback function to call for each set property
- * @user_data: data to pass to @callback
- *
- * Calls @callback once for each property marked removed in @props (in
- * unspecified order), passing it the name of the property, the
- * property's type (if known), a %NULL value, and @user_data.
- **/
-void
-e2k_properties_foreach_removed (E2kProperties *props,
- E2kPropertiesForeachFunc callback,
- gpointer user_data)
-{
- struct foreach_data fd;
-
- g_return_if_fail (props != NULL);
-
- fd.callback = callback;
- fd.user_data = user_data;
-
- g_hash_table_foreach (props->removed, foreach_callback, &fd);
-}
-
-struct foreach_namespace_data {
- E2kPropertiesForeachNamespaceFunc callback;
- gpointer user_data;
- gboolean need_array_namespace, need_type_namespace;
- GHashTable *seen_namespaces;
-};
-
-static void
-foreach_namespace_callback (gpointer key, gpointer value, gpointer data)
-{
- struct foreach_namespace_data *fnd = data;
- E2kPropInfo *pi;
- const gchar *name;
-
- g_static_mutex_lock (&known_properties_lock);
- pi = g_hash_table_lookup (known_properties, key);
- g_static_mutex_unlock (&known_properties_lock);
- if (!pi)
- return;
-
- name = e2k_prop_namespace_name (pi->name);
- if (!g_hash_table_lookup (fnd->seen_namespaces, name)) {
- g_hash_table_insert (fnd->seen_namespaces,
- (gchar *)name, (gchar *)name);
- fnd->callback (name, e2k_prop_namespace_abbrev (pi->name),
- fnd->user_data);
- }
-
- switch (pi->type) {
- case E2K_PROP_TYPE_STRING_ARRAY:
- case E2K_PROP_TYPE_BINARY_ARRAY:
- case E2K_PROP_TYPE_INT_ARRAY:
- fnd->need_array_namespace = TRUE;
- /* fall through */
-
- case E2K_PROP_TYPE_BINARY:
- case E2K_PROP_TYPE_INT:
- case E2K_PROP_TYPE_BOOL:
- case E2K_PROP_TYPE_FLOAT:
- case E2K_PROP_TYPE_DATE:
- fnd->need_type_namespace = TRUE;
- break;
-
- default:
- break;
- }
-}
-
-/**
- * e2k_properties_foreach_namespace:
- * @props: an #E2kProperties
- * @callback: callback function to call for each namespace
- * @user_data: data to pass to @callback
- *
- * Calls @callback once for each unique namespace used by the
- * properties (set or removed) in @props, passing it the name of the
- * namespace, its standard abbreviation, and @user_data.
- **/
-void
-e2k_properties_foreach_namespace (E2kProperties *props,
- E2kPropertiesForeachNamespaceFunc callback,
- gpointer user_data)
-{
- struct foreach_namespace_data fnd;
-
- g_return_if_fail (props != NULL);
-
- fnd.callback = callback;
- fnd.user_data = user_data;
- fnd.need_array_namespace = FALSE;
- fnd.need_type_namespace = FALSE;
- fnd.seen_namespaces = g_hash_table_new (NULL, NULL);
-
- g_hash_table_foreach (props->set, foreach_namespace_callback, &fnd);
- g_hash_table_foreach (props->removed, foreach_namespace_callback, &fnd);
-
- if (fnd.need_type_namespace)
- callback (E2K_NS_TYPE, 'T', user_data);
- if (fnd.need_array_namespace)
- callback ("xml:", 'X', user_data);
-
- g_hash_table_destroy (fnd.seen_namespaces);
-}
-
-static GHashTable *namespaces;
-static gint next_namespace = 'a';
-static GStaticMutex namespaces_lock = G_STATIC_MUTEX_INIT;
-
-static const gchar *
-get_div (const gchar *propname)
-{
- const gchar *div;
-
- div = strrchr (propname, '/');
- if (div)
- return div;
- return strrchr (propname, ':');
-}
-
-static gint
-prop_equal (gconstpointer v1, gconstpointer v2)
-{
- const gchar *s1 = (const gchar *)v1, *s2 = (const gchar *)v2;
- const gchar *d1 = get_div (s1), *d2 = get_div (s2);
-
- return (d1 - s1 == d2 - s2) && !g_ascii_strncasecmp (s1, s2, d1 - s1);
-}
-
-static guint
-prop_hash (gconstpointer v)
-{
- const gchar *d = get_div (v);
- const gchar *p = v;
- guint h = g_ascii_tolower (*p);
-
- for (p += 1; p < d; p++)
- h = (h << 5) - h + *p;
- return h;
-}
-
-static void
-setup_namespaces (void)
-{
- namespaces = g_hash_table_new (prop_hash, prop_equal);
- g_hash_table_insert (namespaces, (gpointer) "DAV", GINT_TO_POINTER ('D'));
-}
-
-/**
- * e2k_prop_namespace_name:
- * @prop: the name of a property
- *
- * Splits out the namespace portion of @prop
- *
- * Return value: the URI of @prop's namespace
- **/
-const gchar *
-e2k_prop_namespace_name (const gchar *prop)
-{
- const gchar *div = get_div (prop);
- gpointer key, value;
- gchar *name;
-
- g_static_mutex_lock (&namespaces_lock);
- if (!namespaces)
- setup_namespaces ();
-
- if (g_hash_table_lookup_extended (namespaces, prop, &key, &value)) {
- g_static_mutex_unlock (&namespaces_lock);
- return key;
- }
-
- name = g_strndup (prop, div - prop + 1);
- g_hash_table_insert (namespaces, name, GINT_TO_POINTER (next_namespace));
- next_namespace++;
- g_static_mutex_unlock (&namespaces_lock);
- return name;
-}
-
-/**
- * e2k_prop_namespace_abbrev:
- * @prop: the name of a property
- *
- * Splits out the namespace portion of @prop and assigns a unique
- * abbreviation for it.
- *
- * Return value: the abbreviation used for prop's namespace
- **/
-gchar
-e2k_prop_namespace_abbrev (const gchar *prop)
-{
- const gchar *div = get_div (prop);
- gpointer key, value;
- gchar *name, res;
-
- g_static_mutex_lock (&namespaces_lock);
- if (!namespaces)
- setup_namespaces ();
-
- if (g_hash_table_lookup_extended (namespaces, prop, &key, &value)) {
- g_static_mutex_unlock (&namespaces_lock);
- return GPOINTER_TO_INT (value);
- }
-
- name = g_strndup (prop, div - prop + 1);
- g_hash_table_insert (namespaces, name, GINT_TO_POINTER (next_namespace));
- res = next_namespace++;
- g_static_mutex_unlock (&namespaces_lock);
-
- return res;
-}
-
-/**
- * e2k_prop_property_name:
- * @prop: the name of a property
- *
- * Splits out the non-namespace portion of @prop
- *
- * Return value: the non-namespaced name of @prop
- **/
-const gchar *
-e2k_prop_property_name (const gchar *prop)
-{
- return get_div (prop) + 1;
-}
-
-/**
- * e2k_prop_proptag:
- * @prop: the name of a MAPI property
- *
- * Computes the MAPI proptag value of @prop, which must be the name
- * of a MAPI property.
- *
- * Return value: the MAPI proptag value
- **/
-guint32
-e2k_prop_proptag (const gchar *prop)
-{
- E2kPropInfo *pi;
-
- pi = get_propinfo (prop, E2K_PROP_TYPE_UNKNOWN);
- return pi->proptag;
-}
-
-/**
- * e2k_proptag_prop:
- * @proptag: a MAPI property
- *
- * Computes the WebDAV property name of the property with the
- * given proptag.
- *
- * Return value: the WebDAV property name associated with @proptag
- **/
-const gchar *
-e2k_proptag_prop (guint32 proptag)
-{
- E2kPropInfo *pi;
- gchar *tmpname;
-
- tmpname = g_strdup_printf (E2K_NS_MAPI_PROPTAG "x%08x",
- (unsigned)proptag);
-
- pi = get_propinfo (tmpname, E2K_PROP_TYPE_UNKNOWN);
- g_free (tmpname);
- return pi->name;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __E2K_PROPERTIES_H__
-#define __E2K_PROPERTIES_H__
-
-#include <glib.h>
-#include <libxml/tree.h>
-
-typedef struct E2kProperties E2kProperties;
-
-typedef enum {
- E2K_PROP_TYPE_UNKNOWN,
-
- E2K_PROP_TYPE_STRING,
- E2K_PROP_TYPE_BINARY,
- E2K_PROP_TYPE_STRING_ARRAY,
- E2K_PROP_TYPE_BINARY_ARRAY,
- E2K_PROP_TYPE_XML,
-
- /* These are all stored as STRING or STRING_ARRAY */
- E2K_PROP_TYPE_INT,
- E2K_PROP_TYPE_INT_ARRAY,
- E2K_PROP_TYPE_BOOL,
- E2K_PROP_TYPE_FLOAT,
- E2K_PROP_TYPE_DATE
-} E2kPropType;
-
-#define E2K_PROP_TYPE_IS_ARRAY(type) (((type) == E2K_PROP_TYPE_STRING_ARRAY) || ((type) == E2K_PROP_TYPE_BINARY_ARRAY) || ((type) == E2K_PROP_TYPE_INT_ARRAY))
-
-E2kProperties *e2k_properties_new (void);
-E2kProperties *e2k_properties_copy (E2kProperties *props);
-void e2k_properties_free (E2kProperties *props);
-
-gpointer e2k_properties_get_prop (E2kProperties *props,
- const gchar *propname);
-gboolean e2k_properties_empty (E2kProperties *props);
-
-void e2k_properties_set_string (E2kProperties *props,
- const gchar *propname,
- gchar *value);
-void e2k_properties_set_string_array (E2kProperties *props,
- const gchar *propname,
- GPtrArray *value);
-void e2k_properties_set_binary (E2kProperties *props,
- const gchar *propname,
- GByteArray *value);
-void e2k_properties_set_binary_array (E2kProperties *props,
- const gchar *propname,
- GPtrArray *value);
-void e2k_properties_set_int (E2kProperties *props,
- const gchar *propname,
- gint value);
-void e2k_properties_set_int_array (E2kProperties *props,
- const gchar *propname,
- GPtrArray *value);
-void e2k_properties_set_xml (E2kProperties *props,
- const gchar *propname,
- xmlNode *value);
-void e2k_properties_set_bool (E2kProperties *props,
- const gchar *propname,
- gboolean value);
-void e2k_properties_set_float (E2kProperties *props,
- const gchar *propname,
- gfloat value);
-void e2k_properties_set_date (E2kProperties *props,
- const gchar *propname,
- gchar *value);
-
-void e2k_properties_set_type_as_string (E2kProperties *props,
- const gchar *propname,
- E2kPropType type,
- gchar *value);
-void e2k_properties_set_type_as_string_array (E2kProperties *props,
- const gchar *propname,
- E2kPropType type,
- GPtrArray *value);
-
-void e2k_properties_remove (E2kProperties *props,
- const gchar *propname);
-
-typedef void (*E2kPropertiesForeachFunc) (const gchar *propname,
- E2kPropType type,
- gpointer value,
- gpointer user_data);
-void e2k_properties_foreach (E2kProperties *props,
- E2kPropertiesForeachFunc callback,
- gpointer user_data);
-void e2k_properties_foreach_removed (E2kProperties *props,
- E2kPropertiesForeachFunc callback,
- gpointer user_data);
-
-typedef void(*E2kPropertiesForeachNamespaceFunc)(const gchar *namespace,
- gchar abbrev,
- gpointer user_data);
-void e2k_properties_foreach_namespace (E2kProperties *props,
- E2kPropertiesForeachNamespaceFunc callback,
- gpointer user_data);
-
-const gchar *e2k_prop_namespace_name (const gchar *prop);
-gchar e2k_prop_namespace_abbrev (const gchar *prop);
-const gchar *e2k_prop_property_name (const gchar *prop);
-
-guint32 e2k_prop_proptag (const gchar *prop);
-const gchar *e2k_proptag_prop (guint32 proptag);
-
-#define E2K_PROPTAG_TYPE(proptag) (proptag & 0xFFFF)
-#define E2K_PROPTAG_ID(proptag) (proptag & 0xFFFF0000)
-
-#define E2K_PT_SHORT 0x0002
-#define E2K_PT_LONG 0x0003
-#define E2K_PT_ERROR 0x000a
-#define E2K_PT_BOOLEAN 0x000b
-#define E2K_PT_OBJECT 0x000d
-#define E2K_PT_LONGLONG 0x0014
-#define E2K_PT_STRING8 0x001e
-#define E2K_PT_UNICODE 0x001f
-#define E2K_PT_SYSTIME 0x0040
-#define E2K_PT_BINARY 0x0102
-
-#endif /* __E2K_PROPERTIES_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2001-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-struct mapi_proptag {
- char *proptag, *name;
-} mapi_proptags[] = {
-@AUTOGENERATE@
-};
-static int nmapi_proptags = sizeof (mapi_proptags) / sizeof (mapi_proptags[0]);
-
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2002-2004 Novell, Inc. */
-
-#ifndef __E2K_PROPNAMES_H__
-#define __E2K_PROPNAMES_H__
-
-#define E2K_NS_DAV "DAV:"
-#define E2K_PR_DAV_CONTENT_CLASS "DAV:contentclass"
-#define E2K_PR_DAV_CONTENT_LENGTH "DAV:getcontentlength"
-#define E2K_PR_DAV_CONTENT_TYPE "DAV:getcontenttype"
-#define E2K_PR_DAV_CREATION_DATE "DAV:creationdate"
-#define E2K_PR_DAV_DISPLAY_NAME "DAV:displayname"
-#define E2K_PR_DAV_LAST_MODIFIED "DAV:getlastmodified"
-#define E2K_PR_DAV_HAS_SUBS "DAV:hassubs"
-#define E2K_PR_DAV_HREF "DAV:href"
-#define E2K_PR_DAV_IS_COLLECTION "DAV:iscollection"
-#define E2K_PR_DAV_IS_HIDDEN "DAV:ishidden"
-#define E2K_PR_DAV_LOCATION "DAV:location"
-#define E2K_PR_DAV_UID "DAV:uid"
-#define E2K_PR_DAV_VISIBLE_COUNT "DAV:visiblecount"
-
-#define E2K_NS_CALENDAR "urn:schemas:calendar:"
-#define E2K_PR_CALENDAR_BUSY_STATUS E2K_NS_CALENDAR "busystatus"
-#define E2K_PR_CALENDAR_DTEND E2K_NS_CALENDAR "dtend"
-#define E2K_PR_CALENDAR_DTSTART E2K_NS_CALENDAR "dtstart"
-#define E2K_PR_CALENDAR_INSTANCE_TYPE E2K_NS_CALENDAR "instancetype"
-#define E2K_PR_CALENDAR_LAST_MODIFIED E2K_NS_CALENDAR "lastmodifiedtime"
-#define E2K_PR_CALENDAR_UID E2K_NS_CALENDAR "uid"
-#define E2K_PR_CALENDAR_URL E2K_NS_CALENDAR "locationurl"
-#define E2K_PR_CALENDAR_FREEBUSY_URL E2K_NS_CALENDAR "fburl"
-#define E2K_PR_CALENDAR_REMINDER_NEXT_TIME E2K_NS_CALENDAR "remindernexttime"
-
-#define E2K_NS_CONTACTS "urn:schemas:contacts:"
-#define E2K_PR_CONTACTS_FULL_NAME E2K_NS_CONTACTS "cn"
-#define E2K_PR_CONTACTS_FAMILY_NAME E2K_NS_CONTACTS "sn"
-#define E2K_PR_CONTACTS_GIVEN_NAME E2K_NS_CONTACTS "givenName"
-#define E2K_PR_CONTACTS_ADDITIONAL_NAME E2K_NS_CONTACTS "middlename"
-#define E2K_PR_CONTACTS_NAME_SUFFIX E2K_NS_CONTACTS "namesuffix"
-#define E2K_PR_CONTACTS_TITLE E2K_NS_CONTACTS "title"
-#define E2K_PR_CONTACTS_ORG E2K_NS_CONTACTS "o"
-#define E2K_PR_CONTACTS_FILE_AS E2K_NS_CONTACTS "fileas"
-
-#define E2K_PR_CONTACTS_PHONE_CALLBACK E2K_NS_CONTACTS "callbackphone"
-#define E2K_PR_CONTACTS_PHONE_BUSINESS_FAX E2K_NS_CONTACTS "facsimiletelephonenumber"
-#define E2K_PR_CONTACTS_PHONE_HOME_FAX E2K_NS_CONTACTS "homefax"
-#define E2K_PR_CONTACTS_PHONE_HOME E2K_NS_CONTACTS "homePhone"
-#define E2K_PR_CONTACTS_PHONE_HOME_2 E2K_NS_CONTACTS "homephone2"
-#define E2K_PR_CONTACTS_PHONE_ISDN E2K_NS_CONTACTS "internationalisdnnumber"
-#define E2K_PR_CONTACTS_PHONE_MOBILE E2K_NS_CONTACTS "mobile"
-#define E2K_PR_CONTACTS_PHONE_COMPANY E2K_NS_CONTACTS "organizationmainphone"
-#define E2K_PR_CONTACTS_PHONE_OTHER_FAX E2K_NS_CONTACTS "otherfax"
-#define E2K_PR_CONTACTS_PHONE_PAGER E2K_NS_CONTACTS "pager"
-#define E2K_PR_CONTACTS_PHONE_BUSINESS E2K_NS_CONTACTS "telephoneNumber"
-#define E2K_PR_CONTACTS_PHONE_BUSINESS_2 E2K_NS_CONTACTS "telephonenumber2"
-#define E2K_PR_CONTACTS_PHONE_TELEX E2K_NS_CONTACTS "telexnumber"
-#define E2K_PR_CONTACTS_PHONE_TTYTDD E2K_NS_CONTACTS "ttytddphone"
-#define E2K_PR_CONTACTS_PHONE_ASSISTANT E2K_NS_CONTACTS "secretaryphone"
-#define E2K_PR_CONTACTS_PHONE_CAR E2K_NS_CONTACTS "othermobile"
-#define E2K_PR_CONTACTS_PHONE_OTHER E2K_NS_CONTACTS "otherTelephone"
-
-#define E2K_PR_CONTACTS_EMAIL1 E2K_NS_CONTACTS "email1"
-#define E2K_PR_CONTACTS_EMAIL2 E2K_NS_CONTACTS "email2"
-#define E2K_PR_CONTACTS_EMAIL3 E2K_NS_CONTACTS "email3"
-
-#define E2K_PR_CONTACTS_ADDRESS_WORK E2K_NS_CONTACTS "workaddress"
-#define E2K_PR_CONTACTS_WORK_STREET E2K_NS_CONTACTS "street"
-#define E2K_PR_CONTACTS_WORK_PO_BOX E2K_NS_CONTACTS "postofficebox"
-#define E2K_PR_CONTACTS_WORK_CITY E2K_NS_CONTACTS "l"
-#define E2K_PR_CONTACTS_WORK_STATE E2K_NS_CONTACTS "st"
-#define E2K_PR_CONTACTS_WORK_ZIP E2K_NS_CONTACTS "postalcode"
-#define E2K_PR_CONTACTS_WORK_COUNTRY E2K_NS_CONTACTS "co"
-#define E2K_PR_CONTACTS_ADDRESS_HOME E2K_NS_CONTACTS "homepostaladdress"
-#define E2K_PR_CONTACTS_HOME_STREET E2K_NS_CONTACTS "homeStreet"
-#define E2K_PR_CONTACTS_HOME_PO_BOX E2K_NS_CONTACTS "homePostOfficeBox"
-#define E2K_PR_CONTACTS_HOME_CITY E2K_NS_CONTACTS "homeCity"
-#define E2K_PR_CONTACTS_HOME_STATE E2K_NS_CONTACTS "homeState"
-#define E2K_PR_CONTACTS_HOME_ZIP E2K_NS_CONTACTS "homePostalCode"
-#define E2K_PR_CONTACTS_HOME_COUNTRY E2K_NS_CONTACTS "homeCountry"
-#define E2K_PR_CONTACTS_ADDRESS_OTHER E2K_NS_CONTACTS "otherpostaladdress"
-#define E2K_PR_CONTACTS_OTHER_STREET E2K_NS_CONTACTS "otherstreet"
-#define E2K_PR_CONTACTS_OTHER_PO_BOX E2K_NS_CONTACTS "otherpostofficebox"
-#define E2K_PR_CONTACTS_OTHER_CITY E2K_NS_CONTACTS "othercity"
-#define E2K_PR_CONTACTS_OTHER_STATE E2K_NS_CONTACTS "otherstate"
-#define E2K_PR_CONTACTS_OTHER_ZIP E2K_NS_CONTACTS "otherpostalcode"
-#define E2K_PR_CONTACTS_OTHER_COUNTRY E2K_NS_CONTACTS "othercountry"
-
-#define E2K_PR_CONTACTS_HOMEPAGE_URL E2K_NS_CONTACTS "businesshomepage"
-#define E2K_PR_CONTACTS_ORG_UNIT E2K_NS_CONTACTS "department"
-#define E2K_PR_CONTACTS_OFFICE E2K_NS_CONTACTS "roomnumber"
-#define E2K_PR_CONTACTS_ROLE E2K_NS_CONTACTS "profession"
-#define E2K_PR_CONTACTS_MANAGER E2K_NS_CONTACTS "manager"
-#define E2K_PR_CONTACTS_ASSISTANT E2K_NS_CONTACTS "secretarycn"
-#define E2K_PR_CONTACTS_NICKNAME E2K_NS_CONTACTS "nickname"
-#define E2K_PR_CONTACTS_SPOUSE E2K_NS_CONTACTS "spousecn"
-#define E2K_PR_CONTACTS_BIRTH_DATE E2K_NS_CONTACTS "bday"
-#define E2K_PR_CONTACTS_ANNIVERSARY E2K_NS_CONTACTS "weddinganniversary"
-
-#define E2K_NS_HTTPMAIL "urn:schemas:httpmail:"
-#define E2K_PR_HTTPMAIL_DATE E2K_NS_HTTPMAIL "date"
-#define E2K_PR_HTTPMAIL_FROM_EMAIL E2K_NS_HTTPMAIL "fromemail"
-#define E2K_PR_HTTPMAIL_FROM_NAME E2K_NS_HTTPMAIL "fromname"
-#define E2K_PR_HTTPMAIL_HAS_ATTACHMENT E2K_NS_HTTPMAIL "hasattachment"
-#define E2K_PR_HTTPMAIL_MESSAGE_FLAG E2K_NS_HTTPMAIL "messageflag"
-#define E2K_PR_HTTPMAIL_READ E2K_NS_HTTPMAIL "read"
-#define E2K_PR_HTTPMAIL_SUBJECT E2K_NS_HTTPMAIL "subject"
-#define E2K_PR_HTTPMAIL_TEXT_DESCRIPTION E2K_NS_HTTPMAIL "textdescription"
-#define E2K_PR_HTTPMAIL_THREAD_TOPIC E2K_NS_HTTPMAIL "thread-topic"
-#define E2K_PR_HTTPMAIL_UNREAD_COUNT E2K_NS_HTTPMAIL "unreadcount"
-
-#define E2K_NS_STD_FOLDER "urn:schemas:httpmail:"
-#define E2K_PR_STD_FOLDER_CALENDAR E2K_NS_HTTPMAIL "calendar"
-#define E2K_PR_STD_FOLDER_CONTACTS E2K_NS_HTTPMAIL "contacts"
-#define E2K_PR_STD_FOLDER_DELETED_ITEMS E2K_NS_HTTPMAIL "deleteditems"
-#define E2K_PR_STD_FOLDER_DRAFTS E2K_NS_HTTPMAIL "drafts"
-#define E2K_PR_STD_FOLDER_INBOX E2K_NS_HTTPMAIL "inbox"
-#define E2K_PR_STD_FOLDER_JOURNAL E2K_NS_HTTPMAIL "journal"
-#define E2K_PR_STD_FOLDER_ROOT E2K_NS_HTTPMAIL "msgfolderroot"
-#define E2K_PR_STD_FOLDER_NOTES E2K_NS_HTTPMAIL "notes"
-#define E2K_PR_STD_FOLDER_OUTBOX E2K_NS_HTTPMAIL "outbox"
-#define E2K_PR_STD_FOLDER_SENDMSG E2K_NS_HTTPMAIL "sendmsg"
-#define E2K_PR_STD_FOLDER_SENT_ITEMS E2K_NS_HTTPMAIL "sentitems"
-#define E2K_PR_STD_FOLDER_TASKS E2K_NS_HTTPMAIL "tasks"
-
-#define E2K_NS_MAILHEADER "urn:schemas:mailheader:"
-#define E2K_PR_MAILHEADER_CC E2K_NS_MAILHEADER "cc"
-#define E2K_PR_MAILHEADER_DATE E2K_NS_MAILHEADER "date"
-#define E2K_PR_MAILHEADER_FROM E2K_NS_MAILHEADER "from"
-#define E2K_PR_MAILHEADER_IMPORTANCE E2K_NS_MAILHEADER "importance"
-#define E2K_PR_MAILHEADER_IN_REPLY_TO E2K_NS_MAILHEADER "in-reply-to"
-#define E2K_PR_MAILHEADER_MESSAGE_ID E2K_NS_MAILHEADER "message-id"
-#define E2K_PR_MAILHEADER_RECEIVED E2K_NS_MAILHEADER "received"
-#define E2K_PR_MAILHEADER_REFERENCES E2K_NS_MAILHEADER "references"
-#define E2K_PR_MAILHEADER_REPLY_BY E2K_NS_MAILHEADER "reply-by"
-#define E2K_PR_MAILHEADER_SUBJECT E2K_NS_MAILHEADER "subject"
-#define E2K_PR_MAILHEADER_THREAD_INDEX E2K_NS_MAILHEADER "thread-index"
-#define E2K_PR_MAILHEADER_TO E2K_NS_MAILHEADER "to"
-#define E2K_PR_MAILHEADER_COMPLETED E2K_NS_MAILHEADER "x-message-completed"
-
-
-#define E2K_NS_SUBSCRIPTION "http://schemas.microsoft.com/Exchange/"
-#define E2K_PR_SUBSCRIPTION_ID E2K_NS_SUBSCRIPTION "subscriptionID"
-
-#define E2K_NS_EXCHANGE "http://schemas.microsoft.com/exchange/"
-#define E2K_PR_EXCHANGE_MESSAGE_CLASS E2K_NS_EXCHANGE "outlookmessageclass"
-#define E2K_PR_EXCHANGE_FOLDER_CLASS E2K_NS_EXCHANGE "outlookfolderclass"
-#define E2K_PR_EXCHANGE_KEYWORDS E2K_NS_EXCHANGE "keywords-utf8"
-#define E2K_PR_EXCHANGE_SD_BINARY E2K_NS_EXCHANGE "ntsecuritydescriptor"
-#define E2K_PR_EXCHANGE_SD_XML E2K_NS_EXCHANGE "security/descriptor"
-#define E2K_PR_EXCHANGE_TIMEZONE E2K_NS_EXCHANGE "timezone"
-#define E2K_PR_EXCHANGE_PERMANENTURL E2K_NS_EXCHANGE "permanenturl"
-#define E2K_PR_EXCHANGE_FOLDER_SIZE E2K_NS_EXCHANGE "foldersize"
-#define E2K_PR_EXCHANGE_OOF_STATE E2K_NS_EXCHANGE "oof-state"
-
-#define E2K_NS_REPL "http://schemas.microsoft.com/repl/"
-#define E2K_PR_REPL_UID E2K_NS_REPL "repl-uid"
-
-#define E2K_NS_SECURITY "http://schemas.microsoft.com/security/"
-#define E2K_NS_TYPE "urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/"
-
-#define E2K_NS_MAPI "http://schemas.microsoft.com/mapi/"
-#define E2K_PR_MAPI_COMMON_START E2K_NS_MAPI "commonstart"
-#define E2K_PR_MAPI_COMMON_END E2K_NS_MAPI "commonend"
-#define E2K_PR_MAPI_NO_AUTOARCHIVE E2K_NS_MAPI "agingdontageme"
-#define E2K_PR_MAPI_PRIORITY E2K_NS_MAPI "priority"
-#define E2K_PR_MAPI_REMINDER_SET E2K_NS_MAPI "reminderset"
-#define E2K_PR_MAPI_SENSITIVITY E2K_NS_MAPI "sensitivity"
-#define E2K_PR_MAPI_SIDE_EFFECTS E2K_NS_MAPI "sideeffects"
-#define E2K_PR_MAPI_EMAIL_1_ENTRYID E2K_NS_MAPI "email1originalentryid"
-#define E2K_PR_MAPI_EMAIL_1_ADDRTYPE E2K_NS_MAPI "email1addrtype"
-#define E2K_PR_MAPI_EMAIL_1_ADDRESS E2K_NS_MAPI "email1emailaddress"
-#define E2K_PR_MAPI_EMAIL_1_DISPLAY_NAME E2K_NS_MAPI "email1originaldisplayname"
-#define E2K_PR_MAPI_EMAIL_2_ENTRYID E2K_NS_MAPI "email2originalentryid"
-#define E2K_PR_MAPI_EMAIL_2_ADDRTYPE E2K_NS_MAPI "email2addrtype"
-#define E2K_PR_MAPI_EMAIL_2_ADDRESS E2K_NS_MAPI "email2emailaddress"
-#define E2K_PR_MAPI_EMAIL_2_DISPLAY_NAME E2K_NS_MAPI "email2originaldisplayname"
-#define E2K_PR_MAPI_EMAIL_3_ENTRYID E2K_NS_MAPI "email3originalentryid"
-#define E2K_PR_MAPI_EMAIL_3_ADDRTYPE E2K_NS_MAPI "email3addrtype"
-#define E2K_PR_MAPI_EMAIL_3_ADDRESS E2K_NS_MAPI "email3emailaddress"
-#define E2K_PR_MAPI_EMAIL_3_DISPLAY_NAME E2K_NS_MAPI "email3originaldisplayname"
-#define E2K_PR_MAPI_EMAIL_LIST_TYPE E2K_NS_MAPI "emaillisttype"
-#define E2K_PR_MAPI_EMAIL_ADDRESS_LIST E2K_NS_MAPI "emailaddresslist"
-
-
-#define E2K_NS_MAPI_ID "http://schemas.microsoft.com/mapi/id/"
-#define E2K_NS_MAPI_ID_LEN (sizeof (E2K_NS_MAPI_ID) - 1)
-
-#define E2K_NS_OUTLOOK_APPOINTMENT E2K_NS_MAPI_ID "{00062002-0000-0000-C000-000000000046}/"
-
-#define E2K_NS_OUTLOOK_TASK E2K_NS_MAPI_ID "{00062003-0000-0000-C000-000000000046}/"
-#define E2K_PR_OUTLOOK_TASK_STATUS E2K_NS_OUTLOOK_TASK "0x00008101"
-#define E2K_PR_OUTLOOK_TASK_PERCENT E2K_NS_OUTLOOK_TASK "0x00008102"
-#define E2K_PR_OUTLOOK_TASK_TEAM_TASK E2K_NS_OUTLOOK_TASK "0x00008103"
-#define E2K_PR_OUTLOOK_TASK_START_DT E2K_NS_OUTLOOK_TASK "0x00008104"
-#define E2K_PR_OUTLOOK_TASK_DUE_DT E2K_NS_OUTLOOK_TASK "0x00008105"
-#define E2K_PR_OUTLOOK_TASK_DONE_DT E2K_NS_OUTLOOK_TASK "0x0000810f"
-#define E2K_PR_OUTLOOK_TASK_ACTUAL_WORK E2K_NS_OUTLOOK_TASK "0x00008110"
-#define E2K_PR_OUTLOOK_TASK_TOTAL_WORK E2K_NS_OUTLOOK_TASK "0x00008111"
-#define E2K_PR_OUTLOOK_TASK_IS_DONE E2K_NS_OUTLOOK_TASK "0x0000811c"
-#define E2K_PR_OUTLOOK_TASK_OWNER E2K_NS_OUTLOOK_TASK "0x0000811f"
-#define E2K_PR_OUTLOOK_TASK_RECURRING E2K_NS_OUTLOOK_TASK "0x00008126"
-#define E2K_PR_OUTLOOK_TASK_ASSIGNMENT E2K_NS_OUTLOOK_TASK "0x00008129"
-
-#define E2K_NS_OUTLOOK_CONTACT E2K_NS_MAPI_ID "{00062004-0000-0000-C000-000000000046}/"
-#define E2K_PR_OUTLOOK_CONTACT_JOURNAL E2K_NS_OUTLOOK_CONTACT "0x00008025"
-#define E2K_PR_OUTLOOK_CONTACT_NETMEETING_URL E2K_NS_OUTLOOK_CONTACT "0x00008056"
-#define E2K_PR_OUTLOOK_CONTACT_IM_ADDR E2K_NS_OUTLOOK_CONTACT "0x00008062"
-
-#define E2K_NS_OUTLOOK_COMMON E2K_NS_MAPI_ID "{00062008-0000-0000-C000-000000000046}/"
-#define E2K_PR_OUTLOOK_COMMON_CONTACTS E2K_NS_OUTLOOK_COMMON "0x00008586"
-
-
-#define E2K_NS_OUTLOOK_JOURNAL E2K_NS_MAPI_ID "{0006200A-0000-0000-C000-000000000046}/"
-
-#define E2K_NS_OUTLOOK_STICKYNOTE E2K_NS_MAPI_ID "{0006200E-0000-0000-C000-000000000046}/"
-#define E2K_PR_OUTLOOK_STICKYNOTE_COLOR E2K_NS_OUTLOOK_STICKYNOTE "0x00008b00"
-#define E2K_PR_OUTLOOK_STICKYNOTE_WIDTH E2K_NS_OUTLOOK_STICKYNOTE "0x00008b02"
-#define E2K_PR_OUTLOOK_STICKYNOTE_HEIGHT E2K_NS_OUTLOOK_STICKYNOTE "0x00008b03"
-
-
-#define E2K_NS_MAPI_PROPTAG "http://schemas.microsoft.com/mapi/proptag/"
-
-@AUTOGENERATE@
-
-#endif /* __E2K_PROPNAMES_H__ */
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2003-2004 Novell, Inc. */
-
-#ifndef __E2K_PROPTAGS_H__
-#define __E2K_PROPTAGS_H__
-
-@AUTOGENERATE@
-
-#endif /* __E2K_PROPTAGS_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2001-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* e2k-restriction.c: message restrictions (WHERE clauses / Rule conditions) */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e2k-restriction.h"
-#include "e2k-properties.h"
-#include "e2k-rule.h"
-
-#include <stdarg.h>
-#include <string.h>
-
-static E2kRestriction *
-conjoin (E2kRestrictionType type, gint nrns, E2kRestriction **rns, gboolean unref)
-{
- E2kRestriction *ret = g_new0 (E2kRestriction, 1);
- gint i;
-
- ret->type = type;
- ret->res.and.nrns = nrns;
- ret->res.and.rns = g_new (E2kRestriction *, nrns);
- for (i = 0; i < nrns; i++) {
- ret->res.and.rns[i] = rns[i];
- if (!unref)
- e2k_restriction_ref (rns[i]);
- }
-
- return ret;
-}
-
-/**
- * e2k_restriction_and:
- * @nrns: length of @rns
- * @rns: an array of #E2kRestriction
- * @unref: whether or not to unref the restrictions when it is done
- *
- * Creates a new restriction which is true if all of the restrictions
- * in @rns are true.
- *
- * If @unref is %TRUE, then e2k_restriction_and() is essentially
- * stealing the caller's references on the restrictions. If it is
- * %FALSE, then e2k_restriction_and() will acquire its own references
- * to each of the restrictions.
- *
- * Return value: the new restriction
- **/
-E2kRestriction *
-e2k_restriction_and (gint nrns, E2kRestriction **rns, gboolean unref)
-{
- return conjoin (E2K_RESTRICTION_AND, nrns, rns, unref);
-}
-
-/**
- * e2k_restriction_or:
- * @nrns: length of @rns
- * @rns: an array of #E2kRestriction
- * @unref: see e2k_restriction_and()
- *
- * Creates a new restriction which is true if any of the restrictions
- * in @rns are true.
- *
- * Return value: the new restriction
- **/
-E2kRestriction *
-e2k_restriction_or (gint nrns, E2kRestriction **rns, gboolean unref)
-{
- return conjoin (E2K_RESTRICTION_OR, nrns, rns, unref);
-}
-
-static E2kRestriction *
-conjoinv (E2kRestrictionType type, E2kRestriction *rn, va_list ap)
-{
- E2kRestriction *ret = g_new0 (E2kRestriction, 1);
- GPtrArray *rns;
-
- rns = g_ptr_array_new ();
- while (rn) {
- g_ptr_array_add (rns, rn);
- rn = va_arg (ap, E2kRestriction *);
- }
- va_end (ap);
-
- ret->type = type;
- ret->res.and.nrns = rns->len;
- ret->res.and.rns = (E2kRestriction **)rns->pdata;
- g_ptr_array_free (rns, FALSE);
-
- return ret;
-}
-
-/**
- * e2k_restriction_andv:
- * @rn: an #E2kRestriction
- * @...: a %NULL-terminated list of additional #E2kRestrictions
- *
- * Creates a new restriction which is true if all of the passed-in
- * restrictions are true. e2k_restriction_andv() steals the caller's
- * reference on each of the passed-in restrictions.
- *
- * Return value: the new restriction
- **/
-E2kRestriction *
-e2k_restriction_andv (E2kRestriction *rn, ...)
-{
- va_list ap;
-
- va_start (ap, rn);
- return conjoinv (E2K_RESTRICTION_AND, rn, ap);
-}
-
-/**
- * e2k_restriction_orv:
- * @rn: an #E2kRestriction
- * @...: a %NULL-terminated list of additional #E2kRestrictions
- *
- * Creates a new restriction which is true if any of the passed-in
- * restrictions are true. e2k_restriction_orv() steals the caller's
- * reference on each of the passed-in restrictions.
- *
- * Return value: the new restriction
- **/
-E2kRestriction *
-e2k_restriction_orv (E2kRestriction *rn, ...)
-{
- va_list ap;
-
- va_start (ap, rn);
- return conjoinv (E2K_RESTRICTION_OR, rn, ap);
-}
-
-/**
- * e2k_restriction_not:
- * @rn: an #E2kRestriction
- * @unref: see e2k_restriction_and()
- *
- * Creates a new restriction which is true if @rn is false.
- *
- * Return value: the new restriction
- **/
-E2kRestriction *
-e2k_restriction_not (E2kRestriction *rn, gboolean unref)
-{
- E2kRestriction *ret = g_new0 (E2kRestriction, 1);
-
- ret->type = E2K_RESTRICTION_NOT;
- ret->res.not.rn = rn;
- if (!unref)
- e2k_restriction_ref (rn);
-
- return ret;
-}
-
-/**
- * e2k_restriction_content:
- * @propname: text property to compare against
- * @fuzzy_level: how to compare
- * @value: value to compare against
- *
- * Creates a new restriction that is true for objects where the
- * indicated property's value matches @value according to @fuzzy_level.
- *
- * For a WebDAV SEARCH, @fuzzy_level should be %E2K_FL_FULLSTRING,
- * %E2K_FL_SUBSTRING, %E2K_FL_PREFIX, or %E2K_FL_SUFFIX.
- *
- * For a MAPI restriction, @fuzzy_level may not be %E2K_FL_SUFFIX, but
- * may be ORed with any of the additional values %E2K_FL_IGNORECASE,
- * %E2K_FL_IGNORENONSPACE, or %E2K_FL_LOOSE.
- *
- * To compare a property's sort order to another string, use
- * e2k_restriction_prop_string().
- *
- * Return value: the new restriction
- **/
-E2kRestriction *
-e2k_restriction_content (const gchar *propname,
- E2kRestrictionFuzzyLevel fuzzy_level,
- const gchar *value)
-{
- E2kRestriction *ret = g_new0 (E2kRestriction, 1);
-
- ret->type = E2K_RESTRICTION_CONTENT;
- ret->res.content.fuzzy_level = fuzzy_level;
- e2k_rule_prop_set (&ret->res.content.pv.prop, propname);
- ret->res.content.pv.type = E2K_PROP_TYPE_STRING;
- ret->res.content.pv.value = g_strdup (value);
-
- return ret;
-}
-
-/**
- * e2k_restriction_prop_bool:
- * @propname: boolean property to compare against
- * @relop: %E2K_RELOP_EQ or %E2K_RELOP_NE
- * @value: %TRUE or %FALSE
- *
- * Creates a new restriction that is true for objects where the
- * indicated property matches @relop and @value.
- *
- * Return value: the new restriction
- **/
-E2kRestriction *
-e2k_restriction_prop_bool (const gchar *propname, E2kRestrictionRelop relop,
- gboolean value)
-{
- E2kRestriction *ret = g_new0 (E2kRestriction, 1);
-
- ret->type = E2K_RESTRICTION_PROPERTY;
- ret->res.property.relop = relop;
- e2k_rule_prop_set (&ret->res.property.pv.prop, propname);
- ret->res.property.pv.type = E2K_PROP_TYPE_BOOL;
- ret->res.property.pv.value = GUINT_TO_POINTER (value);
-
- return ret;
-}
-
-/**
- * e2k_restriction_prop_int:
- * @propname: integer property to compare against
- * @relop: an #E2kRestrictionRelop
- * @value: number to compare against
- *
- * Creates a new restriction that is true for objects where the
- * indicated property matches @value according to @relop.
- *
- * Return value: the new restriction
- **/
-E2kRestriction *
-e2k_restriction_prop_int (const gchar *propname, E2kRestrictionRelop relop,
- gint value)
-{
- E2kRestriction *ret = g_new0 (E2kRestriction, 1);
-
- ret->type = E2K_RESTRICTION_PROPERTY;
- ret->res.property.relop = relop;
- e2k_rule_prop_set (&ret->res.property.pv.prop, propname);
- ret->res.property.pv.type = E2K_PROP_TYPE_INT;
- ret->res.property.pv.value = GINT_TO_POINTER (value);
-
- return ret;
-}
-
-/**
- * e2k_restriction_prop_date:
- * @propname: date/time property to compare against
- * @relop: an #E2kRestrictionRelop
- * @value: date/time to compare against (as returned by e2k_make_timestamp())
- *
- * Creates a new restriction that is true for objects where the
- * indicated property matches @value according to @relop.
- *
- * Return value: the new restriction
- **/
-E2kRestriction *
-e2k_restriction_prop_date (const gchar *propname, E2kRestrictionRelop relop,
- const gchar *value)
-{
- E2kRestriction *ret = g_new0 (E2kRestriction, 1);
-
- ret->type = E2K_RESTRICTION_PROPERTY;
- ret->res.property.relop = relop;
- e2k_rule_prop_set (&ret->res.property.pv.prop, propname);
- ret->res.property.pv.type = E2K_PROP_TYPE_DATE;
- ret->res.property.pv.value = g_strdup (value);
-
- return ret;
-}
-
-/**
- * e2k_restriction_prop_string:
- * @propname: text property to compare against
- * @relop: an #E2kRestrictionRelop
- * @value: text to compare against
- *
- * Creates a new restriction that is true for objects where the
- * indicated property matches @value according to @relop.
- *
- * To do a substring match, use e2k_restriction_content().
- *
- * Return value: the new restriction
- **/
-E2kRestriction *
-e2k_restriction_prop_string (const gchar *propname, E2kRestrictionRelop relop,
- const gchar *value)
-{
- E2kRestriction *ret = g_new0 (E2kRestriction, 1);
-
- ret->type = E2K_RESTRICTION_PROPERTY;
- ret->res.property.relop = relop;
- e2k_rule_prop_set (&ret->res.property.pv.prop, propname);
- ret->res.property.pv.type = E2K_PROP_TYPE_STRING;
- ret->res.property.pv.value = g_strdup (value);
-
- return ret;
-}
-
-/**
- * e2k_restriction_prop_binary:
- * @propname: binary property to compare against
- * @relop: %E2K_RELOP_EQ or %E2K_RELOP_NE
- * @data: data to compare against
- * @len: length of @data
- *
- * Creates a new restriction that is true for objects where the
- * indicated property matches @value according to @relop.
- *
- * Return value: the new restriction
- **/
-E2kRestriction *
-e2k_restriction_prop_binary (const gchar *propname, E2kRestrictionRelop relop,
- gconstpointer data, gint len)
-{
- E2kRestriction *ret = g_new0 (E2kRestriction, 1);
-
- ret->type = E2K_RESTRICTION_PROPERTY;
- ret->res.property.relop = relop;
- e2k_rule_prop_set (&ret->res.property.pv.prop, propname);
- ret->res.property.pv.type = E2K_PROP_TYPE_BINARY;
- ret->res.property.pv.value = g_byte_array_new ();
- g_byte_array_append (ret->res.property.pv.value, data, len);
-
- return ret;
-}
-
-/**
- * e2k_restriction_compare:
- * @propname1: first property
- * @relop: an #E2kRestrictionRelop
- * @propname2: second property
- *
- * Creates a new restriction which is true for objects where
- * @propname1 and @propname2 have the relationship described by
- * @relop.
- *
- * Return value: the new restriction
- **/
-E2kRestriction *
-e2k_restriction_compare (const gchar *propname1, E2kRestrictionRelop relop,
- const gchar *propname2)
-{
- E2kRestriction *ret = g_new0 (E2kRestriction, 1);
-
- ret->type = E2K_RESTRICTION_COMPAREPROPS;
- ret->res.compare.relop = relop;
- e2k_rule_prop_set (&ret->res.compare.prop1, propname1);
- e2k_rule_prop_set (&ret->res.compare.prop2, propname2);
-
- return ret;
-}
-
-/**
- * e2k_restriction_bitmask:
- * @propname: integer property to compare
- * @bitop: an #E2kRestrictionBitop
- * @mask: mask of bits to compare against
- *
- * Creates a new restriction that is true for objects where the
- * indicated bits of the value of @propname either are or aren't zero,
- * as indicated by @bitop.
- *
- * This cannot be used for WebDAV SEARCH restrictions.
- *
- * Return value: the new restriction
- **/
-E2kRestriction *
-e2k_restriction_bitmask (const gchar *propname, E2kRestrictionBitop bitop,
- guint32 mask)
-{
- E2kRestriction *ret = g_new0 (E2kRestriction, 1);
-
- ret->type = E2K_RESTRICTION_BITMASK;
- ret->res.bitmask.bitop = bitop;
- e2k_rule_prop_set (&ret->res.bitmask.prop, propname);
- ret->res.bitmask.mask = mask;
-
- return ret;
-}
-
-/**
- * e2k_restriction_size:
- * @propname: property to compare
- * @relop: an #E2kRestrictionRelop
- * @size: the size to compare @propname to
- *
- * Creates a new restriction which is true for objects where the size
- * of the value of @propname matches @size according to @relop.
- *
- * This cannot be used for WebDAV SEARCH restrictions.
- *
- * You probably do not want to use this. The standard idiom for
- * checking the size of a message is to use e2k_restriction_prop_int()
- * on its %PR_MESSAGE_SIZE property, not to use e2k_restriction_size()
- * on its %PR_BODY.
- *
- * Return value: the new restriction
- **/
-E2kRestriction *
-e2k_restriction_size (const gchar *propname, E2kRestrictionRelop relop,
- guint32 size)
-{
- E2kRestriction *ret = g_new0 (E2kRestriction, 1);
-
- ret->type = E2K_RESTRICTION_SIZE;
- ret->res.size.relop = relop;
- e2k_rule_prop_set (&ret->res.size.prop, propname);
- ret->res.size.size = size;
-
- return ret;
-}
-
-/**
- * e2k_restriction_exist:
- * @propname: property to check
- *
- * Creates a new restriction which is true for objects that have
- * a @propname property.
- *
- * This cannot be used for WebDAV SEARCH restrictions.
- *
- * Return value: the new restriction
- **/
-E2kRestriction *
-e2k_restriction_exist (const gchar *propname)
-{
- E2kRestriction *ret = g_new0 (E2kRestriction, 1);
-
- ret->type = E2K_RESTRICTION_EXIST;
- e2k_rule_prop_set (&ret->res.exist.prop, propname);
-
- return ret;
-}
-
-/**
- * e2k_restriction_sub:
- * @subtable: the WebDAV name of a MAPI property of type PT_OBJECT
- * @rn: the restriction to apply against the values of @subtable
- * @unref: see e2k_restriction_and()
- *
- * Creates a new restriction that is true for objects where @rn is
- * true when applied to the value of @subtable on that object.
- *
- * @subtable is generally %PR_MESSAGE_RECIPIENTS (for finding messages
- * whose recipients match a given restriction) or
- * %PR_MESSAGE_ATTACHMENTS (for finding messages whose attachments
- * match a given restriction).
- *
- * This cannot be used for WebDAV SEARCH restrictions.
- *
- * Return value: the new restriction
- **/
-E2kRestriction *
-e2k_restriction_sub (const gchar *subtable, E2kRestriction *rn, gboolean unref)
-{
- E2kRestriction *ret = g_new0 (E2kRestriction, 1);
-
- ret->type = E2K_RESTRICTION_SUBRESTRICTION;
- e2k_rule_prop_set (&ret->res.sub.subtable, subtable);
- ret->res.sub.rn = rn;
- if (!unref)
- e2k_restriction_ref (rn);
-
- return ret;
-}
-
-/**
- * e2k_restriction_unref:
- * @rn: a restriction
- *
- * Unrefs @rn. If there are no more references to @rn, it is freed.
- **/
-void
-e2k_restriction_unref (E2kRestriction *rn)
-{
- gint i;
-
- if (rn->ref_count--)
- return;
-
- switch (rn->type) {
- case E2K_RESTRICTION_AND:
- case E2K_RESTRICTION_OR:
- for (i = 0; i < rn->res.and.nrns; i++)
- e2k_restriction_unref (rn->res.and.rns[i]);
- g_free (rn->res.and.rns);
- break;
-
- case E2K_RESTRICTION_NOT:
- e2k_restriction_unref (rn->res.not.rn);
- break;
-
- case E2K_RESTRICTION_CONTENT:
- e2k_rule_free_propvalue (&rn->res.content.pv);
- break;
-
- case E2K_RESTRICTION_PROPERTY:
- e2k_rule_free_propvalue (&rn->res.property.pv);
- break;
-
- default:
- break;
- }
-
- g_free (rn);
-}
-
-/**
- * e2k_restriction_ref:
- * @rn: a restriction
- *
- * Refs @rn.
- **/
-void
-e2k_restriction_ref (E2kRestriction *rn)
-{
- rn->ref_count++;
-}
-
-/* SQL export */
-
-static gboolean rn_to_sql (E2kRestriction *rn, GString *sql, E2kRestrictionType inside);
-
-static const gchar *sql_relops[] = { "<", "<=", ">", ">=", "=", "!=" };
-static const gint n_sql_relops = G_N_ELEMENTS (sql_relops);
-
-static gboolean
-rns_to_sql (E2kRestrictionType type, E2kRestriction **rns, gint nrns, GString *sql)
-{
- gint i;
- gboolean need_op = FALSE;
- gboolean rv = FALSE;
-
- for (i = 0; i < nrns; i++) {
- if (need_op) {
- g_string_append (sql, type == E2K_RESTRICTION_AND ?
- " AND " : " OR ");
- need_op = FALSE;
- }
- if (rn_to_sql (rns[i], sql, type)) {
- need_op = TRUE;
- rv = TRUE;
- }
- }
- return rv;
-}
-
-static void
-append_sql_quoted (GString *sql, const gchar *string)
-{
- while (*string) {
- if (*string == '\'')
- g_string_append (sql, "''");
- else
- g_string_append_c (sql, *string);
- string++;
- }
-}
-
-static gboolean
-rn_to_sql (E2kRestriction *rn, GString *sql, E2kRestrictionType inside)
-{
- E2kPropValue *pv;
-
- switch (rn->type) {
- case E2K_RESTRICTION_AND:
- case E2K_RESTRICTION_OR: {
- GString *subsql = g_string_new ("");
- gboolean rv;
- if ((rv = rns_to_sql (rn->type, rn->res.and.rns, rn->res.and.nrns, subsql))) {
- if (rn->type != inside)
- g_string_append (sql, "(");
- g_string_append (sql, subsql->str);
- if (rn->type != inside)
- g_string_append (sql, ")");
- }
- g_string_free (subsql, TRUE);
-
- return rv;
- }
-
- case E2K_RESTRICTION_NOT: {
- GString *subsql = g_string_new ("");
- gboolean rv;
- if ((rv = rn_to_sql (rn->res.not.rn, subsql, rn->type))) {
- g_string_append (sql, "NOT (");
- g_string_append (sql, subsql->str);
- g_string_append (sql, ")");
- }
- g_string_free (subsql, TRUE);
-
- return rv;
- }
-
- case E2K_RESTRICTION_CONTENT:
- pv = &rn->res.content.pv;
- g_string_append_printf (sql, "\"%s\" ", pv->prop.name);
-
- switch (E2K_FL_MATCH_TYPE (rn->res.content.fuzzy_level)) {
- case E2K_FL_SUBSTRING:
- g_string_append (sql, "LIKE '%");
- append_sql_quoted (sql, pv->value);
- g_string_append (sql, "%'");
- break;
-
- case E2K_FL_PREFIX:
- g_string_append (sql, "LIKE '");
- append_sql_quoted (sql, pv->value);
- g_string_append (sql, "%'");
- break;
-
- case E2K_FL_SUFFIX:
- g_string_append (sql, "LIKE '%");
- append_sql_quoted (sql, pv->value);
- g_string_append_c (sql, '\'');
- break;
-
- case E2K_FL_FULLSTRING:
- default:
- g_string_append (sql, "= '");
- append_sql_quoted (sql, pv->value);
- g_string_append_c (sql, '\'');
- break;
- }
- return TRUE;
-
- case E2K_RESTRICTION_PROPERTY:
- if (rn->res.property.relop >= n_sql_relops)
- return FALSE;
-
- pv = &rn->res.property.pv;
- g_string_append_printf (sql, "\"%s\" %s ", pv->prop.name,
- sql_relops[rn->res.property.relop]);
-
- switch (pv->type) {
- case E2K_PROP_TYPE_INT:
- g_string_append_printf (sql, "%d",
- GPOINTER_TO_UINT (pv->value));
- break;
-
- case E2K_PROP_TYPE_BOOL:
- g_string_append (sql, pv->value ? "True" : "False");
- break;
-
- case E2K_PROP_TYPE_DATE:
- g_string_append_printf (sql,
- "cast (\"%s\" as 'dateTime.tz')",
- (gchar *)pv->value);
- break;
-
- default:
- g_string_append_c (sql, '\'');
- append_sql_quoted (sql, pv->value);
- g_string_append_c (sql, '\'');
- break;
- }
- return TRUE;
-
- case E2K_RESTRICTION_COMPAREPROPS:
- if (rn->res.compare.relop >= n_sql_relops)
- return FALSE;
-
- g_string_append_printf (sql, "\"%s\" %s \"%s\"",
- rn->res.compare.prop1.name,
- sql_relops[rn->res.compare.relop],
- rn->res.compare.prop2.name);
- return TRUE;
-
- case E2K_RESTRICTION_COMMENT:
- return TRUE;
-
- case E2K_RESTRICTION_BITMASK:
- case E2K_RESTRICTION_EXIST:
- case E2K_RESTRICTION_SIZE:
- case E2K_RESTRICTION_SUBRESTRICTION:
- default:
- return FALSE;
-
- }
-}
-
-/**
- * e2k_restriction_to_sql:
- * @rn: a restriction
- *
- * Converts @rn to an SQL WHERE clause to be used with the WebDAV
- * SEARCH method. Note that certain restriction types cannot be used
- * in SQL, as mentioned in their descriptions above.
- *
- * If the restriction matches all objects, the return value will
- * be the empty string. Otherwise it will start with "WHERE ".
- *
- * Return value: the SQL WHERE clause, which the caller must free,
- * or %NULL if @rn could not be converted to SQL.
- **/
-gchar *
-e2k_restriction_to_sql (E2kRestriction *rn)
-{
- GString *sql;
- gchar *ret;
-
- sql = g_string_new (NULL);
- if (!rn_to_sql (rn, sql, E2K_RESTRICTION_AND)) {
- g_string_free (sql, TRUE);
- return NULL;
- }
-
- if (sql->len)
- g_string_prepend (sql, "WHERE ");
-
- ret = sql->str;
- g_string_free (sql, FALSE);
- return ret;
-}
-
-/* Binary import/export */
-
-static gboolean
-extract_restriction (guint8 **data, gint *len, E2kRestriction **rn)
-{
- gint type;
-
- if (*len == 0)
- return FALSE;
- type = (*data)[0];
- (*data)++;
- (*len)--;
-
- switch (type) {
- case E2K_RESTRICTION_AND:
- case E2K_RESTRICTION_OR:
- {
- E2kRestriction **rns;
- guint16 nrns;
- gint i;
-
- if (!e2k_rule_extract_uint16 (data, len, &nrns))
- return FALSE;
- rns = g_new0 (E2kRestriction *, nrns);
- for (i = 0; i < nrns; i++) {
- if (!extract_restriction (data, len, &rns[i])) {
- while (i--)
- e2k_restriction_unref (rns[i]);
- g_free (rns);
- return FALSE;
- }
- }
-
- *rn = conjoin (type, nrns, rns, TRUE);
- return TRUE;
- }
-
- case E2K_RESTRICTION_NOT:
- {
- E2kRestriction *subrn;
-
- if (!extract_restriction (data, len, &subrn))
- return FALSE;
- *rn = e2k_restriction_not (subrn, TRUE);
- return TRUE;
- }
-
- case E2K_RESTRICTION_CONTENT:
- {
- guint32 fuzzy_level;
- E2kRuleProp prop;
- E2kPropValue pv;
-
- if (!e2k_rule_extract_uint32 (data, len, &fuzzy_level) ||
- !e2k_rule_extract_proptag (data, len, &prop) ||
- !e2k_rule_extract_propvalue (data, len, &pv))
- return FALSE;
-
- pv.prop = prop;
-
- *rn = g_new0 (E2kRestriction, 1);
- (*rn)->type = type;
- (*rn)->res.content.fuzzy_level = fuzzy_level;
- (*rn)->res.content.pv = pv;
- return TRUE;
- }
-
- case E2K_RESTRICTION_PROPERTY:
- {
- guint8 relop;
- E2kRuleProp prop;
- E2kPropValue pv;
-
- if (!e2k_rule_extract_byte (data, len, &relop) ||
- !e2k_rule_extract_proptag (data, len, &prop) ||
- !e2k_rule_extract_propvalue (data, len, &pv))
- return FALSE;
-
- pv.prop = prop;
-
- *rn = g_new0 (E2kRestriction, 1);
- (*rn)->type = type;
- (*rn)->res.property.relop = relop;
- (*rn)->res.property.pv = pv;
- return TRUE;
- }
-
- case E2K_RESTRICTION_COMPAREPROPS:
- {
- /* FIXME */
- return FALSE;
- }
-
- case E2K_RESTRICTION_BITMASK:
- {
- guint8 bitop;
- guint32 mask;
- E2kRuleProp prop;
-
- if (!e2k_rule_extract_byte (data, len, &bitop) ||
- !e2k_rule_extract_proptag (data, len, &prop) ||
- !e2k_rule_extract_uint32 (data, len, &mask))
- return FALSE;
-
- *rn = g_new0 (E2kRestriction, 1);
- (*rn)->type = type;
- (*rn)->res.bitmask.bitop = bitop;
- (*rn)->res.bitmask.prop = prop;
- (*rn)->res.bitmask.mask = mask;
- return TRUE;
- }
-
- case E2K_RESTRICTION_SIZE:
- {
- /* FIXME */
- return FALSE;
- }
-
- case E2K_RESTRICTION_EXIST:
- {
- E2kRuleProp prop;
-
- if (!e2k_rule_extract_proptag (data, len, &prop))
- return FALSE;
-
- *rn = g_new0 (E2kRestriction, 1);
- (*rn)->type = type;
- (*rn)->res.exist.prop = prop;
- return TRUE;
- }
-
- case E2K_RESTRICTION_SUBRESTRICTION:
- {
- E2kRuleProp subtable;
- E2kRestriction *subrn;
-
- if (!e2k_rule_extract_proptag (data, len, &subtable) ||
- !extract_restriction (data, len, &subrn))
- return FALSE;
-
- *rn = g_new0 (E2kRestriction, 1);
- (*rn)->type = type;
- (*rn)->res.sub.subtable = subtable;
- (*rn)->res.sub.rn = subrn;
- return TRUE;
- }
-
- case E2K_RESTRICTION_COMMENT:
- {
- guint8 nprops, dummy;
- E2kPropValue *props;
- gint i;
-
- if (!e2k_rule_extract_byte (data, len, &nprops))
- return FALSE;
-
- props = g_new0 (E2kPropValue, nprops);
- for (i = 0; i < nprops; i++) {
- if (!e2k_rule_extract_propvalue (data, len, &props[i])) {
- while (i--)
- e2k_rule_free_propvalue (&props[i]);
- g_free (props);
- return FALSE;
- }
- }
-
- *rn = g_new0 (E2kRestriction, 1);
- (*rn)->type = type;
- (*rn)->res.comment.nprops = nprops;
- (*rn)->res.comment.props = props;
-
- /* FIXME: There is always a "1" byte here, but I don't
- * know why.
- */
- if (!e2k_rule_extract_byte (data, len, &dummy) || dummy != 1) {
- e2k_restriction_unref (*rn);
- return FALSE;
- }
-
- if (!extract_restriction (data, len, &(*rn)->res.comment.rn)) {
- e2k_restriction_unref (*rn);
- return FALSE;
- }
-
- return TRUE;
- }
-
- default:
- return FALSE;
- }
-}
-
-/**
- * e2k_restriction_extract:
- * @data: pointer to data pointer
- * @len: pointer to data length
- * @rn: pointer to variable to store the extracted restriction in
- *
- * Attempts to extract a restriction from *@data, which contains
- * a binary-encoded restriction from a server-side rule.
- *
- * On success, *@rn will contain the extracted restriction, *@data
- * will be advanced past the end of the restriction data, and *@len
- * will be decremented accordingly.
- *
- * Return value: success or failure
- **/
-gboolean
-e2k_restriction_extract (guint8 **data, gint *len, E2kRestriction **rn)
-{
- guint32 rnlen;
-
- if (!e2k_rule_extract_uint32 (data, len, &rnlen))
- return FALSE;
- if (rnlen > *len)
- return FALSE;
-
- if (rnlen == 1 && (*data)[0] == 0xFF) {
- (*data)++;
- (*len)--;
- *rn = NULL;
- return TRUE;
- }
-
- if (*len < 2)
- return FALSE;
- if ((*data)[0] != 0 || (*data)[1] != 0)
- return FALSE;
- (*data) += 2;
- (*len) -= 2;
-
- return extract_restriction (data, len, rn);
-}
-
-static void
-append_restriction (GByteArray *ba, E2kRestriction *rn)
-{
- gint i;
-
- e2k_rule_append_byte (ba, rn->type);
-
- switch (rn->type) {
- case E2K_RESTRICTION_AND:
- case E2K_RESTRICTION_OR:
- e2k_rule_append_uint16 (ba, rn->res.and.nrns);
- for (i = 0; i < rn->res.and.nrns; i++)
- append_restriction (ba, rn->res.and.rns[i]);
- break;
-
- case E2K_RESTRICTION_NOT:
- append_restriction (ba, rn->res.not.rn);
- break;
-
- case E2K_RESTRICTION_CONTENT:
- e2k_rule_append_uint32 (ba, rn->res.content.fuzzy_level);
- e2k_rule_append_proptag (ba, &rn->res.content.pv.prop);
- e2k_rule_append_propvalue (ba, &rn->res.content.pv);
- break;
-
- case E2K_RESTRICTION_PROPERTY:
- e2k_rule_append_byte (ba, rn->res.property.relop);
- e2k_rule_append_proptag (ba, &rn->res.property.pv.prop);
- e2k_rule_append_propvalue (ba, &rn->res.property.pv);
- break;
-
- case E2K_RESTRICTION_COMPAREPROPS:
- /* FIXME */
- break;
-
- case E2K_RESTRICTION_BITMASK:
- e2k_rule_append_byte (ba, rn->res.bitmask.bitop);
- e2k_rule_append_proptag (ba, &rn->res.bitmask.prop);
- e2k_rule_append_uint32 (ba, rn->res.bitmask.mask);
- break;
-
- case E2K_RESTRICTION_SIZE:
- break;
-
- case E2K_RESTRICTION_EXIST:
- e2k_rule_append_proptag (ba, &rn->res.exist.prop);
- break;
-
- case E2K_RESTRICTION_SUBRESTRICTION:
- e2k_rule_append_proptag (ba, &rn->res.sub.subtable);
- append_restriction (ba, rn->res.sub.rn);
- break;
-
- case E2K_RESTRICTION_COMMENT:
- e2k_rule_append_byte (ba, rn->res.comment.nprops);
-
- for (i = 0; i < rn->res.comment.nprops; i++)
- e2k_rule_append_propvalue (ba, &rn->res.comment.props[i]);
-
- /* FIXME: There is always a "1" byte here, but I don't
- * know why.
- */
- e2k_rule_append_byte (ba, 1);
-
- append_restriction (ba, rn->res.comment.rn);
- break;
-
- default:
- break;
- }
-}
-
-/**
- * e2k_restriction_append:
- * @ba: a buffer into which a server-side rule is being constructed
- * @rn: the restriction to append to @ba
- *
- * Appends @rn to @ba as part of a server-side rule.
- **/
-void
-e2k_restriction_append (GByteArray *ba, E2kRestriction *rn)
-{
- gint rnlen_offset, rnlen;
-
- if (!rn) {
- e2k_rule_append_uint32 (ba, 1);
- e2k_rule_append_byte (ba, 0xFF);
- return;
- }
-
- /* Save space for the length field */
- rnlen_offset = ba->len;
- e2k_rule_append_uint32 (ba, 0);
-
- /* FIXME: ??? */
- e2k_rule_append_uint16 (ba, 0);
-
- append_restriction (ba, rn);
-
- rnlen = ba->len - rnlen_offset - 4;
- e2k_rule_write_uint32 (ba->data + rnlen_offset, rnlen);
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __E2K_RESTRICTION_H__
-#define __E2K_RESTRICTION_H__
-
-#include "e2k-types.h"
-
-G_BEGIN_DECLS
-
-typedef enum {
- E2K_RELOP_LT = 0,
- E2K_RELOP_LE = 1,
- E2K_RELOP_GT = 2,
- E2K_RELOP_GE = 3,
- E2K_RELOP_EQ = 4,
- E2K_RELOP_NE = 5,
- E2K_RELOP_RE = 6,
-
- E2K_RELOP_DL_MEMBER = 100
-} E2kRestrictionRelop;
-
-typedef enum {
- E2K_BMR_EQZ = 0,
- E2K_BMR_NEZ = 1
-} E2kRestrictionBitop;
-
-typedef enum {
- E2K_FL_FULLSTRING = 0x00000,
- E2K_FL_SUBSTRING = 0x00001,
- E2K_FL_PREFIX = 0x00002,
- E2K_FL_SUFFIX = 0x00003, /* Not a MAPI constant */
-
- E2K_FL_IGNORECASE = 0x10000,
- E2K_FL_IGNORENONSPACE = 0x20000,
- E2K_FL_LOOSE = 0x40000
-} E2kRestrictionFuzzyLevel;
-
-#define E2K_FL_MATCH_TYPE(fl) ((fl) & 0x3)
-
-E2kRestriction *e2k_restriction_and (gint nrns,
- E2kRestriction **rns,
- gboolean unref);
-E2kRestriction *e2k_restriction_andv (E2kRestriction *rn, ...);
-E2kRestriction *e2k_restriction_or (gint nrns,
- E2kRestriction **rns,
- gboolean unref);
-E2kRestriction *e2k_restriction_orv (E2kRestriction *rn, ...);
-E2kRestriction *e2k_restriction_not (E2kRestriction *rn,
- gboolean unref);
-E2kRestriction *e2k_restriction_content (const gchar *propname,
- E2kRestrictionFuzzyLevel fuzzy_level,
- const gchar *value);
-E2kRestriction *e2k_restriction_prop_bool (const gchar *propname,
- E2kRestrictionRelop relop,
- gboolean value);
-E2kRestriction *e2k_restriction_prop_int (const gchar *propname,
- E2kRestrictionRelop relop,
- gint value);
-E2kRestriction *e2k_restriction_prop_date (const gchar *propname,
- E2kRestrictionRelop relop,
- const gchar *value);
-E2kRestriction *e2k_restriction_prop_string (const gchar *propname,
- E2kRestrictionRelop relop,
- const gchar *value);
-E2kRestriction *e2k_restriction_prop_binary (const gchar *propname,
- E2kRestrictionRelop relop,
- gconstpointer data,
- gint len);
-E2kRestriction *e2k_restriction_compare (const gchar *propname1,
- E2kRestrictionRelop relop,
- const gchar *propname2);
-E2kRestriction *e2k_restriction_bitmask (const gchar *propname,
- E2kRestrictionBitop bitop,
- guint32 mask);
-E2kRestriction *e2k_restriction_size (const gchar *propname,
- E2kRestrictionRelop relop,
- guint32 size);
-E2kRestriction *e2k_restriction_exist (const gchar *propname);
-E2kRestriction *e2k_restriction_sub (const gchar *subtable,
- E2kRestriction *rn,
- gboolean unref);
-
-void e2k_restriction_ref (E2kRestriction *rn);
-void e2k_restriction_unref (E2kRestriction *rn);
-
-gchar *e2k_restriction_to_sql (E2kRestriction *rn);
-
-gboolean e2k_restriction_extract (guint8 **data,
- gint *len,
- E2kRestriction **rn);
-void e2k_restriction_append (GByteArray *ba,
- E2kRestriction *rn);
-
-G_END_DECLS
-
-#endif /* __E2K_RESTRICTION_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2001-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "e2k-result.h"
-#include "e2k-http-utils.h"
-#include "e2k-propnames.h"
-#include "e2k-xml-utils.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/xmlmemory.h>
-
-static void
-prop_get_binary_array (E2kResult *result, const gchar *propname, xmlNode *node)
-{
- GPtrArray *array;
-
- array = g_ptr_array_new ();
- for (node = node->xmlChildrenNode; node; node = node->next) {
- GByteArray *byte_array;
-
- byte_array = g_byte_array_new ();
- if (node->xmlChildrenNode && node->xmlChildrenNode->content) {
- guchar *data;
- gsize length = 0;
-
- data = g_base64_decode (
- (gchar *) node->xmlChildrenNode->content, &length);
- g_byte_array_append (byte_array, data, length);
- g_free (data);
- }
- g_ptr_array_add (array, byte_array);
- }
-
- e2k_properties_set_binary_array (result->props, propname, array);
-}
-
-static void
-prop_get_string_array (E2kResult *result, const gchar *propname,
- E2kPropType real_type, xmlNode *node)
-{
- GPtrArray *array;
-
- array = g_ptr_array_new ();
- for (node = node->xmlChildrenNode; node; node = node->next) {
- if (node->xmlChildrenNode && node->xmlChildrenNode->content)
- g_ptr_array_add (array, g_strdup ((gchar *) node->xmlChildrenNode->content));
- else
- g_ptr_array_add (array, g_strdup (""));
- }
-
- e2k_properties_set_type_as_string_array (result->props, propname,
- real_type, array);
-}
-
-static void
-prop_get_binary (E2kResult *result, const gchar *propname, xmlNode *node)
-{
- GByteArray *byte_array;
-
- byte_array = g_byte_array_new ();
- if (node->xmlChildrenNode && node->xmlChildrenNode->content) {
- guchar *data;
- gsize length = 0;
-
- data = g_base64_decode (
- (gchar *) node->xmlChildrenNode->content, &length);
- g_byte_array_append (byte_array, data, length);
- g_free (data);
- }
-
- e2k_properties_set_binary (result->props, propname, byte_array);
-}
-
-static void
-prop_get_string (E2kResult *result, const gchar *propname,
- E2kPropType real_type, xmlNode *node)
-{
- gchar *content;
-
- if (node->xmlChildrenNode && node->xmlChildrenNode->content)
- content = g_strdup ((gchar *) node->xmlChildrenNode->content);
- else
- content = g_strdup ("");
-
- e2k_properties_set_type_as_string (result->props, propname,
- real_type, content);
-}
-
-static void
-prop_get_xml (E2kResult *result, const gchar *propname, xmlNode *node)
-{
- e2k_properties_set_xml (result->props, propname,
- xmlCopyNode (node, TRUE));
-}
-
-static void
-prop_parse (xmlNode *node, E2kResult *result)
-{
- gchar *name;
- xmlChar *type;
-
- g_return_if_fail (node->ns != NULL);
-
- if (!result->props)
- result->props = e2k_properties_new ();
-
- if (!strncmp ((gchar *) node->ns->href, E2K_NS_MAPI_ID, E2K_NS_MAPI_ID_LEN)) {
- /* Reinsert the illegal initial '0' that was stripped out
- * by sanitize_bad_multistatus. (This also covers us in
- * the cases where the server returns the property without
- * the '0'.)
- */
- name = g_strdup_printf ("%s0%s", node->ns->href, node->name);
- } else
- name = g_strdup_printf ("%s%s", node->ns->href, node->name);
-
- type = xmlGetNsProp (
- node,
- (xmlChar *) "dt",
- (xmlChar *) E2K_NS_TYPE);
- if (type && !xmlStrcmp (type, (xmlChar *) "mv.bin.base64"))
- prop_get_binary_array (result, name, node);
- else if (type && !xmlStrcmp (type, (xmlChar *) "mv.int"))
- prop_get_string_array (result, name, E2K_PROP_TYPE_INT_ARRAY, node);
- else if (type && !xmlStrncmp (type, (xmlChar *) "mv.", 3))
- prop_get_string_array (result, name, E2K_PROP_TYPE_STRING_ARRAY, node);
- else if (type && !xmlStrcmp (type, (xmlChar *) "bin.base64"))
- prop_get_binary (result, name, node);
- else if (type && !xmlStrcmp (type, (xmlChar *) "int"))
- prop_get_string (result, name, E2K_PROP_TYPE_INT, node);
- else if (type && !xmlStrcmp (type, (xmlChar *) "boolean"))
- prop_get_string (result, name, E2K_PROP_TYPE_BOOL, node);
- else if (type && !xmlStrcmp (type, (xmlChar *) "float"))
- prop_get_string (result, name, E2K_PROP_TYPE_FLOAT, node);
- else if (type && !xmlStrcmp (type, (xmlChar *) "dateTime.tz"))
- prop_get_string (result, name, E2K_PROP_TYPE_DATE, node);
- else if (!node->xmlChildrenNode ||
- !node->xmlChildrenNode->xmlChildrenNode)
- prop_get_string (result, name, E2K_PROP_TYPE_STRING, node);
- else
- prop_get_xml (result, name, node);
-
- if (type)
- xmlFree (type);
- g_free (name);
-}
-
-static void
-propstat_parse (xmlNode *node, E2kResult *result)
-{
- node = node->xmlChildrenNode;
- if (!E2K_IS_NODE (node, "DAV:", "status"))
- return;
- result->status = e2k_http_parse_status (
- (gchar *) node->xmlChildrenNode->content);
- if (result->status != E2K_HTTP_OK)
- return;
-
- node = node->next;
- if (!E2K_IS_NODE (node, "DAV:", "prop"))
- return;
-
- for (node = node->xmlChildrenNode; node; node = node->next) {
- if (node->type == XML_ELEMENT_NODE)
- prop_parse (node, result);
- }
-}
-
-static void
-e2k_result_clear (E2kResult *result)
-{
- xmlFree (result->href);
- result->href = NULL;
- if (result->props) {
- e2k_properties_free (result->props);
- result->props = NULL;
- }
-}
-
-/**
- * e2k_results_array_new:
- *
- * Creates a new results array
- *
- * Return value: the array
- **/
-GArray *
-e2k_results_array_new (void)
-{
- return g_array_new (FALSE, FALSE, sizeof (E2kResult));
-}
-
-/* Properties in the /mapi/id/{...} namespaces are usually (though not
- * always) returned with names that start with '0', which is illegal
- * and makes libxml choke. So we preprocess them to fix that.
- */
-static gchar *
-sanitize_bad_multistatus (const gchar *buf, gint len)
-{
- GString *body;
- const gchar *p;
- gint start, end;
- gchar ns, badprop[7], *ret;
-
- /* If there are no "mapi/id/{...}" namespace declarations, then
- * we don't need any cleanup.
- */
- if (!memchr (buf, '{', len))
- return NULL;
-
- body = g_string_new_len (buf, len);
-
- /* Find the start and end of namespace declarations */
- p = strstr (body->str, " xmlns:");
- g_return_val_if_fail (p != NULL, NULL);
- start = p + 1 - body->str;
-
- p = strchr (p, '>');
- g_return_val_if_fail (p != NULL, NULL);
- end = p - body->str;
-
- while (1) {
- if (strncmp (body->str + start, "xmlns:", 6) != 0)
- break;
- if (strncmp (body->str + start + 7, "=\"", 2) != 0)
- break;
- if (strncmp (body->str + start + 9, E2K_NS_MAPI_ID, E2K_NS_MAPI_ID_LEN) != 0)
- goto next;
-
- ns = body->str[start + 6];
-
- /* Find properties in this namespace and strip the
- * initial '0' from their names to make them valid
- * XML NCNames.
- */
- snprintf (badprop, 6, "<%c:0x", ns);
- while ((p = strstr (body->str, badprop)))
- g_string_erase (body, p + 3 - body->str, 1);
- snprintf (badprop, 7, "</%c:0x", ns);
- while ((p = strstr (body->str, badprop)))
- g_string_erase (body, p + 4 - body->str, 1);
-
- next:
- p = strchr (body->str + start, '"');
- if (!p)
- break;
- p = strchr (p + 1, '"');
- if (!p)
- break;
- if (p[1] != ' ')
- break;
-
- start = p + 2 - body->str;
- }
-
- ret = body->str;
- g_string_free (body, FALSE);
- return ret;
-}
-
-/**
- * e2k_results_array_add_from_multistatus:
- * @results_array: a results array, created by e2k_results_array_new()
- * @msg: a 207 Multi-Status response
- *
- * Constructs an #E2kResult for each response in @msg and appends them
- * to @results_array.
- **/
-void
-e2k_results_array_add_from_multistatus (GArray *results_array,
- SoupMessage *msg)
-{
- xmlDoc *doc;
- xmlNode *node, *rnode;
- E2kResult result;
- gchar *body;
-
- g_return_if_fail (msg->status_code == E2K_HTTP_MULTI_STATUS);
-
- body = sanitize_bad_multistatus (msg->response_body->data,
- msg->response_body->length);
- if (body) {
- doc = e2k_parse_xml (body, -1);
- g_free (body);
- } else {
- doc = e2k_parse_xml (msg->response_body->data,
- msg->response_body->length);
- }
- if (!doc)
- return;
- node = doc->xmlRootNode;
- if (!node || !E2K_IS_NODE (node, "DAV:", "multistatus")) {
- xmlFree (doc);
- return;
- }
-
- for (node = node->xmlChildrenNode; node; node = node->next) {
- if (!E2K_IS_NODE (node, "DAV:", "response") ||
- !node->xmlChildrenNode)
- continue;
-
- memset (&result, 0, sizeof (result));
- result.status = E2K_HTTP_OK; /* sometimes omitted if Brief */
-
- for (rnode = node->xmlChildrenNode; rnode; rnode = rnode->next) {
- if (rnode->type != XML_ELEMENT_NODE)
- continue;
-
- if (E2K_IS_NODE (rnode, "DAV:", "href"))
- result.href = (gchar *) xmlNodeGetContent (rnode);
- else if (E2K_IS_NODE (rnode, "DAV:", "status")) {
- result.status = e2k_http_parse_status (
- (gchar *) rnode->xmlChildrenNode->content);
- } else if (E2K_IS_NODE (rnode, "DAV:", "propstat"))
- propstat_parse (rnode, &result);
- else
- prop_parse (rnode, &result);
- }
-
- if (result.href) {
- if (E2K_HTTP_STATUS_IS_SUCCESSFUL (result.status) &&
- !result.props)
- result.props = e2k_properties_new ();
- g_array_append_val (results_array, result);
- } else
- e2k_result_clear (&result);
- }
-
- xmlFreeDoc (doc);
-}
-
-/**
- * e2k_results_array_free:
- * @results_array: the array
- * @free_results: whether or not to also free the contents of the array
- *
- * Frees @results_array, and optionally its contents
- **/
-void
-e2k_results_array_free (GArray *results_array, gboolean free_results)
-{
- if (free_results) {
- e2k_results_free ((E2kResult *)results_array->data,
- results_array->len);
- }
- g_array_free (results_array, FALSE);
-}
-
-/**
- * e2k_results_from_multistatus:
- * @msg: a 207 Multi-Status response
- * @results: pointer to a variable to store an array of E2kResult in
- * @nresults: pointer to a variable to store the length of *@results in
- *
- * Parses @msg and puts the results in *@results and *@nresults.
- * The caller should free the data with e2k_results_free()
- **/
-void
-e2k_results_from_multistatus (SoupMessage *msg,
- E2kResult **results, gint *nresults)
-{
- GArray *results_array;
-
- results_array = e2k_results_array_new ();
- e2k_results_array_add_from_multistatus (results_array, msg);
-
- *results = (E2kResult *)results_array->data;
- *nresults = results_array->len;
- e2k_results_array_free (results_array, FALSE);
-}
-
-/**
- * e2k_results_copy:
- * @results: a results array returned from e2k_results_from_multistatus()
- * @nresults: the length of @results
- *
- * Performs a deep copy of @results
- *
- * Return value: a copy of @results.
- **/
-E2kResult *
-e2k_results_copy (E2kResult *results, gint nresults)
-{
- GArray *results_array = NULL;
- E2kResult result, *new_results;
- gint i;
-
- results_array = g_array_new (TRUE, FALSE, sizeof (E2kResult));
- for (i = 0; i < nresults; i++) {
- result.href = xmlMemStrdup (results[i].href);
- result.status = results[i].status;
- result.props = e2k_properties_copy (results[i].props);
-
- g_array_append_val (results_array, result);
- }
-
- new_results = (E2kResult *) (results_array->data);
- g_array_free (results_array, FALSE);
- return new_results;
-}
-
-/**
- * e2k_results_free:
- * @results: a results array
- * @nresults: the length of @results
- *
- * Frees the data in @results.
- **/
-void
-e2k_results_free (E2kResult *results, gint nresults)
-{
- gint i;
-
- for (i = 0; i < nresults; i++)
- e2k_result_clear (&results[i]);
- g_free (results);
-}
-
-/* Iterators */
-struct E2kResultIter {
- E2kContext *ctx;
- E2kOperation *op;
- E2kHTTPStatus status;
-
- E2kResult *results;
- gint nresults, next;
- gint first, total;
- gboolean ascending;
-
- E2kResultIterFetchFunc fetch_func;
- E2kResultIterFreeFunc free_func;
- gpointer user_data;
-};
-
-static void
-iter_fetch (E2kResultIter *iter)
-{
- if (iter->nresults) {
- if (iter->ascending)
- iter->first += iter->nresults;
- else
- iter->first -= iter->nresults;
- e2k_results_free (iter->results, iter->nresults);
- iter->nresults = 0;
- }
-
- iter->status = iter->fetch_func (iter, iter->ctx, iter->op,
- &iter->results,
- &iter->nresults,
- &iter->first,
- &iter->total,
- iter->user_data);
- iter->next = 0;
-}
-
-/**
- * e2k_result_iter_new:
- * @ctx: an #E2kContext
- * @op: an #E2kOperation, to use for cancellation
- * @ascending: %TRUE if results should be returned in ascending
- * order, %FALSE if they should be returned in descending order
- * @total: the total number of results that will be returned, or -1
- * if not yet known
- * @fetch_func: function to call to fetch more results
- * @free_func: function to call when the iterator is freed
- * @user_data: data to pass to @fetch_func and @free_func
- *
- * Creates a object that can be used to return the results of
- * a Multi-Status query on @ctx.
- *
- * @fetch_func will be called to fetch results, and it may update the
- * #first and #total fields if necessary. If @ascending is %TRUE, then
- * e2k_result_iter_next() will first return the first result, then the
- * second result, etc. If @ascending is %FALSE, it will return the
- * last result, then the second-to-last result, etc.
- *
- * When all of the results returned by the first @fetch_func call have
- * been returned to the caller, @fetch_func will be called again to
- * get more results. This will continue until @fetch_func returns 0
- * results, or returns an error code.
- *
- * Return value: the new iterator
- **/
-E2kResultIter *
-e2k_result_iter_new (E2kContext *ctx, E2kOperation *op,
- gboolean ascending, gint total,
- E2kResultIterFetchFunc fetch_func,
- E2kResultIterFreeFunc free_func,
- gpointer user_data)
-{
- E2kResultIter *iter;
-
- iter = g_new0 (E2kResultIter, 1);
- iter->ctx = g_object_ref (ctx);
- iter->op = op;
- iter->ascending = ascending;
- iter->total = total;
- iter->fetch_func = fetch_func;
- iter->free_func = free_func;
- iter->user_data = user_data;
-
- iter_fetch (iter);
-
- return iter;
-}
-
-/**
- * e2k_result_iter_next:
- * @iter: an #E2kResultIter
- *
- * Returns the next result in the operation being iterated by @iter.
- * If there are no more results, or if an error occurs, it will return
- * %NULL. (The return value of e2k_result_iter_free() distinguishes
- * these two cases.)
- *
- * Return value: the result, or %NULL
- **/
-E2kResult *
-e2k_result_iter_next (E2kResultIter *iter)
-{
- g_return_val_if_fail (iter != NULL, NULL);
-
- if (iter->nresults == 0)
- return NULL;
-
- if (iter->next >= iter->nresults) {
- iter_fetch (iter);
- if (iter->nresults == 0)
- return NULL;
- if (iter->total <= 0)
- iter->status = E2K_HTTP_MALFORMED;
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (iter->status))
- return NULL;
- }
-
- return iter->ascending ?
- &iter->results[iter->next++] :
- &iter->results[iter->nresults - ++iter->next];
-}
-
-/**
- * e2k_result_iter_get_index:
- * @iter: an #E2kResultIter
- *
- * Returns the index of the current result in the complete list of
- * results. Note that for a descending search, %index will start at
- * %total - 1 and count backwards to 0.
- *
- * Return value: the index of the current result
- **/
-gint
-e2k_result_iter_get_index (E2kResultIter *iter)
-{
- g_return_val_if_fail (iter != NULL, -1);
-
- return iter->ascending ?
- iter->first + iter->next - 1 :
- iter->first + (iter->nresults - iter->next);
-}
-
-/**
- * e2k_result_iter_get_total:
- * @iter: an #E2kResultIter
- *
- * Returns the total number of results expected for @iter. Note that
- * in some cases, this may change while the results are being iterated
- * (if objects that match the query are added to or removed from the
- * folder).
- *
- * Return value: the total number of results expected
- **/
-gint
-e2k_result_iter_get_total (E2kResultIter *iter)
-{
- g_return_val_if_fail (iter != NULL, -1);
-
- return iter->total;
-}
-
-/**
- * e2k_result_iter_free:
- * @iter: an #E2kResultIter
- *
- * Frees @iter and all associated memory, and returns a status code
- * indicating whether it ended successfully or not. (Note that the
- * status may be %E2K_HTTP_OK rather than %E2K_HTTP_MULTI_STATUS.)
- *
- * Return value: the final status
- **/
-E2kHTTPStatus
-e2k_result_iter_free (E2kResultIter *iter)
-{
- E2kHTTPStatus status;
-
- g_return_val_if_fail (iter != NULL, E2K_HTTP_MALFORMED);
-
- status = iter->status;
- if (iter->nresults)
- e2k_results_free (iter->results, iter->nresults);
- iter->free_func (iter, iter->user_data);
- g_object_unref (iter->ctx);
- g_free (iter);
-
- return status;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __E2K_RESULT_H__
-#define __E2K_RESULT_H__
-
-#include <libsoup/soup-message.h>
-#include "e2k-properties.h"
-#include "e2k-types.h"
-#include "e2k-http-utils.h"
-
-typedef struct {
- gchar *href;
- gint status;
- E2kProperties *props;
-} E2kResult;
-
-void e2k_results_from_multistatus (SoupMessage *msg,
- E2kResult **results,
- gint *nresults);
-
-E2kResult *e2k_results_copy (E2kResult *results,
- gint nresults);
-
-void e2k_results_free (E2kResult *results,
- gint nresults);
-
-GArray *e2k_results_array_new (void);
-
-void e2k_results_array_add_from_multistatus (GArray *results_array,
- SoupMessage *msg);
-
-void e2k_results_array_free (GArray *results_array,
- gboolean free_results);
-
-typedef struct E2kResultIter E2kResultIter;
-
-typedef E2kHTTPStatus (*E2kResultIterFetchFunc) (E2kResultIter *iter,
- E2kContext *ctx,
- E2kOperation *op,
- E2kResult **results,
- gint *nresults,
- gint *first,
- gint *total,
- gpointer user_data);
-typedef void (*E2kResultIterFreeFunc) (E2kResultIter *iter,
- gpointer user_data);
-
-E2kResultIter *e2k_result_iter_new (E2kContext *ctx,
- E2kOperation *op,
- gboolean ascending,
- gint total,
- E2kResultIterFetchFunc fetch_func,
- E2kResultIterFreeFunc free_func,
- gpointer user_data);
-
-E2kResult *e2k_result_iter_next (E2kResultIter *iter);
-gint e2k_result_iter_get_index (E2kResultIter *iter);
-gint e2k_result_iter_get_total (E2kResultIter *iter);
-E2kHTTPStatus e2k_result_iter_free (E2kResultIter *iter);
-
-#endif /* __E2K_RESULT_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2002-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "e2k-rule-xml.h"
-#include "e2k-action.h"
-#include "e2k-properties.h"
-#include "e2k-propnames.h"
-#include "e2k-proptags.h"
-#include "e2k-utils.h"
-#include "mapi.h"
-
-static const gchar *contains_types[] = { NULL, "contains", NULL, NULL, NULL, "not contains", NULL, NULL };
-static const gchar *subject_types[] = { "is", "contains", "starts with", NULL, "is not", "not contains", "not starts with", NULL };
-#define E2K_FL_NEGATE 4
-#define E2K_FL_MAX 8
-
-#if 0
-static gboolean
-fuzzy_level_from_name (const gchar *name, const gchar *map[],
- gint *fuzzy_level, gboolean *negated)
-{
- gint i;
-
- for (i = 0; i < E2K_FL_MAX; i++) {
- if (map[i] && !strcmp (name, map[i])) {
- *fuzzy_level = i & ~E2K_FL_NEGATE;
- *negated = (*fuzzy_level != i);
- return TRUE;
- }
- }
-
- return FALSE;
-}
-#endif
-
-static inline const gchar *
-fuzzy_level_to_name (gint fuzzy_level, gboolean negated, const gchar *map[])
-{
- fuzzy_level = E2K_FL_MATCH_TYPE (fuzzy_level);
- if (negated)
- fuzzy_level |= E2K_FL_NEGATE;
-
- return map[fuzzy_level];
-}
-
-static const gchar *is_types[] = { NULL, NULL, NULL, NULL, "is", "is not" };
-static const gchar *date_types[] = { "before", "before", "after", "after", NULL, NULL };
-static const gchar *gsizeypes[] = { "less than", "less than", "greater than", "greater than", NULL, NULL };
-
-#if 0
-static gboolean
-relop_from_name (const gchar *name, const gchar *map[],
- E2kRestrictionRelop *relop)
-{
- gint i;
-
- for (i = 0; i < E2K_RELOP_RE; i++) {
- if (map[i] && !strcmp (name, map[i])) {
- *relop = i;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-#endif
-
-static inline const gchar *
-relop_to_name (E2kRestrictionRelop relop, gboolean negated, const gchar *map[])
-{
- static const gint negate_map[] = {
- E2K_RELOP_GE, E2K_RELOP_GT, E2K_RELOP_LE, E2K_RELOP_LT,
- E2K_RELOP_NE, E2K_RELOP_EQ
- };
-
- if (negated)
- relop = negate_map[relop];
-
- return map[relop];
-}
-
-/* Check if @rn encodes Outlook's "Message was sent only to me" rule */
-static gboolean
-restriction_is_only_to_me (E2kRestriction *rn)
-{
- E2kRestriction *sub;
-
- if (rn->type != E2K_RESTRICTION_AND || rn->res.and.nrns != 3)
- return FALSE;
-
- sub = rn->res.and.rns[0];
- if (sub->type != E2K_RESTRICTION_PROPERTY ||
- sub->res.property.relop != E2K_RELOP_EQ ||
- sub->res.property.pv.prop.proptag != E2K_PROPTAG_PR_MESSAGE_TO_ME ||
- sub->res.property.pv.value == NULL)
- return FALSE;
-
- sub = rn->res.and.rns[1];
- if (sub->type != E2K_RESTRICTION_NOT)
- return FALSE;
- sub = sub->res.not.rn;
- if (sub->type != E2K_RESTRICTION_CONTENT ||
- !(sub->res.content.fuzzy_level & E2K_FL_SUBSTRING) ||
- sub->res.content.pv.prop.proptag != E2K_PROPTAG_PR_DISPLAY_TO ||
- strcmp (sub->res.content.pv.value, ";") != 0)
- return FALSE;
-
- sub = rn->res.and.rns[2];
- if (sub->type != E2K_RESTRICTION_PROPERTY ||
- sub->res.content.pv.prop.proptag != E2K_PROPTAG_PR_DISPLAY_CC ||
- strcmp (sub->res.content.pv.value, "") != 0)
- return FALSE;
-
- return TRUE;
-}
-
-/* Check if @rn encodes Outlook's "is a delegatable meeting request" rule */
-static gboolean
-restriction_is_delegation (E2kRestriction *rn)
-{
- E2kRestriction *sub;
-
- if (rn->type != E2K_RESTRICTION_AND || rn->res.and.nrns != 3)
- return FALSE;
-
- sub = rn->res.and.rns[0];
- if (sub->type != E2K_RESTRICTION_CONTENT ||
- E2K_FL_MATCH_TYPE (sub->res.content.fuzzy_level) != E2K_FL_PREFIX ||
- sub->res.content.pv.prop.proptag != E2K_PROPTAG_PR_MESSAGE_CLASS ||
- strcmp (sub->res.content.pv.value, "IPM.Schedule.Meeting") != 0)
- return FALSE;
-
- sub = rn->res.and.rns[1];
- if (sub->type != E2K_RESTRICTION_NOT ||
- sub->res.not.rn->type != E2K_RESTRICTION_EXIST ||
- sub->res.not.rn->res.exist.prop.proptag != E2K_PROPTAG_PR_DELEGATED_BY_RULE)
- return FALSE;
-
- sub = rn->res.and.rns[2];
- if (sub->type != E2K_RESTRICTION_OR || sub->res.or.nrns != 2)
- return FALSE;
-
- sub = rn->res.and.rns[2]->res.or.rns[0];
- if (sub->type != E2K_RESTRICTION_NOT ||
- sub->res.not.rn->type != E2K_RESTRICTION_EXIST ||
- sub->res.not.rn->res.exist.prop.proptag != E2K_PROPTAG_PR_SENSITIVITY)
- return FALSE;
-
- sub = rn->res.and.rns[2]->res.or.rns[1];
- if (sub->type != E2K_RESTRICTION_PROPERTY ||
- sub->res.property.relop != E2K_RELOP_NE ||
- sub->res.property.pv.prop.proptag != E2K_PROPTAG_PR_SENSITIVITY ||
- GPOINTER_TO_INT (sub->res.property.pv.value) != MAPI_SENSITIVITY_PRIVATE)
- return FALSE;
-
- return TRUE;
-}
-
-static xmlNode *
-new_value (xmlNode *part,
- const xmlChar *name,
- const xmlChar *type,
- const xmlChar *value)
-{
- xmlNode *node;
-
- node = xmlNewChild (part, NULL, (xmlChar *) "value", NULL);
- xmlSetProp (node, (xmlChar *) "name", name);
- xmlSetProp (node, (xmlChar *) "type", type);
- if (value)
- xmlSetProp (node, (xmlChar *) "value", value);
-
- return node;
-}
-
-static xmlNode *
-new_value_int (xmlNode *part,
- const xmlChar *name,
- const xmlChar *type,
- const xmlChar *value_name,
- glong value)
-{
- xmlNode *node;
- gchar *str;
-
- node = xmlNewChild (part, NULL, (xmlChar *) "value", NULL);
- xmlSetProp (node, (xmlChar *) "name", name);
- xmlSetProp (node, (xmlChar *) "type", type);
-
- str = g_strdup_printf ("%ld", value);
- xmlSetProp (node, (xmlChar *) value_name, (xmlChar *) str);
- g_free (str);
-
- return node;
-}
-
-static xmlNode *
-new_part (const xmlChar *part_name)
-{
- xmlNode *part;
-
- part = xmlNewNode (NULL, (xmlChar *) "part");
- xmlSetProp (part, (xmlChar *) "name", part_name);
- return part;
-}
-
-static xmlNode *
-match (const xmlChar *part_name,
- const xmlChar *value_name,
- const xmlChar *value_value,
- const xmlChar *string_name,
- const xmlChar *string_value)
-{
- xmlNode *part, *value;
-
- part = new_part (part_name);
- value = new_value (
- part, value_name, (xmlChar *) "option", value_value);
- value = new_value (part, string_name, (xmlChar *) "string", NULL);
- xmlNewTextChild (value, NULL, (xmlChar *) "string", string_value);
-
- return part;
-}
-
-static xmlNode *
-message_is (const xmlChar *name,
- const xmlChar *type_name,
- const xmlChar *kind,
- gboolean negated)
-{
- xmlNode *part;
-
- part = new_part (name);
- new_value (
- part, type_name, (xmlChar *) "option",
- negated ? (xmlChar *) "is not" : (xmlChar *) "is");
- new_value (part, (xmlChar *) "kind", (xmlChar *) "option", kind);
-
- return part;
-}
-
-static xmlNode *
-address_is (E2kRestriction *comment_rn, gboolean recipients, gboolean negated)
-{
- xmlNode *part;
- E2kRestriction *rn;
- E2kPropValue *pv;
- const gchar *relation, *display_name, *p;
- gchar *addr, *full_addr;
- GByteArray *ba;
- gint i;
-
- rn = comment_rn->res.comment.rn;
- if (rn->type != E2K_RESTRICTION_PROPERTY ||
- rn->res.property.relop != E2K_RELOP_EQ)
- return NULL;
- pv = &rn->res.property.pv;
-
- if ((recipients && pv->prop.proptag != E2K_PROPTAG_PR_SEARCH_KEY) ||
- (!recipients && pv->prop.proptag != E2K_PROPTAG_PR_SENDER_SEARCH_KEY))
- return NULL;
-
- relation = relop_to_name (rn->res.property.relop, negated, is_types);
- if (!relation)
- return NULL;
-
- /* Extract the address part */
- ba = pv->value;
- p = strchr ((gchar *)ba->data, ':');
- if (p)
- addr = g_ascii_strdown (p + 1, -1);
- else
- addr = g_ascii_strdown ((gchar *)ba->data, -1);
-
- /* Find the display name in the comment */
- display_name = NULL;
- for (i = 0; i < comment_rn->res.comment.nprops; i++) {
- pv = &comment_rn->res.comment.props[i];
- if (E2K_PROPTAG_TYPE (pv->prop.proptag) == E2K_PT_UNICODE) {
- display_name = pv->value;
- break;
- }
- }
-
- if (display_name)
- full_addr = g_strdup_printf ("%s <%s>", display_name, addr);
- else
- full_addr = g_strdup_printf ("<%s>", addr);
-
- if (recipients) {
- part = match (
- (xmlChar *) "recipient",
- (xmlChar *) "recipient-type",
- (xmlChar *) relation,
- (xmlChar *) "recipient",
- (xmlChar *) full_addr);
- } else {
- part = match (
- (xmlChar *) "sender",
- (xmlChar *) "sender-type",
- (xmlChar *) relation,
- (xmlChar *) "sender",
- (xmlChar *) full_addr);
- }
-
- g_free (full_addr);
- g_free (addr);
- return part;
-}
-
-static gboolean
-restriction_to_xml (E2kRestriction *rn, xmlNode *partset,
- E2kRestrictionType wrap_type, gboolean negated)
-{
- xmlNode *part, *value, *node;
- E2kPropValue *pv;
- const gchar *match_type;
- gint i;
-
- switch (rn->type) {
- case E2K_RESTRICTION_AND:
- case E2K_RESTRICTION_OR:
- /* Check for special rules */
- if (restriction_is_only_to_me (rn)) {
- part = message_is (
- (xmlChar *) "message-to-me",
- (xmlChar *) "message-to-me-type",
- (xmlChar *) "only", negated);
- break;
- } else if (restriction_is_delegation (rn)) {
- part = message_is (
- (xmlChar *) "special-message",
- (xmlChar *) "special-message-type",
- (xmlChar *) "delegated-meeting-request",
- negated);
- break;
- }
-
- /* If we are inside an "and" and hit another "and",
- * we can just remove the extra level:
- * (and foo (and bar baz) quux) =>
- * (and foo bar baz quux)
- * Likewise for "or"s.
- *
- * If we are inside an "and" and hit a "(not (or" (or
- * vice versa), we can use DeMorgan's Law and then
- * apply the above rule:
- * (and foo (not (or bar baz)) quux) =>
- * (and foo (and (not bar) (not baz)) quux) =>
- * (and foo (not bar) (not baz) quux)
- *
- * This handles both cases.
- */
- if ((rn->type == wrap_type && !negated) ||
- (rn->type != wrap_type && negated)) {
- for (i = 0; i < rn->res.and.nrns; i++) {
- if (!restriction_to_xml (rn->res.and.rns[i],
- partset, wrap_type,
- negated))
- return FALSE;
- }
- return TRUE;
- }
-
- /* Otherwise, we have a rule that can't be expressed
- * as "match all" or "match any".
- */
- return FALSE;
-
- case E2K_RESTRICTION_NOT:
- return restriction_to_xml (rn->res.not.rn, partset,
- wrap_type, !negated);
-
- case E2K_RESTRICTION_CONTENT:
- {
- gint fuzzy_level = E2K_FL_MATCH_TYPE (rn->res.content.fuzzy_level);
-
- pv = &rn->res.content.pv;
-
- switch (pv->prop.proptag) {
- case E2K_PROPTAG_PR_BODY:
- match_type = fuzzy_level_to_name (fuzzy_level, negated,
- contains_types);
- if (!match_type)
- return FALSE;
-
- part = match (
- (xmlChar *) "body",
- (xmlChar *) "body-type",
- (xmlChar *) match_type,
- (xmlChar *) "word",
- (xmlChar *) pv->value);
- break;
-
- case E2K_PROPTAG_PR_SUBJECT:
- match_type = fuzzy_level_to_name (fuzzy_level, negated,
- subject_types);
- if (!match_type)
- return FALSE;
-
- part = match (
- (xmlChar *) "subject",
- (xmlChar *) "subject-type",
- (xmlChar *) match_type,
- (xmlChar *) "subject",
- (xmlChar *) pv->value);
- break;
-
- case E2K_PROPTAG_PR_TRANSPORT_MESSAGE_HEADERS:
- match_type = fuzzy_level_to_name (fuzzy_level, negated,
- contains_types);
- if (!match_type)
- return FALSE;
-
- part = match (
- (xmlChar *) "full-headers",
- (xmlChar *) "full-headers-type",
- (xmlChar *) match_type,
- (xmlChar *) "word",
- (xmlChar *) pv->value);
- break;
-
- case E2K_PROPTAG_PR_MESSAGE_CLASS:
- if ((fuzzy_level == E2K_FL_FULLSTRING) &&
- !strcmp (pv->value, "IPM.Note.Rules.OofTemplate.Microsoft")) {
- part = message_is (
- (xmlChar *) "special-message",
- (xmlChar *) "special-message-type",
- (xmlChar *) "oof", negated);
- } else if ((fuzzy_level == E2K_FL_PREFIX) &&
- !strcmp (pv->value, "IPM.Schedule.Meeting")) {
- part = message_is (
- (xmlChar *) "special-message",
- (xmlChar *) "special-message-type",
- (xmlChar *) "meeting-request", negated);
- } else
- return FALSE;
-
- break;
-
- default:
- return FALSE;
- }
- break;
- }
-
- case E2K_RESTRICTION_PROPERTY:
- {
- E2kRestrictionRelop relop;
- const gchar *relation;
-
- relop = rn->res.property.relop;
- if (relop >= E2K_RELOP_RE)
- return FALSE;
-
- pv = &rn->res.property.pv;
-
- switch (pv->prop.proptag) {
- case E2K_PROPTAG_PR_MESSAGE_TO_ME:
- if ((relop == E2K_RELOP_EQ && !pv->value) ||
- (relop == E2K_RELOP_NE && pv->value))
- negated = !negated;
-
- part = message_is (
- (xmlChar *) "message-to-me",
- (xmlChar *) "message-to-me-type",
- (xmlChar *) "to", negated);
- break;
-
- case E2K_PROPTAG_PR_MESSAGE_CC_ME:
- if ((relop == E2K_RELOP_EQ && !pv->value) ||
- (relop == E2K_RELOP_NE && pv->value))
- negated = !negated;
-
- part = message_is (
- (xmlChar *) "message-to-me",
- (xmlChar *) "message-to-me-type",
- (xmlChar *) "cc", negated);
- break;
-
- case E2K_PROPTAG_PR_MESSAGE_DELIVERY_TIME:
- case E2K_PROPTAG_PR_CLIENT_SUBMIT_TIME:
- {
- gchar *timestamp;
-
- relation = relop_to_name (relop, negated, date_types);
- if (!relation)
- return FALSE;
-
- if (pv->prop.proptag == E2K_PROPTAG_PR_MESSAGE_DELIVERY_TIME)
- part = new_part ((xmlChar *) "received-date");
- else
- part = new_part ((xmlChar *) "sent-date");
-
- value = new_value (
- part,
- (xmlChar *) "date-spec-type",
- (xmlChar *) "option",
- (xmlChar *) relation);
- value = new_value (
- part,
- (xmlChar *) "versus",
- (xmlChar *) "datespec", NULL);
-
- node = xmlNewChild (
- value, NULL, (xmlChar *) "datespec", NULL);
- xmlSetProp (
- node,
- (xmlChar *) "type",
- (xmlChar *) "1");
-
- timestamp = g_strdup_printf ("%lu", (gulong)e2k_parse_timestamp (pv->value));
- xmlSetProp (
- node,
- (xmlChar *) "value",
- (xmlChar *) timestamp);
- g_free (timestamp);
- break;
- }
-
- case E2K_PROPTAG_PR_MESSAGE_SIZE:
- relation = relop_to_name (relop, negated, gsizeypes);
- if (!relation)
- return FALSE;
-
- part = new_part ((xmlChar *) "size");
- new_value (
- part,
- (xmlChar *) "size-type",
- (xmlChar *) "option",
- (xmlChar *) relation);
- new_value_int (
- part,
- (xmlChar *) "versus",
- (xmlChar *) "integer",
- (xmlChar *) "integer",
- GPOINTER_TO_INT (pv->value) / 1024);
- break;
-
- case E2K_PROPTAG_PR_IMPORTANCE:
- relation = relop_to_name (relop, negated, is_types);
- if (!relation)
- return FALSE;
-
- part = new_part ((xmlChar *) "importance");
- new_value (
- part,
- (xmlChar *) "importance-type",
- (xmlChar *) "option",
- (xmlChar *) relation);
- new_value_int (
- part,
- (xmlChar *) "importance",
- (xmlChar *) "option",
- (xmlChar *) "value",
- GPOINTER_TO_INT (pv->value));
- break;
-
- case E2K_PROPTAG_PR_SENSITIVITY:
- relation = relop_to_name (relop, negated, is_types);
- if (!relation)
- return FALSE;
-
- part = new_part ((xmlChar *) "sensitivity");
- xmlSetProp (
- part,
- (xmlChar *) "name",
- (xmlChar *) "sensitivity");
- new_value (
- part,
- (xmlChar *) "sensitivity-type",
- (xmlChar *) "option",
- (xmlChar *) relation);
- new_value_int (
- part,
- (xmlChar *) "sensitivity",
- (xmlChar *) "option",
- (xmlChar *) "value",
- GPOINTER_TO_INT (pv->value));
- break;
-
- default:
- return FALSE;
- }
- break;
- }
-
- case E2K_RESTRICTION_COMMENT:
- part = address_is (rn, FALSE, negated);
- if (!part)
- return FALSE;
- break;
-
- case E2K_RESTRICTION_BITMASK:
- if (rn->res.bitmask.prop.proptag != E2K_PROPTAG_PR_MESSAGE_FLAGS ||
- rn->res.bitmask.mask != MAPI_MSGFLAG_HASATTACH)
- return FALSE;
-
- part = new_part ((xmlChar *) "attachments");
- if (rn->res.bitmask.bitop == E2K_BMR_NEZ) {
- new_value (
- part,
- (xmlChar *) "match-type",
- (xmlChar *) "option",
- negated ?
- (xmlChar *) "not exist" :
- (xmlChar *) "exist");
- } else {
- new_value (
- part,
- (xmlChar *) "match-type",
- (xmlChar *) "option",
- negated ?
- (xmlChar *) "exist" :
- (xmlChar *) "not exist");
- }
- break;
-
- case E2K_RESTRICTION_SUBRESTRICTION:
- if (rn->res.sub.subtable.proptag != E2K_PROPTAG_PR_MESSAGE_RECIPIENTS)
- return FALSE;
- if (rn->res.sub.rn->type != E2K_RESTRICTION_COMMENT)
- return FALSE;
-
- part = address_is (rn->res.sub.rn, TRUE, negated);
- if (!part)
- return FALSE;
- break;
-
- default:
- return FALSE;
- }
-
- xmlAddChild (partset, part);
- return TRUE;
-}
-
-static gchar *
-stringify_entryid (guint8 *data, gint len)
-{
- GString *string;
- gchar *ret;
- gint i;
-
- string = g_string_new (NULL);
-
- for (i = 0; i < len && i < 22; i++)
- g_string_append_printf (string, "%02x", data[i]);
- if (i < len && data[i]) {
- for (; i < len; i++)
- g_string_append_printf (string, "%02x", data[i]);
- }
-
- ret = string->str;
- g_string_free (string, FALSE);
- return ret;
-}
-
-static gboolean
-action_to_xml (E2kAction *act, xmlNode *actionset)
-{
- xmlNode *part, *value;
- gchar *entryid;
-
- switch (act->type) {
- case E2K_ACTION_MOVE:
- case E2K_ACTION_COPY:
- part = new_part (
- act->type == E2K_ACTION_MOVE ?
- (xmlChar *) "move-to-folder" :
- (xmlChar *) "copy-to-folder");
- value = new_value (
- part,
- (xmlChar *) "folder",
- (xmlChar *) "folder-source-key", NULL);
- entryid = stringify_entryid (
- act->act.xfer.folder_source_key->data + 1,
- act->act.xfer.folder_source_key->len - 1);
- xmlNewTextChild (
- value, NULL,
- (xmlChar *) "entryid",
- (xmlChar *) entryid);
- g_free (entryid);
- break;
-
- case E2K_ACTION_REPLY:
- case E2K_ACTION_OOF_REPLY:
- part = new_part (
- act->type == E2K_ACTION_REPLY ?
- (xmlChar *) "reply" :
- (xmlChar *) "oof-reply");
- value = new_value (
- part,
- (xmlChar *) "template",
- (xmlChar *) "message-entryid", NULL);
- entryid = stringify_entryid (
- act->act.reply.entryid->data,
- act->act.reply.entryid->len);
- xmlNewTextChild (
- value, NULL,
- (xmlChar *) "entryid",
- (xmlChar *) entryid);
- g_free (entryid);
- break;
-
- case E2K_ACTION_DEFER:
- part = new_part ((xmlChar *) "defer");
- break;
-
- case E2K_ACTION_BOUNCE:
- part = new_part ((xmlChar *) "bounce");
- switch (act->act.bounce_code) {
- case E2K_ACTION_BOUNCE_CODE_TOO_LARGE:
- new_value (
- part,
- (xmlChar *) "bounce_code",
- (xmlChar *) "option",
- (xmlChar *) "size");
- break;
- case E2K_ACTION_BOUNCE_CODE_FORM_MISMATCH:
- new_value (
- part,
- (xmlChar *) "bounce_code",
- (xmlChar *) "option",
- (xmlChar *) "form-mismatch");
- break;
- case E2K_ACTION_BOUNCE_CODE_ACCESS_DENIED:
- new_value (
- part,
- (xmlChar *) "bounce_code",
- (xmlChar *) "option",
- (xmlChar *) "permission");
- break;
- }
- break;
-
- case E2K_ACTION_FORWARD:
- case E2K_ACTION_DELEGATE:
- {
- gint i, j;
- E2kAddrList *list;
- E2kAddrEntry *entry;
- E2kPropValue *pv;
- const gchar *display_name, *email;
- gchar *full_addr;
-
- list = act->act.addr_list;
- for (i = 0; i < list->nentries; i++) {
- entry = &list->entry[i];
- display_name = email = NULL;
- for (j = 0; j < entry->nvalues; j++) {
- pv = &entry->propval[j];
- if (pv->prop.proptag == E2K_PROPTAG_PR_TRANSMITTABLE_DISPLAY_NAME)
- display_name = pv->value;
- else if (pv->prop.proptag == E2K_PROPTAG_PR_EMAIL_ADDRESS)
- email = pv->value;
- }
-
- if (!email)
- continue;
- if (display_name)
- full_addr = g_strdup_printf ("%s <%s>", display_name, email);
- else
- full_addr = g_strdup_printf ("<%s>", email);
-
- part = new_part (
- act->type == E2K_ACTION_FORWARD ?
- (xmlChar *) "forward" :
- (xmlChar *) "delegate");
- value = new_value (
- part,
- (xmlChar *) "recipient",
- (xmlChar *) "recipient", NULL);
- xmlNewTextChild (
- value, NULL,
- (xmlChar *) "recipient",
- (xmlChar *) full_addr);
- g_free (full_addr);
-
- xmlAddChild (actionset, part);
- }
- return TRUE;
- }
-
- case E2K_ACTION_TAG:
- if (act->act.proptag.prop.proptag != E2K_PROPTAG_PR_IMPORTANCE)
- return FALSE;
-
- part = new_part ((xmlChar *) "set-importance");
- new_value_int (
- part,
- (xmlChar *) "importance",
- (xmlChar *) "option",
- (xmlChar *) "value",
- GPOINTER_TO_INT (act->act.proptag.value));
- break;
-
- case E2K_ACTION_DELETE:
- part = new_part ((xmlChar *) "delete");
- break;
-
- case E2K_ACTION_MARK_AS_READ:
- part = new_part ((xmlChar *) "mark-read");
- break;
-
- default:
- return FALSE;
- }
-
- xmlAddChild (actionset, part);
- return TRUE;
-}
-
-static gboolean
-rule_to_xml (E2kRule *rule, xmlNode *ruleset)
-{
- xmlNode *top, *set;
- E2kRestriction *rn;
- gint i;
-
- top = xmlNewChild (ruleset, NULL, (xmlChar *) "rule", NULL);
-
- xmlSetProp (
- top,
- (xmlChar *) "source",
- (rule->state & E2K_RULE_STATE_ONLY_WHEN_OOF) ?
- (xmlChar *) "oof" : (xmlChar *) "incoming");
- xmlSetProp (
- top,
- (xmlChar *) "enabled",
- (rule->state & E2K_RULE_STATE_ENABLED) ?
- (xmlChar *) "1" : (xmlChar *) "0");
-
- if (rule->name)
- xmlNewTextChild (
- top, NULL,
- (xmlChar *) "title",
- (xmlChar *) rule->name);
-
- set = xmlNewChild (top, NULL, (xmlChar *) "partset", NULL);
- rn = rule->condition;
- if (rn) {
- E2kRestrictionType wrap_type;
-
- if (rn->type == E2K_RESTRICTION_OR) {
- xmlSetProp (
- top,
- (xmlChar *) "grouping",
- (xmlChar *) "any");
- wrap_type = E2K_RESTRICTION_OR;
- } else {
- xmlSetProp (
- top,
- (xmlChar *) "grouping",
- (xmlChar *) "all");
- wrap_type = E2K_RESTRICTION_AND;
- }
-
- if (!restriction_to_xml (rn, set, wrap_type, FALSE)) {
- g_warning ("could not express restriction as xml");
- xmlUnlinkNode (top);
- xmlFreeNode (top);
- return FALSE;
- }
- } else
- xmlSetProp (top, (xmlChar *) "grouping", (xmlChar *) "all");
-
- set = xmlNewChild (top, NULL, (xmlChar *) "actionset", NULL);
- for (i = 0; i < rule->actions->len; i++) {
- if (!action_to_xml (rule->actions->pdata[i], set)) {
- g_warning ("could not express action as xml");
- xmlUnlinkNode (top);
- xmlFreeNode (top);
- return FALSE;
- }
- }
-
- if (rule->state & E2K_RULE_STATE_EXIT_LEVEL)
- xmlAddChild (set, new_part ((xmlChar *) "stop"));
-
- return TRUE;
-}
-
-/**
- * e2k_rules_to_xml:
- * @rules: an #E2kRules
- *
- * Encodes @rules into an XML format like that used by the evolution
- * filter code.
- *
- * Return value: the XML rules
- **/
-xmlDoc *
-e2k_rules_to_xml (E2kRules *rules)
-{
- xmlDoc *doc;
- xmlNode *top, *ruleset;
- gint i;
-
- doc = xmlNewDoc (NULL);
- top = xmlNewNode (NULL, (xmlChar *) "filteroptions");
- xmlDocSetRootElement (doc, top);
-
- ruleset = xmlNewChild (top, NULL, (xmlChar *) "ruleset", NULL);
-
- for (i = 0; i < rules->rules->len; i++)
- rule_to_xml (rules->rules->pdata[i], ruleset);
-
- return doc;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2003, 2004 Novell, Inc. */
-
-#ifndef __E2K_RULE_XML_H__
-#define __E2K_RULE_XML_H__
-
-#include "e2k-types.h"
-#include "e2k-rule.h"
-
-xmlDoc *e2k_rules_to_xml (E2kRules *rules);
-
-#endif /* __E2K_RULE_XML_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2003, 2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "e2k-rule.h"
-#include "e2k-action.h"
-#include "e2k-properties.h"
-#include "e2k-propnames.h"
-#include "e2k-utils.h"
-
-/**
- * e2k_rule_prop_set:
- * @prop: an #E2kRuleProp
- * @propname: a MAPI property name
- *
- * This is a convenience function to set both the %name and %proptag
- * fields of @prop.
- **/
-void
-e2k_rule_prop_set (E2kRuleProp *prop, const gchar *propname)
-{
- prop->name = propname;
- prop->proptag = e2k_prop_proptag (propname);
-}
-
-/**
- * e2k_rule_write_uint32:
- * @ptr: pointer into a binary rule
- * @val: a uint32 value
- *
- * Writes @val into the rule at @ptr
- **/
-void
-e2k_rule_write_uint32 (guint8 *ptr, guint32 val)
-{
- *ptr++ = ( val & 0xFF);
- *ptr++ = ((val >> 8) & 0xFF);
- *ptr++ = ((val >> 16) & 0xFF);
- *ptr++ = ((val >> 24) & 0xFF);
-}
-
-/**
- * e2k_rule_append_uint32:
- * @ba: a byte array containing a binary rule
- * @val: a uint32 value
- *
- * Appends @val to the rule in @ba
- **/
-void
-e2k_rule_append_uint32 (GByteArray *ba, guint32 val)
-{
- g_byte_array_set_size (ba, ba->len + 4);
- e2k_rule_write_uint32 (ba->data + ba->len - 4, val);
-}
-
-/**
- * e2k_rule_read_uint32:
- * @ptr: pointer into a binary rule
- *
- * Reads a uint32 value from the rule at @ptr
- *
- * Return value: the uint32 value
- **/
-guint32
-e2k_rule_read_uint32 (guint8 *ptr)
-{
- return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
-}
-
-/**
- * e2k_rule_extract_uint32:
- * @ptr: pointer to a pointer into a binary rule
- * @len: pointer to the remaining length of *@ptr
- * @val: pointer to a uint32 value
- *
- * Reads a uint32 value from the rule at **@ptr into *@val and updates
- * *@ptr and *@len accordingly.
- *
- * Return value: success or failure
- **/
-gboolean
-e2k_rule_extract_uint32 (guint8 **ptr, gint *len, guint32 *val)
-{
- if (*len < 4)
- return FALSE;
-
- *val = e2k_rule_read_uint32 (*ptr);
-
- *ptr += 4;
- *len -= 4;
- return TRUE;
-}
-
-/**
- * e2k_rule_write_uint16:
- * @ptr: pointer into a binary rule
- * @val: a uint16 value
- *
- * Writes @val into the rule at @ptr
- **/
-void
-e2k_rule_write_uint16 (guint8 *ptr, guint16 val)
-{
- *ptr++ = ( val & 0xFF);
- *ptr++ = ((val >> 8) & 0xFF);
-}
-
-/**
- * e2k_rule_append_uint16:
- * @ba: a byte array containing a binary rule
- * @val: a uint16 value
- *
- * Appends @val to the rule in @ba
- **/
-void
-e2k_rule_append_uint16 (GByteArray *ba, guint16 val)
-{
- g_byte_array_set_size (ba, ba->len + 2);
- e2k_rule_write_uint16 (ba->data + ba->len - 2, val);
-}
-
-/**
- * e2k_rule_read_uint16:
- * @ptr: pointer into a binary rule
- *
- * Reads a uint16 value from the rule at @ptr
- *
- * Return value: the uint16 value
- **/
-guint16
-e2k_rule_read_uint16 (guint8 *ptr)
-{
- return ptr[0] | (ptr[1] << 8);
-}
-
-/**
- * e2k_rule_extract_uint16:
- * @ptr: pointer to a pointer into a binary rule
- * @len: pointer to the remaining length of *@ptr
- * @val: pointer to a uint16 value
- *
- * Reads a uint16 value from the rule at **@ptr into *@val and updates
- * *@ptr and *@len accordingly.
- *
- * Return value: success or failure
- **/
-gboolean
-e2k_rule_extract_uint16 (guint8 **ptr, gint *len, guint16 *val)
-{
- if (*len < 2)
- return FALSE;
-
- *val = e2k_rule_read_uint16 (*ptr);
-
- *ptr += 2;
- *len -= 2;
- return TRUE;
-}
-
-/**
- * e2k_rule_append_byte:
- * @ba: a byte array containing a binary rule
- * @val: a byte value
- *
- * Appends @val to the rule in @ba
- **/
-void
-e2k_rule_append_byte (GByteArray *ba, guint8 val)
-{
- g_byte_array_append (ba, &val, 1);
-}
-
-/**
- * e2k_rule_extract_byte:
- * @ptr: pointer to a pointer into a binary rule
- * @len: pointer to the remaining length of *@ptr
- * @val: pointer to a byte value
- *
- * Reads a byte value from the rule at **@ptr into *@val and updates
- * *@ptr and *@len accordingly.
- *
- * Return value: success or failure
- **/
-gboolean
-e2k_rule_extract_byte (guint8 **ptr, gint *len, guint8 *val)
-{
- if (*len < 1)
- return FALSE;
-
- *val = **ptr;
-
- *ptr += 1;
- *len -= 1;
- return TRUE;
-}
-
-/**
- * e2k_rule_append_string:
- * @ba: a byte array containing a binary rule
- * @str: a (Windows) locale-encoded string
- *
- * Appends @str to the rule in @ba
- **/
-void
-e2k_rule_append_string (GByteArray *ba, const gchar *str)
-{
- /* FIXME: verify encoding */
- g_byte_array_append (ba, (guint8 *) str, strlen (str) + 1);
-}
-
-/**
- * e2k_rule_extract_string:
- * @ptr: pointer to a pointer into a binary rule
- * @len: pointer to the remaining length of *@ptr
- * @str: pointer to a string pointer
- *
- * Reads a (Windows) locale-encoded string from the rule at **@ptr
- * into *@str and updates *@ptr and *@len accordingly.
- *
- * Return value: success or failure
- **/
-gboolean
-e2k_rule_extract_string (guint8 **ptr, gint *len, gchar **str)
-{
- gint slen;
-
- for (slen = 0; slen < *len; slen++) {
- if ((*ptr)[slen] == '\0') {
- *str = g_strdup ((gchar *) *ptr);
- *ptr += slen + 1;
- *len -= slen + 1;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/**
- * e2k_rule_append_unicode:
- * @ba: a byte array containing a binary rule
- * @str: a UTF-8 string
- *
- * Appends @str to the rule in @ba
- **/
-void
-e2k_rule_append_unicode (GByteArray *ba, const gchar *str)
-{
- gunichar2 *utf16;
- gint i;
-
- utf16 = g_utf8_to_utf16 (str, -1, NULL, NULL, NULL);
- g_return_if_fail (utf16 != NULL);
-
- for (i = 0; utf16[i]; i++)
- e2k_rule_append_uint16 (ba, utf16[i]);
- e2k_rule_append_uint16 (ba, 0);
- g_free (utf16);
-}
-
-/**
- * e2k_rule_extract_unicode:
- * @ptr: pointer to a pointer into a binary rule
- * @len: pointer to the remaining length of *@ptr
- * @str: pointer to a string pointer
- *
- * Reads a Unicode-encoded string from the rule at **@ptr into *@str
- * and updates *@ptr and *@len accordingly.
- *
- * Return value: success or failure
- **/
-gboolean
-e2k_rule_extract_unicode (guint8 **ptr, gint *len, gchar **str)
-{
- guint8 *start, *end;
- gunichar2 *utf16;
-
- start = *ptr;
- end = *ptr + *len;
-
- for (; *ptr < end - 1; (*ptr) += 2) {
- if ((*ptr)[0] == '\0' && (*ptr)[1] == '\0') {
- *ptr += 2;
- *len -= *ptr - start;
-
- utf16 = g_memdup (start, *ptr - start);
- *str = g_utf16_to_utf8 (utf16, -1, NULL, NULL, NULL);
- g_free (utf16);
- return TRUE;
- }
- }
- return FALSE;
-}
-
-/**
- * e2k_rule_append_binary:
- * @ba: a byte array containing a binary rule
- * @data: binary data
- *
- * Appends @data (with a 2-byte length prefix) to the rule in @ba
- **/
-void
-e2k_rule_append_binary (GByteArray *ba, GByteArray *data)
-{
- e2k_rule_append_uint16 (ba, data->len);
- g_byte_array_append (ba, data->data, data->len);
-}
-
-/**
- * e2k_rule_extract_binary:
- * @ptr: pointer to a pointer into a binary rule
- * @len: pointer to the remaining length of *@ptr
- * @data: pointer to a #GByteArray
- *
- * Reads binary data (preceded by a 2-byte length) from the rule at
- * **@ptr into *@data and updates *@ptr and *@len accordingly.
- *
- * Return value: success or failure
- **/
-gboolean
-e2k_rule_extract_binary (guint8 **ptr, gint *len, GByteArray **data)
-{
- guint16 datalen;
-
- if (!e2k_rule_extract_uint16 (ptr, len, &datalen))
- return FALSE;
- if (*len < datalen)
- return FALSE;
-
- *data = g_byte_array_sized_new (datalen);
- memcpy ((*data)->data, *ptr, datalen);
- (*data)->len = datalen;
-
- *ptr += datalen;
- *len -= datalen;
- return TRUE;
-}
-
-#define E2K_PT_UNICODE_RULE 0x84b0
-
-/**
- * e2k_rule_append_proptag:
- * @ba: a byte array containing a binary rule
- * @prop: an #E2kRuleProp
- *
- * Appends a representation of @prop to the rule in @ba
- **/
-void
-e2k_rule_append_proptag (GByteArray *ba, E2kRuleProp *prop)
-{
- guint32 proptag = prop->proptag;
-
- if (E2K_PROPTAG_TYPE (proptag) == E2K_PT_STRING8 ||
- E2K_PROPTAG_TYPE (proptag) == E2K_PT_UNICODE)
- proptag = E2K_PROPTAG_ID (proptag) | E2K_PT_UNICODE_RULE;
-
- e2k_rule_append_uint32 (ba, proptag);
-}
-
-/**
- * e2k_rule_extract_proptag:
- * @ptr: pointer to a pointer into a binary rule
- * @len: pointer to the remaining length of *@ptr
- * @prop: poitner to an #E2kRuleProp
- *
- * Reads a proptag from the rule at **@ptr into *@prop and updates
- * *@ptr and *@len accordingly.
- *
- * Return value: success or failure
- **/
-gboolean
-e2k_rule_extract_proptag (guint8 **ptr, gint *len, E2kRuleProp *prop)
-{
- if (!e2k_rule_extract_uint32 (ptr, len, &prop->proptag))
- return FALSE;
-
- if (E2K_PROPTAG_TYPE (prop->proptag) == E2K_PT_UNICODE_RULE)
- prop->proptag = E2K_PROPTAG_ID (prop->proptag) | E2K_PT_UNICODE;
- prop->name = e2k_proptag_prop (prop->proptag);
-
- return TRUE;
-}
-
-/**
- * e2k_rule_append_propvalue:
- * @ba: a byte array containing a binary rule
- * @pv: an #E2kPropValue
- *
- * Appends a representation of @pv (the proptag and its value) to the
- * rule in @ba
- **/
-void
-e2k_rule_append_propvalue (GByteArray *ba, E2kPropValue *pv)
-{
- g_return_if_fail (pv->prop.proptag != 0);
-
- e2k_rule_append_proptag (ba, &pv->prop);
-
- switch (E2K_PROPTAG_TYPE (pv->prop.proptag)) {
- case E2K_PT_UNICODE:
- case E2K_PT_STRING8:
- e2k_rule_append_unicode (ba, pv->value);
- break;
-
- case E2K_PT_BINARY:
- e2k_rule_append_binary (ba, pv->value);
- break;
-
- case E2K_PT_LONG:
- e2k_rule_append_uint32 (ba, GPOINTER_TO_UINT (pv->value));
- break;
-
- case E2K_PT_BOOLEAN:
- e2k_rule_append_byte (ba, GPOINTER_TO_UINT (pv->value));
- break;
-
- default:
- /* FIXME */
- break;
- }
-}
-
-/**
- * e2k_rule_extract_propvalue:
- * @ptr: pointer to a pointer into a binary rule
- * @len: pointer to the remaining length of *@ptr
- * @pv: pointer to an #E2kPropValue
- *
- * Reads a representation of an #E2kPropValue from the rule at **@ptr
- * into *@pv and updates *@ptr and *@len accordingly.
- *
- * Return value: success or failure
- **/
-gboolean
-e2k_rule_extract_propvalue (guint8 **ptr, gint *len, E2kPropValue *pv)
-{
- if (!e2k_rule_extract_proptag (ptr, len, &pv->prop))
- return FALSE;
-
- switch (E2K_PROPTAG_TYPE (pv->prop.proptag)) {
- case E2K_PT_UNICODE:
- case E2K_PT_STRING8:
- pv->type = E2K_PROP_TYPE_STRING;
- return e2k_rule_extract_unicode (ptr, len, (gchar **)&pv->value);
-
- case E2K_PT_BINARY:
- pv->type = E2K_PROP_TYPE_BINARY;
- return e2k_rule_extract_binary (ptr, len, (GByteArray **)&pv->value);
-
- case E2K_PT_SYSTIME:
- {
- guint64 temp;
-
- if (*len < 8)
- return FALSE;
-
- memcpy (&temp, *ptr, 8);
- *ptr += 8;
- *len -= 8;
-
- temp = GUINT64_FROM_LE (temp);
- pv->type = E2K_PROP_TYPE_DATE;
- pv->value = e2k_make_timestamp (e2k_filetime_to_time_t (temp));
- return TRUE;
- }
-
- case E2K_PT_LONG:
- {
- guint32 temp;
-
- if (!e2k_rule_extract_uint32 (ptr, len, &temp))
- return FALSE;
- pv->type = E2K_PROP_TYPE_INT;
- pv->value = GUINT_TO_POINTER (temp);
- return TRUE;
- }
-
- case E2K_PT_BOOLEAN:
- {
- guint8 temp;
-
- if (!e2k_rule_extract_byte (ptr, len, &temp))
- return FALSE;
- pv->type = E2K_PROP_TYPE_BOOL;
- pv->value = GUINT_TO_POINTER ((guint)temp);
- return TRUE;
- }
-
- default:
- /* FIXME */
- return FALSE;
- }
-}
-
-/**
- * e2k_rule_free_propvalue:
- * @pv: an #E2kPropValue
- *
- * Frees @pv
- **/
-void
-e2k_rule_free_propvalue (E2kPropValue *pv)
-{
- if (pv->type == E2K_PROP_TYPE_STRING ||
- pv->type == E2K_PROP_TYPE_DATE)
- g_free (pv->value);
- else if (pv->type == E2K_PROP_TYPE_BINARY && pv->value)
- g_byte_array_free (pv->value, TRUE);
-}
-
-/**
- * e2k_rule_free:
- * @rule: an #E2kRule
- *
- * Frees @rule
- **/
-void
-e2k_rule_free (E2kRule *rule)
-{
- if (rule->name)
- g_free (rule->name);
- if (rule->condition)
- e2k_restriction_unref (rule->condition);
- if (rule->actions)
- e2k_actions_free (rule->actions);
- if (rule->provider)
- g_free (rule->provider);
- if (rule->provider_data)
- g_byte_array_free (rule->provider_data, TRUE);
-}
-
-/**
- * e2k_rules_free:
- * @rules: an #E2kRules structure
- *
- * Frees @rules and the rules it contains
- **/
-void
-e2k_rules_free (E2kRules *rules)
-{
- gint i;
-
- for (i = 0; i < rules->rules->len; i++)
- e2k_rule_free (rules->rules->pdata[i]);
- g_ptr_array_free (rules->rules, TRUE);
- g_free (rules);
-}
-
-/**
- * e2k_rules_from_binary:
- * @rules_data: binary-encoded rules data
- *
- * Extract rules from @rules_data and returns them in an #E2kRules
- * structure.
- *
- * Return value: the rules, or %NULL on error.
- **/
-E2kRules *
-e2k_rules_from_binary (GByteArray *rules_data)
-{
- guint8 *data;
- gint len, i;
- guint32 nrules, pdlen;
- E2kRules *rules;
- E2kRule *rule;
-
- data = rules_data->data;
- len = rules_data->len;
-
- if (len < 9)
- return NULL;
- if (*data != 2)
- return NULL;
- data++;
- len--;
-
- rules = g_new0 (E2kRules, 1);
- rules->version = 2;
-
- if (!e2k_rule_extract_uint32 (&data, &len, &nrules) ||
- !e2k_rule_extract_uint32 (&data, &len, &rules->codepage)) {
- g_free (rules);
- return NULL;
- }
-
- rules->rules = g_ptr_array_new ();
- for (i = 0; i < nrules; i++) {
- rule = g_new0 (E2kRule, 1);
- g_ptr_array_add (rules->rules, rule);
-
- if (!e2k_rule_extract_uint32 (&data, &len, &rule->sequence) ||
- !e2k_rule_extract_uint32 (&data, &len, &rule->state) ||
- !e2k_rule_extract_uint32 (&data, &len, &rule->user_flags) ||
- !e2k_rule_extract_uint32 (&data, &len, &rule->condition_lcid) ||
- !e2k_restriction_extract (&data, &len, &rule->condition) ||
- !e2k_actions_extract (&data, &len, &rule->actions) ||
- !e2k_rule_extract_string (&data, &len, &rule->provider) ||
- !e2k_rule_extract_string (&data, &len, &rule->name) ||
- !e2k_rule_extract_uint32 (&data, &len, &rule->level))
- goto error;
-
- /* The provider data has a 4-byte length, unlike the
- * binary fields in a condition or rule.
- */
- if (!e2k_rule_extract_uint32 (&data, &len, &pdlen))
- goto error;
- if (len < pdlen)
- goto error;
- rule->provider_data = g_byte_array_sized_new (pdlen);
- rule->provider_data->len = pdlen;
- memcpy (rule->provider_data->data, data, pdlen);
- data += pdlen;
- len -= pdlen;
- }
-
- return rules;
-
- error:
- e2k_rules_free (rules);
- return NULL;
-}
-
-/**
- * e2k_rules_to_binary:
- * @rules: an #E2kRules structure
- *
- * Encodes @rules into binary form
- *
- * Return value: the binary-encoded rules
- **/
-GByteArray *
-e2k_rules_to_binary (E2kRules *rules)
-{
- GByteArray *ba;
- E2kRule *rule;
- gint i;
-
- ba = g_byte_array_new ();
- e2k_rule_append_byte (ba, rules->version);
- e2k_rule_append_uint32 (ba, rules->rules->len);
- e2k_rule_append_uint32 (ba, rules->codepage);
-
- for (i = 0; i < rules->rules->len; i++) {
- rule = rules->rules->pdata[i];
-
- e2k_rule_append_uint32 (ba, rule->sequence);
- e2k_rule_append_uint32 (ba, rule->state);
- e2k_rule_append_uint32 (ba, rule->user_flags);
- e2k_rule_append_uint32 (ba, rule->condition_lcid);
- e2k_restriction_append (ba, rule->condition);
- e2k_actions_append (ba, rule->actions);
- e2k_rule_append_string (ba, rule->provider);
- e2k_rule_append_string (ba, rule->name);
- e2k_rule_append_uint32 (ba, rule->level);
-
- /* The provider data has a 4-byte length, unlike the
- * binary fields in a condition or rule.
- */
- e2k_rule_append_uint32 (ba, rule->provider_data->len);
- g_byte_array_append (ba, rule->provider_data->data,
- rule->provider_data->len);
- }
-
- return ba;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2003, 2004 Novell, Inc. */
-
-#ifndef __E2K_RULE_H__
-#define __E2K_RULE_H__
-
-#include "e2k-types.h"
-#include "e2k-properties.h"
-#include "e2k-restriction.h"
-
-/* We define these types here because they're private to libexchange,
- * so code that #includes e2k-restriction, etc, shouldn't see them.
- */
-
-typedef struct {
- const gchar *name;
- guint32 proptag;
-} E2kRuleProp;
-
-void e2k_rule_prop_set (E2kRuleProp *prop, const gchar *propname);
-
-typedef struct {
- E2kRuleProp prop;
- E2kPropType type;
- gpointer value;
-} E2kPropValue;
-
-typedef enum {
- E2K_RESTRICTION_AND = 0,
- E2K_RESTRICTION_OR = 1,
- E2K_RESTRICTION_NOT = 2,
- E2K_RESTRICTION_CONTENT = 3,
- E2K_RESTRICTION_PROPERTY = 4,
- E2K_RESTRICTION_COMPAREPROPS = 5,
- E2K_RESTRICTION_BITMASK = 6,
- E2K_RESTRICTION_SIZE = 7,
- E2K_RESTRICTION_EXIST = 8,
- E2K_RESTRICTION_SUBRESTRICTION = 9,
- E2K_RESTRICTION_COMMENT = 10
-} E2kRestrictionType;
-
-struct _E2kRestriction {
- /*< private >*/
-
- E2kRestrictionType type;
- gint ref_count;
-
- union {
- struct {
- guint nrns;
- E2kRestriction **rns;
- } and;
-
- struct {
- guint nrns;
- E2kRestriction **rns;
- } or;
-
- struct {
- E2kRestriction *rn;
- } not;
-
- struct {
- E2kRestrictionFuzzyLevel fuzzy_level;
- E2kPropValue pv;
- } content;
-
- struct {
- E2kRestrictionRelop relop;
- E2kPropValue pv;
- } property;
-
- struct {
- E2kRestrictionRelop relop;
- E2kRuleProp prop1;
- E2kRuleProp prop2;
- } compare;
-
- struct {
- E2kRestrictionBitop bitop;
- E2kRuleProp prop;
- guint32 mask;
- } bitmask;
-
- struct {
- E2kRestrictionRelop relop;
- E2kRuleProp prop;
- guint32 size;
- } size;
-
- struct {
- E2kRuleProp prop;
- } exist;
-
- struct {
- E2kRuleProp subtable;
- E2kRestriction *rn;
- } sub;
-
- struct {
- guint32 nprops;
- E2kRestriction *rn;
- E2kPropValue *props;
- } comment;
- } res;
-};
-
-typedef enum {
- E2K_ACTION_MOVE = 1,
- E2K_ACTION_COPY = 2,
- E2K_ACTION_REPLY = 3,
- E2K_ACTION_OOF_REPLY = 4,
- E2K_ACTION_DEFER = 5,
- E2K_ACTION_BOUNCE = 6,
- E2K_ACTION_FORWARD = 7,
- E2K_ACTION_DELEGATE = 8,
- E2K_ACTION_TAG = 9,
- E2K_ACTION_DELETE = 10,
- E2K_ACTION_MARK_AS_READ = 11
-} E2kActionType;
-
-typedef enum {
- E2K_ACTION_REPLY_FLAVOR_NOT_ORIGINATOR = 1,
- E2K_ACTION_REPLY_FLAVOR_STOCK_TEMPLATE = 2
-} E2kActionReplyFlavor;
-
-typedef enum {
- E2K_ACTION_FORWARD_FLAVOR_PRESERVE_SENDER = 1,
- E2K_ACTION_FORWARD_FLAVOR_DO_NOT_MUNGE = 2,
- E2K_ACTION_FORWARD_FLAVOR_REDIRECT = 3,
- E2K_ACTION_FORWARD_FLAVOR_AS_ATTACHMENT = 4
-} E2kActionForwardFlavor;
-
-typedef enum {
- E2K_ACTION_BOUNCE_CODE_TOO_LARGE = 13,
- E2K_ACTION_BOUNCE_CODE_FORM_MISMATCH = 31,
- E2K_ACTION_BOUNCE_CODE_ACCESS_DENIED = 38
-} E2kActionBounceCode;
-
-struct _E2kAddrEntry {
- /*< private >*/
- guint32 nvalues;
- E2kPropValue *propval;
-};
-
-struct _E2kAddrList {
- /*< private >*/
- guint32 nentries;
- E2kAddrEntry entry[1];
-};
-
-struct _E2kAction {
- /*< private >*/
-
- E2kActionType type;
- guint32 flavor;
- guint32 flags;
-
- union {
- struct {
- GByteArray *store_entryid;
- GByteArray *folder_source_key;
- } xfer;
-
- struct {
- GByteArray *entryid;
- guint8 reply_template_guid[16];
- } reply;
-
- GByteArray *defer_data;
- guint32 bounce_code;
- E2kAddrList *addr_list;
- E2kPropValue proptag;
- } act;
-};
-
-typedef enum {
- E2K_RULE_STATE_DISABLED = 0x00,
- E2K_RULE_STATE_ENABLED = 0x01,
- E2K_RULE_STATE_ERROR = 0x02,
- E2K_RULE_STATE_ONLY_WHEN_OOF = 0x04,
- E2K_RULE_STATE_KEEP_OOF_HISTORY = 0x08,
- E2K_RULE_STATE_EXIT_LEVEL = 0x10,
-
- E2K_RULE_STATE_CLEAR_OOF_HISTORY = 0x80000000
-} E2kRuleState;
-
-typedef struct {
- gchar *name;
- guint32 sequence;
- guint32 state;
- guint32 user_flags;
- guint32 level;
- guint32 condition_lcid;
- E2kRestriction *condition;
- GPtrArray *actions;
- gchar *provider;
- GByteArray *provider_data;
-} E2kRule;
-
-typedef struct {
- guint8 version;
- guint32 codepage;
- GPtrArray *rules;
-} E2kRules;
-
-E2kRules *e2k_rules_from_binary (GByteArray *rules_data);
-GByteArray *e2k_rules_to_binary (E2kRules *rules);
-void e2k_rules_free (E2kRules *rules);
-void e2k_rule_free (E2kRule *rule);
-
-/* Generic rule read/write code */
-
-void e2k_rule_write_uint32 (guint8 *ptr, guint32 val);
-void e2k_rule_append_uint32 (GByteArray *ba, guint32 val);
-guint32 e2k_rule_read_uint32 (guint8 *ptr);
-gboolean e2k_rule_extract_uint32 (guint8 **ptr, gint *len,
- guint32 *val);
-
-void e2k_rule_write_uint16 (guint8 *ptr, guint16 val);
-void e2k_rule_append_uint16 (GByteArray *ba, guint16 val);
-guint16 e2k_rule_read_uint16 (guint8 *ptr);
-gboolean e2k_rule_extract_uint16 (guint8 **ptr, gint *len,
- guint16 *val);
-
-void e2k_rule_append_byte (GByteArray *ba, guint8 val);
-gboolean e2k_rule_extract_byte (guint8 **ptr, gint *len,
- guint8 *val);
-
-void e2k_rule_append_string (GByteArray *ba, const gchar *str);
-gboolean e2k_rule_extract_string (guint8 **ptr, gint *len,
- gchar **str);
-
-void e2k_rule_append_unicode (GByteArray *ba, const gchar *str);
-gboolean e2k_rule_extract_unicode (guint8 **ptr, gint *len,
- gchar **str);
-
-void e2k_rule_append_binary (GByteArray *ba, GByteArray *data);
-gboolean e2k_rule_extract_binary (guint8 **ptr, gint *len,
- GByteArray **data);
-
-void e2k_rule_append_proptag (GByteArray *ba, E2kRuleProp *prop);
-gboolean e2k_rule_extract_proptag (guint8 **ptr, gint *len,
- E2kRuleProp *prop);
-
-void e2k_rule_append_propvalue (GByteArray *ba, E2kPropValue *pv);
-gboolean e2k_rule_extract_propvalue (guint8 **ptr, gint *len,
- E2kPropValue *pv);
-void e2k_rule_free_propvalue (E2kPropValue *pv);
-
-#endif /* __E2K_RULE_H__ */
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-
-/* Copyright (C) 2001-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "e2k-security-descriptor.h"
-#include "e2k-sid.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/xmlmemory.h>
-
-struct _E2kSecurityDescriptorPrivate {
- GByteArray *header;
- guint16 control_flags;
- GArray *aces;
-
- E2kSid *default_sid, *owner, *group;
- GHashTable *sids, *sid_order;
-};
-
-typedef struct {
- guint8 Revision;
- guint8 Sbz1;
- guint16 Control;
- guint32 Owner;
- guint32 Group;
- guint32 Sacl;
- guint32 Dacl;
-} E2k_SECURITY_DESCRIPTOR_RELATIVE;
-
-#define E2K_SECURITY_DESCRIPTOR_REVISION 1
-#define E2K_SE_DACL_PRESENT GUINT16_TO_LE(0x0004)
-#define E2K_SE_SACL_PRESENT GUINT16_TO_LE(0x0010)
-#define E2K_SE_DACL_PROTECTED GUINT16_TO_LE(0x1000)
-
-typedef struct {
- guint8 AclRevision;
- guint8 Sbz1;
- guint16 AclSize;
- guint16 AceCount;
- guint16 Sbz2;
-} E2k_ACL;
-
-#define E2K_ACL_REVISION 2
-
-typedef struct {
- guint8 AceType;
- guint8 AceFlags;
- guint16 AceSize;
-} E2k_ACE_HEADER;
-
-#define E2K_ACCESS_ALLOWED_ACE_TYPE (0x00)
-#define E2K_ACCESS_DENIED_ACE_TYPE (0x01)
-
-#define E2K_OBJECT_INHERIT_ACE (0x01)
-#define E2K_CONTAINER_INHERIT_ACE (0x02)
-#define E2K_INHERIT_ONLY_ACE (0x08)
-
-typedef struct {
- E2k_ACE_HEADER Header;
- guint32 Mask;
- E2kSid *Sid;
-} E2k_ACE;
-
-typedef struct {
- guint32 mapi_permission;
- guint32 container_allowed, container_not_denied;
- guint32 object_allowed, object_not_denied;
-} E2kPermissionsMap;
-
-/* The magic numbers are from the WSS SDK, except modified to match
- * Outlook a bit.
- */
-#define LE(x) (GUINT32_TO_LE (x))
-static E2kPermissionsMap permissions_map[] = {
- { E2K_PERMISSION_READ_ANY,
- LE(0x000000), LE(0x000000), LE(0x1208a9), LE(0x0008a9) },
- { E2K_PERMISSION_CREATE,
- LE(0x000002), LE(0x000002), LE(0x000000), LE(0x000000) },
- { E2K_PERMISSION_CREATE_SUBFOLDER,
- LE(0x000004), LE(0x000004), LE(0x000000), LE(0x000000) },
- { E2K_PERMISSION_EDIT_OWNED,
- LE(0x000000), LE(0x000000), LE(0x000200), LE(0x000000) },
- { E2K_PERMISSION_DELETE_OWNED,
- LE(0x000000), LE(0x000000), LE(0x000400), LE(0x000000) },
- { E2K_PERMISSION_EDIT_ANY,
- LE(0x000000), LE(0x000000), LE(0x0c0116), LE(0x1e0316) },
- { E2K_PERMISSION_DELETE_ANY,
- LE(0x000000), LE(0x000000), LE(0x010000), LE(0x010400) },
- { E2K_PERMISSION_OWNER,
- LE(0x0d4110), LE(0x0d4110), LE(0x000000), LE(0x000000) },
- { E2K_PERMISSION_CONTACT,
- LE(0x008000), LE(0x008000), LE(0x000000), LE(0x000000) },
- { E2K_PERMISSION_FOLDER_VISIBLE,
- LE(0x1208a9), LE(0x1200a9), LE(0x000000), LE(0x000000) }
-};
-static const gint permissions_map_size =
- sizeof (permissions_map) / sizeof (permissions_map[0]);
-
-static const guint32 container_permissions_all = LE(0x1fc9bf);
-static const guint32 object_permissions_all = LE(0x1f0fbf);
-#undef LE
-
-#define PARENT_TYPE G_TYPE_OBJECT
-static GObjectClass *parent_class = NULL;
-
-static void dispose (GObject *object);
-
-static void
-class_init (GObjectClass *object_class)
-{
- parent_class = g_type_class_ref (PARENT_TYPE);
-
- object_class->dispose = dispose;
-}
-
-static void
-init (E2kSecurityDescriptor *sd)
-{
- sd->priv = g_new0 (E2kSecurityDescriptorPrivate, 1);
-
- sd->priv->sids = g_hash_table_new (e2k_sid_binary_sid_hash,
- e2k_sid_binary_sid_equal);
- sd->priv->sid_order = g_hash_table_new (NULL, NULL);
- sd->priv->aces = g_array_new (FALSE, TRUE, sizeof (E2k_ACE));
-}
-
-static void
-free_sid (gpointer key, gpointer sid, gpointer data)
-{
- g_object_unref (sid);
-}
-
-static void
-dispose (GObject *object)
-{
- E2kSecurityDescriptor *sd = (E2kSecurityDescriptor *) object;
-
- if (sd->priv) {
- g_hash_table_foreach (sd->priv->sids, free_sid, NULL);
- g_hash_table_destroy (sd->priv->sids);
- g_hash_table_destroy (sd->priv->sid_order);
-
- g_array_free (sd->priv->aces, TRUE);
-
- if (sd->priv->header)
- g_byte_array_free (sd->priv->header, TRUE);
-
- g_free (sd->priv);
- sd->priv = NULL;
- }
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-E2K_MAKE_TYPE (e2k_security_descriptor, E2kSecurityDescriptor, class_init, init, PARENT_TYPE)
-
-/* This determines the relative ordering of any two ACEs in a SID.
- * See docs/security for details.
- */
-static gint
-ace_compar (E2k_ACE *ace1, E2k_ACE *ace2, E2kSecurityDescriptor *sd)
-{
- E2kSidType t1;
- E2kSidType t2;
- gint order1, order2;
-
- if (ace1 == ace2)
- return 0;
-
- /* Figure out which overall section the SID will go in and
- * what its order within that group is.
- */
- if (ace1->Sid == sd->priv->default_sid)
- t1 = E2K_SID_TYPE_GROUP;
- else
- t1 = e2k_sid_get_sid_type (ace1->Sid);
- order1 = GPOINTER_TO_INT (g_hash_table_lookup (sd->priv->sid_order,
- ace1->Sid));
-
- if (ace2->Sid == sd->priv->default_sid)
- t2 = E2K_SID_TYPE_GROUP;
- else
- t2 = e2k_sid_get_sid_type (ace2->Sid);
- order2 = GPOINTER_TO_INT (g_hash_table_lookup (sd->priv->sid_order,
- ace2->Sid));
-
- if (t1 != t2) {
- if (t1 == E2K_SID_TYPE_USER)
- return -1;
- else if (t2 == E2K_SID_TYPE_USER)
- return 1;
- else if (t1 == E2K_SID_TYPE_GROUP)
- return 1;
- else /* (t2 == E2K_SID_TYPE_GROUP) */
- return -1;
- }
-
- if (t1 != E2K_SID_TYPE_GROUP) {
- /* Object-level ACEs go before Container-level ACEs */
- if ((ace1->Header.AceFlags & E2K_OBJECT_INHERIT_ACE) &&
- !(ace2->Header.AceFlags & E2K_OBJECT_INHERIT_ACE))
- return -1;
- else if ((ace2->Header.AceFlags & E2K_OBJECT_INHERIT_ACE) &&
- !(ace1->Header.AceFlags & E2K_OBJECT_INHERIT_ACE))
- return 1;
-
- /* Compare SID order */
- if (order1 < order2)
- return -1;
- else if (order1 > order2)
- return 1;
-
- /* Allowed ACEs for a given SID go before Denied ACEs */
- if (ace1->Header.AceType == ace2->Header.AceType)
- return 0;
- else if (ace1->Header.AceType == E2K_ACCESS_ALLOWED_ACE_TYPE)
- return -1;
- else
- return 1;
- } else {
- /* For groups, object-level ACEs go after Container-level */
- if ((ace1->Header.AceFlags & E2K_OBJECT_INHERIT_ACE) &&
- !(ace2->Header.AceFlags & E2K_OBJECT_INHERIT_ACE))
- return 1;
- else if ((ace2->Header.AceFlags & E2K_OBJECT_INHERIT_ACE) &&
- !(ace1->Header.AceFlags & E2K_OBJECT_INHERIT_ACE))
- return -1;
-
- /* Default comes after groups in each section */
- if (ace1->Sid != ace2->Sid) {
- if (ace1->Sid == sd->priv->default_sid)
- return 1;
- else if (ace2->Sid == sd->priv->default_sid)
- return -1;
- }
-
- /* All Allowed ACEs go before all Denied ACEs */
- if (ace1->Header.AceType == E2K_ACCESS_ALLOWED_ACE_TYPE &&
- ace2->Header.AceType == E2K_ACCESS_DENIED_ACE_TYPE)
- return -1;
- else if (ace1->Header.AceType == E2K_ACCESS_DENIED_ACE_TYPE &&
- ace2->Header.AceType == E2K_ACCESS_ALLOWED_ACE_TYPE)
- return 1;
-
- /* Compare SID order */
- if (order1 < order2)
- return -1;
- else if (order1 > order2)
- return 1;
- else
- return 0;
- }
-}
-
-static xmlNode *
-find_child (xmlNode *node, const xmlChar *name)
-{
- for (node = node->xmlChildrenNode; node; node = node->next) {
- if (node->name && !xmlStrcmp (node->name, name))
- return node;
- }
- return NULL;
-}
-
-static void
-extract_sids (E2kSecurityDescriptor *sd, xmlNodePtr node)
-{
- xmlNodePtr string_sid_node, type_node, display_name_node;
- xmlChar *string_sid, *content, *display_name;
- const guint8 *bsid;
- E2kSid *sid;
- E2kSidType type;
-
- for (; node; node = node->next) {
- if (xmlStrcmp (node->name, (xmlChar *) "sid") != 0) {
- if (node->xmlChildrenNode)
- extract_sids (sd, node->xmlChildrenNode);
- continue;
- }
-
- string_sid_node = find_child (node, (xmlChar *) "string_sid");
- type_node = find_child (node, (xmlChar *) "type");
- display_name_node = find_child (node, (xmlChar *) "display_name");
- if (!string_sid_node || !type_node)
- continue;
-
- string_sid = xmlNodeGetContent (string_sid_node);
-
- content = xmlNodeGetContent (type_node);
- if (!content || !xmlStrcmp (content, (xmlChar *) "user"))
- type = E2K_SID_TYPE_USER;
- else if (!xmlStrcmp (content, (xmlChar *) "group"))
- type = E2K_SID_TYPE_GROUP;
- else if (!xmlStrcmp (content, (xmlChar *) "well_known_group"))
- type = E2K_SID_TYPE_WELL_KNOWN_GROUP;
- else if (!xmlStrcmp (content, (xmlChar *) "alias"))
- type = E2K_SID_TYPE_ALIAS;
- else
- type = E2K_SID_TYPE_INVALID;
- xmlFree (content);
-
- if (display_name_node)
- display_name = xmlNodeGetContent (display_name_node);
- else
- display_name = NULL;
-
- sid = e2k_sid_new_from_string_sid (type, (gchar *) string_sid,
- (gchar *) display_name);
- xmlFree (string_sid);
- if (display_name)
- xmlFree (display_name);
-
- bsid = e2k_sid_get_binary_sid (sid);
- if (g_hash_table_lookup (sd->priv->sids, bsid)) {
- g_object_unref (sid);
- continue;
- }
-
- g_hash_table_insert (sd->priv->sids, (gchar *)bsid, sid);
- }
-}
-
-static gboolean
-parse_sid (E2kSecurityDescriptor *sd, GByteArray *binsd, guint16 *off,
- E2kSid **sid)
-{
- gint sid_len;
-
- if (binsd->len - *off < E2K_SID_BINARY_SID_MIN_LEN)
- return FALSE;
- sid_len = E2K_SID_BINARY_SID_LEN (binsd->data + *off);
- if (binsd->len - *off < sid_len)
- return FALSE;
-
- *sid = g_hash_table_lookup (sd->priv->sids, binsd->data + *off);
- *off += sid_len;
-
- return *sid != NULL;
-}
-
-static gboolean
-parse_acl (E2kSecurityDescriptor *sd, GByteArray *binsd, guint16 *off)
-{
- E2k_ACL aclbuf;
- E2k_ACE acebuf;
- gint ace_count, i;
-
- if (binsd->len - *off < sizeof (E2k_ACL))
- return FALSE;
-
- memcpy (&aclbuf, binsd->data + *off, sizeof (aclbuf));
- if (*off + GUINT16_FROM_LE (aclbuf.AclSize) > binsd->len)
- return FALSE;
- if (aclbuf.AclRevision != E2K_ACL_REVISION)
- return FALSE;
-
- ace_count = GUINT16_FROM_LE (aclbuf.AceCount);
-
- *off += sizeof (aclbuf);
- for (i = 0; i < ace_count; i++) {
- if (binsd->len - *off < sizeof (E2k_ACE))
- return FALSE;
-
- memcpy (&acebuf, binsd->data + *off,
- sizeof (acebuf.Header) + sizeof (acebuf.Mask));
- *off += sizeof (acebuf.Header) + sizeof (acebuf.Mask);
-
- /* If either of OBJECT_INHERIT_ACE or INHERIT_ONLY_ACE
- * is set, both must be.
- */
- if (acebuf.Header.AceFlags & E2K_OBJECT_INHERIT_ACE) {
- if (!(acebuf.Header.AceFlags & E2K_INHERIT_ONLY_ACE))
- return FALSE;
- } else {
- if (acebuf.Header.AceFlags & E2K_INHERIT_ONLY_ACE)
- return FALSE;
- }
-
- if (!parse_sid (sd, binsd, off, &acebuf.Sid))
- return FALSE;
-
- if (!g_hash_table_lookup (sd->priv->sid_order, acebuf.Sid)) {
- gint size = g_hash_table_size (sd->priv->sid_order);
-
- g_hash_table_insert (sd->priv->sid_order, acebuf.Sid,
- GUINT_TO_POINTER (size + 1));
- }
-
- g_array_append_val (sd->priv->aces, acebuf);
- }
-
- return TRUE;
-}
-
-/**
- * e2k_security_descriptor_new:
- * @xml_form: the XML form of the folder's security descriptor
- * (The "http://schemas.microsoft.com/exchange/security/descriptor"
- * property, aka %E2K_PR_EXCHANGE_SD_XML)
- * @binary_form: the binary form of the folder's security descriptor
- * (The "http://schemas.microsoft.com/exchange/ntsecuritydescriptor"
- * property, aka %E2K_PR_EXCHANGE_SD_BINARY)
- *
- * Constructs an #E2kSecurityDescriptor from the data in @xml_form and
- * @binary_form.
- *
- * Return value: the security descriptor, or %NULL if the data could
- * not be parsed.
- **/
-E2kSecurityDescriptor *
-e2k_security_descriptor_new (xmlNodePtr xml_form, GByteArray *binary_form)
-{
- E2kSecurityDescriptor *sd;
- E2k_SECURITY_DESCRIPTOR_RELATIVE sdbuf;
- guint16 off, header_len;
-
- g_return_val_if_fail (xml_form != NULL, NULL);
- g_return_val_if_fail (binary_form != NULL, NULL);
-
- if (binary_form->len < 2)
- return NULL;
-
- memcpy (&header_len, binary_form->data, 2);
- header_len = GUINT16_FROM_LE (header_len);
- if (header_len + sizeof (sdbuf) > binary_form->len)
- return NULL;
-
- memcpy (&sdbuf, binary_form->data + header_len, sizeof (sdbuf));
- if (sdbuf.Revision != E2K_SECURITY_DESCRIPTOR_REVISION)
- return NULL;
- if ((sdbuf.Control & (E2K_SE_DACL_PRESENT | E2K_SE_SACL_PRESENT)) !=
- E2K_SE_DACL_PRESENT)
- return NULL;
-
- sd = g_object_new (E2K_TYPE_SECURITY_DESCRIPTOR, NULL);
- sd->priv->header = g_byte_array_new ();
- g_byte_array_append (sd->priv->header, binary_form->data, header_len);
- sd->priv->control_flags = sdbuf.Control;
-
- /* Create a SID for "Default" then extract remaining SIDs from
- * the XML form since they have display names associated with
- * them.
- */
- sd->priv->default_sid =
- e2k_sid_new_from_string_sid (E2K_SID_TYPE_WELL_KNOWN_GROUP,
- E2K_SID_WKS_EVERYONE, NULL);
- g_hash_table_insert (sd->priv->sids,
- (gchar *)e2k_sid_get_binary_sid (sd->priv->default_sid),
- sd->priv->default_sid);
- extract_sids (sd, xml_form);
-
- off = GUINT32_FROM_LE (sdbuf.Owner) + sd->priv->header->len;
- if (!parse_sid (sd, binary_form, &off, &sd->priv->owner))
- goto lose;
- off = GUINT32_FROM_LE (sdbuf.Group) + sd->priv->header->len;
- if (!parse_sid (sd, binary_form, &off, &sd->priv->group))
- goto lose;
-
- off = GUINT32_FROM_LE (sdbuf.Dacl) + sd->priv->header->len;
- if (!parse_acl (sd, binary_form, &off))
- goto lose;
-
- return sd;
-
- lose:
- g_object_unref (sd);
- return NULL;
-}
-
-/**
- * e2k_security_descriptor_to_binary:
- * @sd: an #E2kSecurityDescriptor
- *
- * Converts @sd back to binary (#E2K_PR_EXCHANGE_SD_BINARY) form
- * so it can be PROPPATCHed back to the server.
- *
- * Return value: the binary form of @sd.
- **/
-GByteArray *
-e2k_security_descriptor_to_binary (E2kSecurityDescriptor *sd)
-{
- GByteArray *binsd;
- E2k_SECURITY_DESCRIPTOR_RELATIVE sdbuf;
- E2k_ACL aclbuf;
- E2k_ACE *aces;
- gint off, ace, last_ace = -1, acl_size, ace_count;
- const guint8 *bsid;
-
- g_return_val_if_fail (E2K_IS_SECURITY_DESCRIPTOR (sd), NULL);
-
- aces = (E2k_ACE *)sd->priv->aces->data;
-
- /* Compute the length of the ACL first */
- acl_size = sizeof (E2k_ACL);
- for (ace = ace_count = 0; ace < sd->priv->aces->len; ace++) {
- if (aces[ace].Mask) {
- ace_count++;
- acl_size += GUINT16_FROM_LE (aces[ace].Header.AceSize);
- }
- }
-
- binsd = g_byte_array_new ();
-
- /* Exchange-specific header */
- g_byte_array_append (binsd, sd->priv->header->data,
- sd->priv->header->len);
-
- /* SECURITY_DESCRIPTOR header */
- memset (&sdbuf, 0, sizeof (sdbuf));
- sdbuf.Revision = E2K_SECURITY_DESCRIPTOR_REVISION;
- sdbuf.Control = sd->priv->control_flags;
- off = sizeof (sdbuf);
- sdbuf.Dacl = GUINT32_TO_LE (off);
- off += acl_size;
- sdbuf.Owner = GUINT32_TO_LE (off);
- bsid = e2k_sid_get_binary_sid (sd->priv->owner);
- off += E2K_SID_BINARY_SID_LEN (bsid);
- sdbuf.Group = GUINT32_TO_LE (off);
- g_byte_array_append (binsd, (gpointer)&sdbuf, sizeof (sdbuf));
-
- /* ACL header */
- aclbuf.AclRevision = E2K_ACL_REVISION;
- aclbuf.Sbz1 = 0;
- aclbuf.AclSize = GUINT16_TO_LE (acl_size);
- aclbuf.AceCount = GUINT16_TO_LE (ace_count);
- aclbuf.Sbz2 = 0;
- g_byte_array_append (binsd, (gpointer)&aclbuf, sizeof (aclbuf));
-
- /* ACEs */
- for (ace = 0; ace < sd->priv->aces->len; ace++) {
- if (!aces[ace].Mask)
- continue;
-
- if (last_ace != -1) {
- if (ace_compar (&aces[last_ace], &aces[ace], sd) != -1) {
- g_warning ("ACE order mismatch at %d\n", ace);
- g_byte_array_free (binsd, TRUE);
- return NULL;
- }
- }
-
- g_byte_array_append (binsd, (gpointer)&aces[ace],
- sizeof (aces[ace].Header) +
- sizeof (aces[ace].Mask));
- bsid = e2k_sid_get_binary_sid (aces[ace].Sid);
- g_byte_array_append (binsd, bsid,
- E2K_SID_BINARY_SID_LEN (bsid));
- last_ace = ace;
- }
-
- /* Owner and Group */
- bsid = e2k_sid_get_binary_sid (sd->priv->owner);
- g_byte_array_append (binsd, bsid, E2K_SID_BINARY_SID_LEN (bsid));
- bsid = e2k_sid_get_binary_sid (sd->priv->group);
- g_byte_array_append (binsd, bsid, E2K_SID_BINARY_SID_LEN (bsid));
-
- return binsd;
-}
-
-/**
- * e2k_security_descriptor_get_default:
- * @sd: a security descriptor
- *
- * Returns an #E2kSid corresponding to the default permissions
- * associated with @sd. You can pass this to
- * e2k_security_descriptor_get_permissions() and
- * e2k_security_descriptor_set_permissions().
- *
- * Return value: the "Default" SID
- **/
-E2kSid *
-e2k_security_descriptor_get_default (E2kSecurityDescriptor *sd)
-{
- return sd->priv->default_sid;
-}
-
-/**
- * e2k_security_descriptor_get_sids:
- * @sd: a security descriptor
- *
- * Returns a #GList containing the SIDs of each user or group
- * represented in @sd. You can pass these SIDs to
- * e2k_security_descriptor_get_permissions(),
- * e2k_security_descriptor_set_permissions(), and
- * e2k_security_descriptor_remove_sid().
- *
- * Return value: a list of SIDs. The caller must free the list
- * with g_list_free(), but should not free the contents.
- **/
-GList *
-e2k_security_descriptor_get_sids (E2kSecurityDescriptor *sd)
-{
- GList *sids = NULL;
- GHashTable *added_sids;
- E2k_ACE *aces;
- gint ace;
-
- g_return_val_if_fail (E2K_IS_SECURITY_DESCRIPTOR (sd), NULL);
-
- added_sids = g_hash_table_new (NULL, NULL);
- aces = (E2k_ACE *)sd->priv->aces->data;
- for (ace = 0; ace < sd->priv->aces->len; ace++) {
- if (!g_hash_table_lookup (added_sids, aces[ace].Sid)) {
- g_hash_table_insert (added_sids, aces[ace].Sid,
- aces[ace].Sid);
- sids = g_list_prepend (sids, aces[ace].Sid);
- }
- }
- g_hash_table_destroy (added_sids);
-
- return sids;
-}
-
-/**
- * e2k_security_descriptor_remove_sid:
- * @sd: a security descriptor
- * @sid: a SID
- *
- * Removes @sid from @sd. If @sid is a user, this means s/he will now
- * have only the default permissions on @sd (unless s/he is a member
- * of a group that is also present in @sd.)
- **/
-void
-e2k_security_descriptor_remove_sid (E2kSecurityDescriptor *sd,
- E2kSid *sid)
-{
- E2k_ACE *aces;
- gint ace;
-
- g_return_if_fail (E2K_IS_SECURITY_DESCRIPTOR (sd));
- g_return_if_fail (E2K_IS_SID (sid));
-
- /* Canonicalize the SID */
- sid = g_hash_table_lookup (sd->priv->sids,
- e2k_sid_get_binary_sid (sid));
- if (!sid)
- return;
-
- /* We can't actually remove all trace of the user, because if
- * he is removed and then re-added without saving in between,
- * then we need to keep the original AceFlags. So we just
- * clear out all of the masks, which (assuming the user is
- * not re-added) will result in him not being written out
- * when sd is saved.
- */
-
- aces = (E2k_ACE *)sd->priv->aces->data;
- for (ace = 0; ace < sd->priv->aces->len; ace++) {
- if (aces[ace].Sid == sid)
- aces[ace].Mask = 0;
- }
-}
-
-/**
- * e2k_security_descriptor_get_permissions:
- * @sd: a security descriptor
- * @sid: a SID
- *
- * Computes the MAPI permissions associated with @sid. (Only the
- * permissions *directly* associated with @sid, not any acquired via
- * group memberships or the Default SID.)
- *
- * Return value: the MAPI permissions
- **/
-guint32
-e2k_security_descriptor_get_permissions (E2kSecurityDescriptor *sd,
- E2kSid *sid)
-{
- E2k_ACE *aces;
- guint32 mapi_perms, checkperm;
- gint ace, map;
-
- g_return_val_if_fail (E2K_IS_SECURITY_DESCRIPTOR (sd), 0);
- g_return_val_if_fail (E2K_IS_SID (sid), 0);
-
- /* Canonicalize the SID */
- sid = g_hash_table_lookup (sd->priv->sids,
- e2k_sid_get_binary_sid (sid));
- if (!sid)
- return 0;
-
- mapi_perms = 0;
- aces = (E2k_ACE *)sd->priv->aces->data;
- for (ace = 0; ace < sd->priv->aces->len; ace++) {
- if (aces[ace].Sid != sid)
- continue;
- if (aces[ace].Header.AceType == E2K_ACCESS_DENIED_ACE_TYPE)
- continue;
-
- for (map = 0; map < permissions_map_size; map++) {
- if (aces[ace].Header.AceFlags & E2K_OBJECT_INHERIT_ACE)
- checkperm = permissions_map[map].object_allowed;
- else
- checkperm = permissions_map[map].container_allowed;
- if (!checkperm)
- continue;
-
- if ((aces[ace].Mask & checkperm) == checkperm)
- mapi_perms |= permissions_map[map].mapi_permission;
- }
- }
-
- return mapi_perms;
-}
-
-/* Put @ace into @sd. If no ACE corresponding to @ace currently exists,
- * it will be added in the right place. If it does already exist, its
- * flags (in particular INHERITED_ACE) will be preserved and only the
- * mask will be changed.
- */
-static void
-set_ace (E2kSecurityDescriptor *sd, E2k_ACE *ace)
-{
- E2k_ACE *aces = (E2k_ACE *)sd->priv->aces->data;
- gint low, mid = 0, high, cmp = -1;
-
- low = 0;
- high = sd->priv->aces->len - 1;
- while (low <= high) {
- mid = (low + high) / 2;
- cmp = ace_compar (ace, &aces[mid], sd);
- if (cmp == 0) {
- if (ace->Mask)
- aces[mid].Mask = ace->Mask;
- else
- g_array_remove_index (sd->priv->aces, mid);
- return;
- } else if (cmp < 0)
- high = mid - 1;
- else
- low = mid + 1;
- }
-
- if (ace->Mask)
- g_array_insert_vals (sd->priv->aces, cmp < 0 ? mid : mid + 1, ace, 1);
-}
-
-/**
- * e2k_security_descriptor_set_permissions:
- * @sd: a security descriptor
- * @sid: a SID
- * @perms: the MAPI permissions
- *
- * Updates or sets @sid's permissions on @sd.
- **/
-void
-e2k_security_descriptor_set_permissions (E2kSecurityDescriptor *sd,
- E2kSid *sid, guint32 perms)
-{
- E2k_ACE ace;
- guint32 object_allowed, object_denied;
- guint32 container_allowed, container_denied;
- const guint8 *bsid;
- E2kSid *sid2;
- gint map;
-
- g_return_if_fail (E2K_IS_SECURITY_DESCRIPTOR (sd));
- g_return_if_fail (E2K_IS_SID (sid));
-
- bsid = e2k_sid_get_binary_sid (sid);
- sid2 = g_hash_table_lookup (sd->priv->sids, bsid);
- if (!sid2) {
- gint size = g_hash_table_size (sd->priv->sid_order);
-
- g_hash_table_insert (sd->priv->sids, (gchar *)bsid, sid);
- g_object_ref (sid);
-
- g_hash_table_insert (sd->priv->sid_order, sid,
- GUINT_TO_POINTER (size + 1));
- } else
- sid = sid2;
-
- object_allowed = 0;
- object_denied = object_permissions_all;
- container_allowed = 0;
- container_denied = container_permissions_all;
-
- for (map = 0; map < permissions_map_size; map++) {
- if (!(permissions_map[map].mapi_permission & perms))
- continue;
-
- object_allowed |= permissions_map[map].object_allowed;
- object_denied &= ~permissions_map[map].object_not_denied;
- container_allowed |= permissions_map[map].container_allowed;
- container_denied &= ~permissions_map[map].container_not_denied;
- }
-
- ace.Sid = sid;
- ace.Header.AceSize = GUINT16_TO_LE (sizeof (ace.Header) +
- sizeof (ace.Mask) +
- E2K_SID_BINARY_SID_LEN (bsid));
-
- ace.Header.AceType = E2K_ACCESS_ALLOWED_ACE_TYPE;
- ace.Header.AceFlags = E2K_OBJECT_INHERIT_ACE | E2K_INHERIT_ONLY_ACE;
- ace.Mask = object_allowed;
- set_ace (sd, &ace);
- if (sid != sd->priv->default_sid) {
- ace.Header.AceType = E2K_ACCESS_DENIED_ACE_TYPE;
- ace.Header.AceFlags = E2K_OBJECT_INHERIT_ACE | E2K_INHERIT_ONLY_ACE;
- ace.Mask = object_denied;
- set_ace (sd, &ace);
- }
-
- ace.Header.AceType = E2K_ACCESS_ALLOWED_ACE_TYPE;
- ace.Header.AceFlags = E2K_CONTAINER_INHERIT_ACE;
- ace.Mask = container_allowed;
- set_ace (sd, &ace);
- if (sid != sd->priv->default_sid) {
- ace.Header.AceType = E2K_ACCESS_DENIED_ACE_TYPE;
- ace.Header.AceFlags = E2K_CONTAINER_INHERIT_ACE;
- ace.Mask = container_denied;
- set_ace (sd, &ace);
- }
-}
-
-static struct {
- const gchar *name;
- guint32 perms;
-} roles[E2K_PERMISSIONS_ROLE_NUM_ROLES] = {
- /* i18n: These are Outlook's words for the default roles in
- the folder permissions dialog. */
- { N_("Owner"), (E2K_PERMISSION_FOLDER_VISIBLE |
- E2K_PERMISSION_READ_ANY |
- E2K_PERMISSION_CREATE |
- E2K_PERMISSION_DELETE_OWNED |
- E2K_PERMISSION_EDIT_OWNED |
- E2K_PERMISSION_DELETE_ANY |
- E2K_PERMISSION_EDIT_ANY |
- E2K_PERMISSION_CREATE_SUBFOLDER |
- E2K_PERMISSION_CONTACT |
- E2K_PERMISSION_OWNER) },
- { N_("Publishing Editor"), (E2K_PERMISSION_FOLDER_VISIBLE |
- E2K_PERMISSION_READ_ANY |
- E2K_PERMISSION_CREATE |
- E2K_PERMISSION_DELETE_OWNED |
- E2K_PERMISSION_EDIT_OWNED |
- E2K_PERMISSION_DELETE_ANY |
- E2K_PERMISSION_EDIT_ANY |
- E2K_PERMISSION_CREATE_SUBFOLDER) },
- { N_("Editor"), (E2K_PERMISSION_FOLDER_VISIBLE |
- E2K_PERMISSION_READ_ANY |
- E2K_PERMISSION_CREATE |
- E2K_PERMISSION_DELETE_OWNED |
- E2K_PERMISSION_EDIT_OWNED |
- E2K_PERMISSION_DELETE_ANY |
- E2K_PERMISSION_EDIT_ANY) },
- { N_("Publishing Author"), (E2K_PERMISSION_FOLDER_VISIBLE |
- E2K_PERMISSION_READ_ANY |
- E2K_PERMISSION_CREATE |
- E2K_PERMISSION_DELETE_OWNED |
- E2K_PERMISSION_EDIT_OWNED |
- E2K_PERMISSION_CREATE_SUBFOLDER) },
- { N_("Author"), (E2K_PERMISSION_FOLDER_VISIBLE |
- E2K_PERMISSION_READ_ANY |
- E2K_PERMISSION_CREATE |
- E2K_PERMISSION_DELETE_OWNED |
- E2K_PERMISSION_EDIT_OWNED) },
- { N_("Non-editing Author"),(E2K_PERMISSION_FOLDER_VISIBLE |
- E2K_PERMISSION_READ_ANY |
- E2K_PERMISSION_CREATE |
- E2K_PERMISSION_DELETE_OWNED) },
- { N_("Reviewer"), (E2K_PERMISSION_FOLDER_VISIBLE |
- E2K_PERMISSION_READ_ANY) },
- { N_("Contributor"), (E2K_PERMISSION_FOLDER_VISIBLE |
- E2K_PERMISSION_CREATE) },
- { N_("None"), (E2K_PERMISSION_FOLDER_VISIBLE) }
-};
-
-/**
- * e2k_permissions_role_get_name:
- * @role: a permissions role
- *
- * Returns the localized name corresponding to @role
- *
- * Return value: the name
- **/
-const gchar *
-e2k_permissions_role_get_name (E2kPermissionsRole role)
-{
- if (role == E2K_PERMISSIONS_ROLE_CUSTOM)
- return _("Custom");
-
- g_return_val_if_fail (role > E2K_PERMISSIONS_ROLE_CUSTOM &&
- role < E2K_PERMISSIONS_ROLE_NUM_ROLES, NULL);
- return _(roles[role].name);
-}
-
-/**
- * e2k_permissions_role_get_perms
- * @role: a permissions role
- *
- * Returns the MAPI permissions associated with @role. @role may not
- * be %E2K_PERMISSIONS_ROLE_CUSTOM.
- *
- * Return value: the MAPI permissions
- **/
-guint32
-e2k_permissions_role_get_perms (E2kPermissionsRole role)
-{
- g_return_val_if_fail (role >= E2K_PERMISSIONS_ROLE_CUSTOM &&
- role < E2K_PERMISSIONS_ROLE_NUM_ROLES, 0);
- return roles[role].perms;
-}
-
-/**
- * e2k_permissions_role_find:
- * @perms: MAPI permissions
- *
- * Finds the #E2kPermissionsRole value associated with @perms. If
- * @perms don't describe any standard role, the return value will be
- * %E2K_PERMISSIONS_ROLE_CUSTOM
- *
- * Return value: the role
- **/
-E2kPermissionsRole
-e2k_permissions_role_find (guint perms)
-{
- gint role;
-
- /* "Folder contact" isn't actually a permission, and is ignored
- * for purposes of roles.
- */
- perms &= ~E2K_PERMISSION_CONTACT;
-
- /* The standard "None" permission includes "Folder visible",
- * but 0 counts as "None" too.
- */
- if (perms == 0)
- return E2K_PERMISSIONS_ROLE_NONE;
-
- for (role = 0; role < E2K_PERMISSIONS_ROLE_NUM_ROLES; role++) {
- if ((roles[role].perms & ~E2K_PERMISSION_CONTACT) == perms)
- return role;
- }
-
- return E2K_PERMISSIONS_ROLE_CUSTOM;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __E2K_SECURITY_DESCRIPTOR_H__
-#define __E2K_SECURITY_DESCRIPTOR_H__
-
-#include "e2k-types.h"
-#include <glib-object.h>
-#include <libxml/tree.h>
-
-#define E2K_TYPE_SECURITY_DESCRIPTOR (e2k_security_descriptor_get_type ())
-#define E2K_SECURITY_DESCRIPTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E2K_TYPE_SECURITY_DESCRIPTOR, E2kSecurityDescriptor))
-#define E2K_SECURITY_DESCRIPTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E2K_TYPE_SECURITY_DESCRIPTOR, E2kSecurityDescriptorClass))
-#define E2K_IS_SECURITY_DESCRIPTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E2K_TYPE_SECURITY_DESCRIPTOR))
-#define E2K_IS_SECURITY_DESCRIPTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E2K_TYPE_SECURITY_DESCRIPTOR))
-
-struct _E2kSecurityDescriptor {
- GObject parent;
-
- E2kSecurityDescriptorPrivate *priv;
-};
-
-struct _E2kSecurityDescriptorClass {
- GObjectClass parent_class;
-};
-
-GType e2k_security_descriptor_get_type (void);
-
-E2kSecurityDescriptor *e2k_security_descriptor_new (xmlNodePtr xml_form,
- GByteArray *binary_form);
-GByteArray *e2k_security_descriptor_to_binary (E2kSecurityDescriptor *sd);
-
-GList *e2k_security_descriptor_get_sids (E2kSecurityDescriptor *sd);
-E2kSid *e2k_security_descriptor_get_default (E2kSecurityDescriptor *sd);
-void e2k_security_descriptor_remove_sid (E2kSecurityDescriptor *sd,
- E2kSid *sid);
-
-/* MAPI folder permissions */
-#define E2K_PERMISSION_READ_ANY 0x001
-#define E2K_PERMISSION_CREATE 0x002
-#define E2K_PERMISSION_EDIT_OWNED 0x008
-#define E2K_PERMISSION_DELETE_OWNED 0x010
-#define E2K_PERMISSION_EDIT_ANY 0x020
-#define E2K_PERMISSION_DELETE_ANY 0x040
-#define E2K_PERMISSION_CREATE_SUBFOLDER 0x080
-#define E2K_PERMISSION_OWNER 0x100
-#define E2K_PERMISSION_CONTACT 0x200
-#define E2K_PERMISSION_FOLDER_VISIBLE 0x400
-
-#define E2K_PERMISSION_EDIT_MASK (E2K_PERMISSION_EDIT_ANY | E2K_PERMISSION_EDIT_OWNED)
-#define E2K_PERMISSION_DELETE_MASK (E2K_PERMISSION_DELETE_ANY | E2K_PERMISSION_DELETE_OWNED)
-
-guint32 e2k_security_descriptor_get_permissions (E2kSecurityDescriptor *sd,
- E2kSid *sid);
-void e2k_security_descriptor_set_permissions (E2kSecurityDescriptor *sd,
- E2kSid *sid,
- guint32 perms);
-
-/* Outlook-defined roles */
-typedef enum {
- E2K_PERMISSIONS_ROLE_OWNER,
- E2K_PERMISSIONS_ROLE_PUBLISHING_EDITOR,
- E2K_PERMISSIONS_ROLE_EDITOR,
- E2K_PERMISSIONS_ROLE_PUBLISHING_AUTHOR,
- E2K_PERMISSIONS_ROLE_AUTHOR,
- E2K_PERMISSIONS_ROLE_NON_EDITING_AUTHOR,
- E2K_PERMISSIONS_ROLE_REVIEWER,
- E2K_PERMISSIONS_ROLE_CONTRIBUTOR,
- E2K_PERMISSIONS_ROLE_NONE,
-
- E2K_PERMISSIONS_ROLE_NUM_ROLES,
- E2K_PERMISSIONS_ROLE_CUSTOM = -1
-} E2kPermissionsRole;
-
-const gchar *e2k_permissions_role_get_name (E2kPermissionsRole role);
-guint32 e2k_permissions_role_get_perms (E2kPermissionsRole role);
-
-E2kPermissionsRole e2k_permissions_role_find (guint perms);
-
-#endif
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-
-/* Copyright (C) 2002-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "e2k-sid.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-#include <libxml/xmlmemory.h>
-
-typedef struct {
- guint8 Revision;
- guint8 SubAuthorityCount;
- guint8 zero_pad[5];
- guint8 IdentifierAuthority;
- guint32 SubAuthority[1];
-} E2kSid_SID;
-#define E2K_SID_SID_REVISION 1
-
-struct _E2kSidPrivate {
- E2kSidType type;
- E2kSid_SID *binary_sid;
- gchar *string_sid;
- gchar *display_name;
-};
-
-#define PARENT_TYPE G_TYPE_OBJECT
-static GObjectClass *parent_class = NULL;
-
-static void dispose (GObject *object);
-
-static void
-class_init (GObjectClass *object_class)
-{
- parent_class = g_type_class_ref (PARENT_TYPE);
-
- object_class->dispose = dispose;
-}
-
-static void
-init (GObject *object)
-{
- E2kSid *sid = E2K_SID (object);
-
- sid->priv = g_new0 (E2kSidPrivate, 1);
-}
-
-static void
-dispose (GObject *object)
-{
- E2kSid *sid = E2K_SID (object);
-
- if (sid->priv) {
- if (sid->priv->string_sid)
- g_free (sid->priv->string_sid);
- if (sid->priv->binary_sid)
- g_free (sid->priv->binary_sid);
- g_free (sid->priv->display_name);
-
- g_free (sid->priv);
- sid->priv = NULL;
- }
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-E2K_MAKE_TYPE (e2k_sid, E2kSid, class_init, init, PARENT_TYPE)
-
-static E2kSid *
-sid_new_internal (E2kSidType type, const gchar *display_name,
- const gchar *string_sid, const guint8 *binary_sid)
-{
- E2kSid *sid;
-
- sid = g_object_new (E2K_TYPE_SID, NULL);
- sid->priv->type = type;
-
- if (binary_sid)
- sid->priv->binary_sid = g_memdup (binary_sid, E2K_SID_BINARY_SID_LEN (binary_sid));
- if (string_sid)
- sid->priv->string_sid = g_strdup (string_sid);
- else if (!display_name)
- e2k_sid_get_string_sid (sid);
-
- if (!display_name) {
- if (type == E2K_SID_TYPE_WELL_KNOWN_GROUP) {
- if (!strcmp (string_sid, E2K_SID_WKS_ANONYMOUS))
- display_name = _(E2K_SID_WKS_ANONYMOUS_NAME);
- else if (!strcmp (string_sid, E2K_SID_WKS_EVERYONE))
- display_name = _(E2K_SID_WKS_EVERYONE_NAME);
- }
- if (!display_name)
- display_name = string_sid;
- }
- sid->priv->display_name = g_strdup (display_name);
-
- return sid;
-}
-
-/**
- * e2k_sid_new_from_string_sid:
- * @type: the type of SID that @string_sid is
- * @string_sid: the string form of a Windows Security Identifier
- * @display_name: UTF-8 display name of the user/group/etc identified
- * by @string_sid
- *
- * Creates an %E2kSid from the given information
- *
- * Return value: the new SID
- **/
-E2kSid *
-e2k_sid_new_from_string_sid (E2kSidType type, const gchar *string_sid,
- const gchar *display_name)
-{
- g_return_val_if_fail (string_sid != NULL, NULL);
-
- if (strlen (string_sid) < 6 || strncmp (string_sid, "S-1-", 4) != 0)
- return NULL;
-
- return sid_new_internal (type, display_name, string_sid, NULL);
-}
-
-/**
- * e2k_sid_new_from_binary_sid:
- * @type: the type of SID that @binary_sid is
- * @binary_sid: the binary form of a Windows Security Identifier
- * @display_name: UTF-8 display name of the user/group/etc identified
- * by @string_sid
- *
- * Creates an %E2kSid from the given information
- *
- * Return value: the new SID
- **/
-E2kSid *
-e2k_sid_new_from_binary_sid (E2kSidType type,
- const guint8 *binary_sid,
- const gchar *display_name)
-{
- g_return_val_if_fail (binary_sid != NULL, NULL);
-
- return sid_new_internal (type, display_name, NULL, binary_sid);
-}
-
-/**
- * e2k_sid_get_sid_type:
- * @sid: a SID
- *
- * Returns the type of @sid (user, group, etc)
- *
- * Return value: the %E2kSidType
- **/
-E2kSidType
-e2k_sid_get_sid_type (E2kSid *sid)
-{
- g_return_val_if_fail (E2K_IS_SID (sid), E2K_SID_TYPE_USER);
-
- return sid->priv->type;
-}
-
-/**
- * e2k_sid_get_string_sid:
- * @sid: a SID
- *
- * Returns the string form of @sid
- *
- * Return value: the string SID
- **/
-const gchar *
-e2k_sid_get_string_sid (E2kSid *sid)
-{
- g_return_val_if_fail (E2K_IS_SID (sid), NULL);
-
- if (!sid->priv->string_sid) {
- GString *string;
- gint sa;
-
- string = g_string_new (NULL);
-
- /* Revision and IdentifierAuthority. */
- g_string_append_printf (string, "S-%u-%u",
- sid->priv->binary_sid->Revision,
- sid->priv->binary_sid->IdentifierAuthority);
-
- /* Subauthorities. */
- for (sa = 0; sa < sid->priv->binary_sid->SubAuthorityCount; sa++) {
- g_string_append_printf (string, "-%lu",
- (gulong) GUINT32_FROM_LE (sid->priv->binary_sid->SubAuthority[sa]));
- }
-
- sid->priv->string_sid = string->str;
- g_string_free (string, FALSE);
- }
-
- return sid->priv->string_sid;
-}
-
-/**
- * e2k_sid_get_binary_sid:
- * @sid: a SID
- *
- * Returns the binary form of @sid. Since the SID data is self-delimiting,
- * no length value is needed. Use E2K_SID_BINARY_SID_LEN() if you need to
- * know the size of the binary data.
- *
- * Return value: the binary SID
- **/
-const guint8 *
-e2k_sid_get_binary_sid (E2kSid *sid)
-{
- g_return_val_if_fail (E2K_IS_SID (sid), NULL);
-
- if (!sid->priv->binary_sid) {
- gint sa, subauth_count;
- guint32 subauthority;
- gchar *p;
-
- p = sid->priv->string_sid + 4;
- subauth_count = 0;
- while ((p = strchr (p, '-'))) {
- subauth_count++;
- p++;
- }
-
- sid->priv->binary_sid = g_malloc0 (sizeof (E2kSid_SID) + 4 * (subauth_count - 1));
- sid->priv->binary_sid->Revision = E2K_SID_SID_REVISION;
- sid->priv->binary_sid->IdentifierAuthority = strtoul (sid->priv->string_sid + 4, &p, 10);
- sid->priv->binary_sid->SubAuthorityCount = subauth_count;
-
- sa = 0;
- while (*p == '-' && sa < subauth_count) {
- subauthority = strtoul (p + 1, &p, 10);
- sid->priv->binary_sid->SubAuthority[sa++] =
- GUINT32_TO_LE (subauthority);
- }
- }
-
- return (guint8 *)sid->priv->binary_sid;
-}
-
-/**
- * e2k_sid_get_display_name:
- * @sid: a SID
- *
- * Returns the display name of the entity identified by @sid
- *
- * Return value: the UTF-8 display name
- **/
-const gchar *
-e2k_sid_get_display_name (E2kSid *sid)
-{
- g_return_val_if_fail (E2K_IS_SID (sid), NULL);
-
- return sid->priv->display_name;
-}
-
-/**
- * e2k_sid_binary_sid_equal:
- * @a: pointer to a binary SID
- * @b: pointer to another binary SID
- *
- * Determines if @a and @b contain the same SID data. For use
- * with #GHashTable.
- *
- * Return value: %TRUE or %FALSE
- **/
-gint
-e2k_sid_binary_sid_equal (gconstpointer a, gconstpointer b)
-{
- const guint8 *bsida = (const guint8 *)a;
- const guint8 *bsidb = (const guint8 *)b;
-
- if (E2K_SID_BINARY_SID_LEN (bsida) !=
- E2K_SID_BINARY_SID_LEN (bsidb))
- return FALSE;
- return memcmp (bsida, bsidb, E2K_SID_BINARY_SID_LEN (bsida)) == 0;
-}
-
-/**
- * e2k_sid_binary_sid_hash:
- * @key: pointer to a binary SID
- *
- * Hashes @key, a binary SID. For use with #GHashTable.
- *
- * Return value: the hash value
- **/
-guint
-e2k_sid_binary_sid_hash (gconstpointer key)
-{
- const guint8 *bsid = (const guint8 *)key;
- guint32 final_sa;
-
- /* The majority of SIDs will differ only in the last
- * subauthority value.
- */
- memcpy (&final_sa, bsid + E2K_SID_BINARY_SID_LEN (bsid) - 4, 4);
- return final_sa;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2002-2004 Novell, Inc. */
-
-#ifndef __E2K_SID_H__
-#define __E2K_SID_H__
-
-#include "e2k-types.h"
-
-#include <glib-object.h>
-#include <libxml/tree.h>
-
-#define E2K_TYPE_SID (e2k_sid_get_type ())
-#define E2K_SID(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E2K_TYPE_SID, E2kSid))
-#define E2K_SID_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E2K_TYPE_SID, E2kSidClass))
-#define E2K_IS_SID(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E2K_TYPE_SID))
-#define E2K_IS_SID_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E2K_TYPE_SID))
-
-typedef enum {
- E2K_SID_TYPE_INVALID,
- E2K_SID_TYPE_USER,
- E2K_SID_TYPE_ALIAS,
- E2K_SID_TYPE_GROUP,
- E2K_SID_TYPE_WELL_KNOWN_GROUP,
- E2K_SID_TYPE_DOMAIN,
- E2K_SID_TYPE_DELETED_ACCOUNT,
- E2K_SID_TYPE_UNKNOWN,
- E2K_SID_TYPE_COMPUTER
-} E2kSidType;
-
-struct _E2kSid {
- GObject parent;
-
- E2kSidPrivate *priv;
-};
-
-struct _E2kSidClass {
- GObjectClass parent_class;
-
-};
-
-GType e2k_sid_get_type (void);
-
-E2kSid *e2k_sid_new_from_string_sid (E2kSidType type,
- const gchar *string_sid,
- const gchar *display_name);
-E2kSid *e2k_sid_new_from_binary_sid (E2kSidType type,
- const guint8 *binary_sid,
- const gchar *display_name);
-
-E2kSidType e2k_sid_get_sid_type (E2kSid *sid);
-const gchar *e2k_sid_get_string_sid (E2kSid *sid);
-const guint8 *e2k_sid_get_binary_sid (E2kSid *sid);
-const gchar *e2k_sid_get_display_name (E2kSid *sid);
-
-#define E2K_SID_BINARY_SID_MIN_LEN 8
-#define E2K_SID_BINARY_SID_LEN(bsid) (8 + ((guint8 *)bsid)[1] * 4)
-guint e2k_sid_binary_sid_hash (gconstpointer key);
-gint e2k_sid_binary_sid_equal (gconstpointer a,
- gconstpointer b);
-
-/* Some well-known SIDs */
-#define E2K_SID_WKS_EVERYONE "S-1-1-0"
-#define E2K_SID_WKS_EVERYONE_NAME "Default"
-#define E2K_SID_WKS_ANONYMOUS "S-1-5-7"
-#define E2K_SID_WKS_ANONYMOUS_NAME "Anonymous"
-
-#endif
-
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __E2K_TYPES_H__
-#define __E2K_TYPES_H__
-
-#include <glib.h>
-#include <glib/gi18n.h>
-
-typedef struct _E2kAction E2kAction;
-typedef struct _E2kAddrEntry E2kAddrEntry;
-typedef struct _E2kAddrList E2kAddrList;
-
-typedef struct _E2kContext E2kContext;
-typedef struct _E2kContextPrivate E2kContextPrivate;
-typedef struct _E2kContextClass E2kContextClass;
-
-typedef struct _E2kGlobalCatalog E2kGlobalCatalog;
-typedef struct _E2kGlobalCatalogPrivate E2kGlobalCatalogPrivate;
-typedef struct _E2kGlobalCatalogClass E2kGlobalCatalogClass;
-
-typedef struct _E2kOperation E2kOperation;
-
-typedef struct _E2kRestriction E2kRestriction;
-
-typedef struct _E2kSecurityDescriptor E2kSecurityDescriptor;
-typedef struct _E2kSecurityDescriptorPrivate E2kSecurityDescriptorPrivate;
-typedef struct _E2kSecurityDescriptorClass E2kSecurityDescriptorClass;
-
-typedef struct _E2kSid E2kSid;
-typedef struct _E2kSidPrivate E2kSidPrivate;
-typedef struct _E2kSidClass E2kSidClass;
-
-#define E2K_MAKE_TYPE(type_name,TypeName,class_init,init,parent) \
-GType type_name##_get_type(void) \
-{ \
- static GType type = 0; \
- if (!type){ \
- static GTypeInfo const object_info = { \
- sizeof (TypeName##Class), \
- \
- (GBaseInitFunc) NULL, \
- (GBaseFinalizeFunc) NULL, \
- \
- (GClassInitFunc) class_init, \
- (GClassFinalizeFunc) NULL, \
- NULL, /* class_data */ \
- \
- sizeof (TypeName), \
- 0, /* n_preallocs */ \
- (GInstanceInitFunc) init, \
- }; \
- type = g_type_register_static (parent, #TypeName, &object_info, 0); \
- } \
- return type; \
-}
-
-#define E2K_MAKE_TYPE_WITH_IFACE(type_name,TypeName,class_init,init,parent,iface_init,iparent) \
-GType type_name##_get_type(void) \
-{ \
- static GType type = 0; \
- if (!type){ \
- static GTypeInfo const object_info = { \
- sizeof (TypeName##Class), \
- \
- (GBaseInitFunc) NULL, \
- (GBaseFinalizeFunc) NULL, \
- \
- (GClassInitFunc) class_init, \
- (GClassFinalizeFunc) NULL, \
- NULL, /* class_data */ \
- \
- sizeof (TypeName), \
- 0, /* n_preallocs */ \
- (GInstanceInitFunc) init, \
- }; \
- static GInterfaceInfo const iface_info = { \
- (GInterfaceInitFunc) iface_init, \
- NULL, \
- NULL \
- }; \
- type = g_type_register_static (parent, #TypeName, &object_info, 0); \
- g_type_add_interface_static (type, iparent, &iface_info); \
- } \
- return type; \
-}
-
-/* Put "E2K_KEEP_PRECEDING_COMMENT_OUT_OF_PO_FILES;" on a line to
- * separate a _() from a comment that doesn't go with it.
- */
-#define E2K_KEEP_PRECEDING_COMMENT_OUT_OF_PO_FILES
-
-#endif
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 1999-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "e2k-uri.h"
-
-/**
- * e2k_uri_new:
- * @uri_string: the URI
- *
- * Parses @uri_string.
- *
- * Return value: a parsed %E2kUri
- **/
-E2kUri *
-e2k_uri_new (const gchar *uri_string)
-{
- E2kUri *uri;
- const gchar *end, *hash, *colon, *semi, *at, *slash;
- const gchar *question, *p;
-
- uri = g_new0 (E2kUri, 1);
-
- /* Find fragment. */
- end = hash = strchr (uri_string, '#');
- if (hash && hash[1]) {
- uri->fragment = g_strdup (hash + 1);
- e2k_uri_decode (uri->fragment);
- } else
- end = uri_string + strlen (uri_string);
-
- /* Find protocol: initial [a-z+.-]* substring until ":" */
- p = uri_string;
- while (p < end && (isalnum ((guchar)*p) ||
- *p == '.' || *p == '+' || *p == '-'))
- p++;
-
- if (p > uri_string && *p == ':') {
- uri->protocol = g_ascii_strdown (uri_string, p - uri_string);
- uri_string = p + 1;
- }
-
- if (!*uri_string)
- return uri;
-
- /* Check for authority */
- if (strncmp (uri_string, "//", 2) == 0) {
- uri_string += 2;
-
- slash = uri_string + strcspn (uri_string, "/#");
- at = strchr (uri_string, '@');
- if (at && at < slash) {
- gchar *backslash;
-
- colon = strchr (uri_string, ':');
- if (colon && colon < at) {
- uri->passwd = g_strndup (colon + 1,
- at - colon - 1);
- e2k_uri_decode (uri->passwd);
- } else {
- uri->passwd = NULL;
- colon = at;
- }
-
- semi = strchr(uri_string, ';');
- if (semi && semi < colon &&
- !g_ascii_strncasecmp (semi, ";auth=", 6)) {
- uri->authmech = g_strndup (semi + 6,
- colon - semi - 6);
- e2k_uri_decode (uri->authmech);
- } else {
- uri->authmech = NULL;
- semi = colon;
- }
-
- uri->user = g_strndup (uri_string, semi - uri_string);
- e2k_uri_decode (uri->user);
- uri_string = at + 1;
-
- backslash = strchr (uri->user, '\\');
- if (!backslash)
- backslash = strchr (uri->user, '/');
- if (backslash) {
- uri->domain = uri->user;
- *backslash = '\0';
- uri->user = g_strdup (backslash + 1);
- }
- } else
- uri->user = uri->passwd = uri->domain = NULL;
-
- /* Find host and port. */
- colon = strchr (uri_string, ':');
- if (colon && colon < slash) {
- uri->host = g_strndup (uri_string, colon - uri_string);
- uri->port = strtoul (colon + 1, NULL, 10);
- } else {
- uri->host = g_strndup (uri_string, slash - uri_string);
- e2k_uri_decode (uri->host);
- uri->port = 0;
- }
-
- uri_string = slash;
- }
-
- /* Find query */
- question = memchr (uri_string, '?', end - uri_string);
- if (question) {
- if (question[1]) {
- uri->query = g_strndup (question + 1,
- end - (question + 1));
- e2k_uri_decode (uri->query);
- }
- end = question;
- }
-
- /* Find parameters */
- semi = memchr (uri_string, ';', end - uri_string);
- if (semi) {
- if (semi[1]) {
- const gchar *cur, *p, *eq;
- gchar *name, *value;
-
- for (cur = semi + 1; cur < end; cur = p + 1) {
- p = memchr (cur, ';', end - cur);
- if (!p)
- p = end;
- eq = memchr (cur, '=', p - cur);
- if (eq) {
- name = g_strndup (cur, eq - cur);
- value = g_strndup (eq + 1, p - (eq + 1));
- e2k_uri_decode (value);
- } else {
- name = g_strndup (cur, p - cur);
- value = g_strdup ("");
- }
- e2k_uri_decode (name);
- g_datalist_set_data_full (&uri->params, name,
- value, g_free);
- g_free (name);
- }
- }
- end = semi;
- }
-
- if (end != uri_string) {
- uri->path = g_strndup (uri_string, end - uri_string);
- e2k_uri_decode (uri->path);
- }
-
- return uri;
-}
-
-/**
- * e2k_uri_free:
- * @uri: an %E2kUri
- *
- * Frees @uri
- **/
-void
-e2k_uri_free (E2kUri *uri)
-{
- if (uri) {
- g_free (uri->protocol);
- g_free (uri->user);
- g_free (uri->domain);
- g_free (uri->authmech);
- g_free (uri->passwd);
- g_free (uri->host);
- g_free (uri->path);
- g_datalist_clear (&uri->params);
- g_free (uri->query);
- g_free (uri->fragment);
-
- g_free (uri);
- }
-}
-
-/**
- * e2k_uri_get_param:
- * @uri: an %E2kUri
- * @name: name of the parameter
- *
- * Fetches a parameter from @uri
- *
- * Return value: the value of @name, or %NULL if it is not set
- **/
-const gchar *
-e2k_uri_get_param (E2kUri *uri, const gchar *name)
-{
- return g_datalist_get_data (&uri->params, name);
-}
-
-#define HEXVAL(c) (isdigit (c) ? (c) - '0' : g_ascii_tolower (c) - 'a' + 10)
-
-/**
- * e2k_uri_decode:
- * @part: a piece of a URI
- *
- * Undoes URI-escaping in @part in-place.
- **/
-void
-e2k_uri_decode (gchar *part)
-{
- guchar *s, *d;
-
- s = d = (guchar *)part;
- while (*s) {
- if (*s == '%') {
- if (isxdigit (s[1]) && isxdigit (s[2])) {
- *d++ = HEXVAL (s[1]) * 16 + HEXVAL (s[2]);
- s += 3;
- } else
- *d++ = *s++;
- } else
- *d++ = *s++;
- }
- *d = '\0';
-}
-
-static const gint uri_encoded_char[] = {
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x00 - 0x0f */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x10 - 0x1f */
- 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, /* ' ' - '/' */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 2, /* '0' - '?' */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* '@' - 'O' */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 1, 0, /* 'P' - '_' */
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* '`' - 'o' */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 1, /* 'p' - 0x7f */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
-};
-
-/**
- * e2k_uri_append_encoded:
- * @str: a %GString containing part of a URI
- * @in: data to append to @str
- * @wss_encode: whether or not to use the special Web Storage System
- * encoding rules
- * @extra_enc_chars: additional characters beyond the normal URI-reserved
- * characters to encode when appending to @str
- *
- * Appends @in to @str, encoding URI-unsafe characters as needed
- * (optionally including some Exchange-specific encodings).
- *
- * When appending a path, you must append each segment separately;
- * e2k_uri_append_encoded() will encode any "/"s passed in.
- **/
-void
-e2k_uri_append_encoded (GString *str, const gchar *in,
- gboolean wss_encode, const gchar *extra_enc_chars)
-{
- const guchar *s = (const guchar *)in;
-
- while (*s) {
- if (extra_enc_chars && strchr (extra_enc_chars, *s))
- goto escape;
- switch (uri_encoded_char[*s]) {
- case 2:
- if (!wss_encode)
- goto escape;
- switch (*s++) {
- case '/':
- g_string_append (str, "_xF8FF_");
- break;
- case '?':
- g_string_append (str, "_x003F_");
- break;
- case '\\':
- g_string_append (str, "_xF8FE_");
- break;
- case '~':
- g_string_append (str, "_x007E_");
- break;
- }
- break;
- case 1:
- escape:
- g_string_append_printf (str, "%%%02x", (gint)*s++);
- break;
- default:
- g_string_append_c (str, *s++);
- break;
- }
- }
-}
-
-/**
- * e2k_uri_encode:
- * @in: data to encode
- * @wss_encode: whether or not to use the special Web Storage System
- * encoding rules
- * @extra_enc_chars: additional characters beyond the normal URI-reserved
- * characters to encode when appending to @str
- *
- * Encodes URI-unsafe characters as in e2k_uri_append_encoded()
- *
- * Return value: the encoded string
- **/
-gchar *
-e2k_uri_encode (const gchar *in, gboolean wss_encode,
- const gchar *extra_enc_chars)
-{
- GString *string;
- gchar *out;
-
- string = g_string_new (NULL);
- e2k_uri_append_encoded (string, in, wss_encode, extra_enc_chars);
- out = string->str;
- g_string_free (string, FALSE);
-
- return out;
-}
-
-/**
- * e2k_uri_path:
- * @uri_string: a well-formed absolute URI
- *
- * Returns the path component of @uri_string, including the initial
- * "/". (The return value is actually a pointer into the passed-in
- * string, meaning this will only really work if the URI has no
- * query/fragment/etc.)
- *
- * Return value: the path component of @uri_string.
- **/
-const gchar *
-e2k_uri_path (const gchar *uri_string)
-{
- const gchar *p;
-
- p = strchr (uri_string, ':');
- if (p++) {
- if (!strncmp (p, "//", 2)) {
- p = strchr (p + 2, '/');
- if (p)
- return p;
- } else if (*p)
- return p;
- }
- return "";
-}
-
-/**
- * e2k_uri_concat:
- * @uri_prefix: an absolute URI
- * @tail: a relative path
- *
- * Constructs a new URI consisting of the concatenation of
- * @uri_prefix and @tail. If @uri_prefix does not end with a "/",
- * one will be inserted between @uri_prefix and @tail.
- *
- * Return value: the new URI
- **/
-gchar *
-e2k_uri_concat (const gchar *uri_prefix, const gchar *tail)
-{
- const gchar *p;
-
- p = strrchr (uri_prefix, '/');
- if (p && !p[1])
- return g_strdup_printf ("%s%s", uri_prefix, tail);
- else
- return g_strdup_printf ("%s/%s", uri_prefix, tail);
-}
-
-/**
- * e2k_uri_relative:
- * @uri_prefix: an absolute URI
- * @uri: another URI, presumably a child of @uri_prefix
- *
- * Returns a URI describing @uri's relation to @uri_prefix; either a
- * relative URI consisting of the subpath of @uri underneath
- * @uri_prefix, or all of @uri if it is not a sub-uri of @uri_prefix.
- *
- * Return value: the relative URI
- **/
-const gchar *
-e2k_uri_relative (const gchar *uri_prefix, const gchar *uri)
-{
- gint prefix_len = strlen (uri_prefix);
-
- if (!strncmp (uri_prefix, uri, prefix_len)) {
- uri += prefix_len;
- while (*uri == '/')
- uri++;
- }
-
- return uri;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef E2K_URI_H
-#define E2K_URI_H
-
-#include <glib.h>
-
-typedef struct {
- gchar *protocol;
- gchar *user;
- gchar *domain;
- gchar *authmech;
- gchar *passwd;
- gchar *host;
- gint port;
- gchar *path;
- GData *params;
- gchar *query;
- gchar *fragment;
-} E2kUri;
-
-E2kUri * e2k_uri_new (const gchar *uri_string);
-void e2k_uri_free (E2kUri *uri);
-const gchar *e2k_uri_get_param (E2kUri *uri, const gchar *name);
-
-void e2k_uri_decode (gchar *part);
-gchar * e2k_uri_encode (const gchar *in,
- gboolean wss_encode,
- const gchar *extra_enc_chars);
-void e2k_uri_append_encoded (GString *str,
- const gchar *in,
- gboolean wss_encode,
- const gchar *extra_enc_chars);
-
-const gchar *e2k_uri_path (const gchar *uri_string);
-
-gchar *e2k_uri_concat (const gchar *uri_prefix, const gchar *tail);
-const gchar *e2k_uri_relative (const gchar *uri_prefix, const gchar *uri);
-
-#endif /* E2K_URI_H */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2001-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "e2k-utils.h"
-#include "e2k-autoconfig.h"
-#include "e2k-propnames.h"
-#include "e2k-rule.h"
-
-#include <libedataserver/e-time-utils.h>
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* Do not internationalize */
-const gchar *e2k_rfc822_months [] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
-/**
- * e2k_parse_timestamp:
- * @timestamp: an ISO8601 timestamp returned by the Exchange server
- *
- * Converts @timestamp to a %time_t value. @timestamp must be in one
- * of the two ISO8601 variants used by Exchange.
- *
- * Note that the timestamps used (in most contexts) by Exchange have
- * millisecond resolution, so converting them to %time_t loses
- * resolution. Since ISO8601 timestamps can be compared using
- * strcmp(), it is often best to keep them as strings.
- *
- * Return value: the %time_t corresponding to @timestamp, or -1 on
- * error.
- **/
-time_t
-e2k_parse_timestamp (const gchar *timestamp)
-{
- struct tm tm;
-
- tm.tm_year = strtoul (timestamp, (gchar **)×tamp, 10) - 1900;
- if (*timestamp++ != '-')
- return -1;
- tm.tm_mon = strtoul (timestamp, (gchar **)×tamp, 10) - 1;
- if (*timestamp++ != '-')
- return -1;
- tm.tm_mday = strtoul (timestamp, (gchar **)×tamp, 10);
- if (*timestamp++ != 'T')
- return -1;
- tm.tm_hour = strtoul (timestamp, (gchar **)×tamp, 10);
- if (*timestamp++ != ':')
- return -1;
- tm.tm_min = strtoul (timestamp, (gchar **)×tamp, 10);
- if (*timestamp++ != ':')
- return -1;
- tm.tm_sec = strtoul (timestamp, (gchar **)×tamp, 10);
- if (*timestamp != '.' && *timestamp != 'Z')
- return -1;
-
- return e_mktime_utc (&tm);
-}
-
-/**
- * e2k_make_timestamp:
- * @when: the %time_t to convert to an ISO8601 timestamp
- *
- * Creates an ISO8601 timestamp (in an format acceptable to Exchange)
- * corresponding to @when.
- *
- * Return value: the timestamp, which the caller must free.
- **/
-gchar *
-e2k_make_timestamp (time_t when)
-{
- struct tm *tm;
-
- tm = gmtime (&when);
- return g_strdup_printf ("%04d-%02d-%02dT%02d:%02d:%02dZ",
- tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
-}
-
-/**
- * e2k_make_timestamp_rfc822:
- * @when: the %time_t to convert to an RFC822 timestamp
- *
- * Creates an RFC822 Date header value corresponding to @when, in the
- * locale timezone.
- *
- * Return value: the timestamp, which the caller must free.
- **/
-gchar *
-e2k_make_timestamp_rfc822 (time_t when)
-{
- struct tm tm;
- gint offset;
-
- e_localtime_with_offset (when, &tm, &offset);
- offset = (offset / 3600) * 100 + (offset / 60) % 60;
-
- return g_strdup_printf ("%02d %s %04d %02d:%02d:%02d %+05d",
- tm.tm_mday, e2k_rfc822_months[tm.tm_mon],
- tm.tm_year + 1900,
- tm.tm_hour, tm.tm_min, tm.tm_sec,
- offset);
-}
-
-/* SYSTIME_OFFSET is the number of minutes between the Windows epoch
- * (1601-01-01T00:00:00Z) and the time_t epoch (1970-01-01T00:00:00Z):
- * 369 years, 89 of which are leap years.
- */
-#define SYSTIME_OFFSET 194074560UL
-
-/**
- * e2k_systime_to_time_t:
- * @systime: a MAPI PT_SYSTIME value (minutes since Windows epoch)
- *
- * Converts the MAPI PT_SYSTIME value @systime to a corresponding
- * %time_t value (assuming it is within the valid range of a %time_t).
- *
- * Return value: a %time_t corresponding to @systime.
- **/
-time_t
-e2k_systime_to_time_t (guint32 systime)
-{
- return (systime - SYSTIME_OFFSET) * 60;
-}
-
-/**
- * e2k_systime_from_time_t:
- * @tt: a %time_t value
- *
- * Converts the %time_t value @tt to a corresponding MAPI PT_SYSTIME
- * value, losing some precision if @tt does not fall on a minute
- * boundary.
- *
- * Return value: the Windows systime value corresponding to @tt
- **/
-guint32
-e2k_systime_from_time_t (time_t tt)
-{
- return (tt / 60) + SYSTIME_OFFSET;
-}
-
-/**
- * e2k_filetime_to_time_t:
- * @filetime: a Windows FILETIME value (100ns intervals since
- * Windows epoch)
- *
- * Converts the Windows FILETIME value @filetime to a corresponding
- * %time_t value (assuming it is within the valid range of a %time_t),
- * truncating to a second boundary.
- *
- * Return value: a %time_t corresponding to @filetime.
- **/
-time_t
-e2k_filetime_to_time_t (guint64 filetime)
-{
- return (time_t)(filetime / 10000000 - SYSTIME_OFFSET * 60);
-}
-
-/**
- * e2k_filetime_from_time_t:
- * @tt: a %time_t value
- *
- * Converts the %time_t value @tt to a corresponding Windows FILETIME
- * value.
- *
- * Return value: the Windows FILETIME value corresponding to @tt
- **/
-guint64
-e2k_filetime_from_time_t (time_t tt)
-{
- return (((guint64)tt) + ((guint64)SYSTIME_OFFSET) * 60) * 10000000;
-}
-
-/**
- * e2k_lf_to_crlf:
- * @in: input text in UNIX ("\n") format
- *
- * Creates a copy of @in with all LFs converted to CRLFs.
- *
- * Return value: the converted text, which the caller must free.
- **/
-gchar *
-e2k_lf_to_crlf (const gchar *in)
-{
- gint len;
- const gchar *s;
- gchar *out, *d;
-
- g_return_val_if_fail (in != NULL, NULL);
-
- len = strlen (in);
- for (s = strchr (in, '\n'); s; s = strchr (s + 1, '\n'))
- len++;
-
- out = g_malloc (len + 1);
- for (s = in, d = out; *s; s++) {
- if (*s == '\n')
- *d++ = '\r';
- *d++ = *s;
- }
- *d = '\0';
-
- return out;
-}
-
-/**
- * e2k_crlf_to_lf:
- * @in: input text in network ("\r\n") format
- *
- * Creates a copy of @in with all CRLFs converted to LFs. (Actually,
- * it just strips CRs, so any raw CRs will be removed.)
- *
- * Return value: the converted text, which the caller must free.
- **/
-gchar *
-e2k_crlf_to_lf (const gchar *in)
-{
- gint len;
- const gchar *s;
- gchar *out;
- GString *str;
-
- g_return_val_if_fail (in != NULL, NULL);
-
- str = g_string_new ("");
-
- len = strlen (in);
- for (s = in; *s; s++) {
- if (*s != '\r')
- str = g_string_append_c (str, *s);
- }
-
- out = str->str;
- g_string_free (str, FALSE);
-
- return out;
-}
-
-/**
- * e2k_strdup_with_trailing_slash:
- * @path: a URI or path
- *
- * Copies @path, appending a "/" to it if and only if it did not
- * already end in "/".
- *
- * Return value: the path, which the caller must free
- **/
-gchar *
-e2k_strdup_with_trailing_slash (const gchar *path)
-{
- gchar *p;
-
- if (!path || !*path)
- return NULL;
-
- p = strrchr (path, '/');
- if (p && !p[1])
- return g_strdup (path);
- else
- return g_strdup_printf ("%s/", path);
-}
-
-/**
- * e2k_entryid_to_dn:
- * @entryid: an Exchange entryid
- *
- * Finds an Exchange 5.5 DN inside a binary entryid property (such as
- * #PR_STORE_ENTRYID or an element of #PR_DELEGATES_ENTRYIDS).
- *
- * Return value: the entryid, which is a pointer into @entryid's data.
- **/
-const gchar *
-e2k_entryid_to_dn (GByteArray *entryid)
-{
- gchar *p;
-
- p = ((gchar *)entryid->data) + entryid->len - 1;
- if (*p == 0) {
- while (*(p - 1) && p > (gchar *)entryid->data)
- p--;
- if (*p == '/')
- return p;
- }
- return NULL;
-}
-
-static void
-append_permanenturl_section (GString *url, guint8 *entryid)
-{
- gint i = 0;
-
- /* First part */
- while (i < 16)
- g_string_append_printf (url, "%02x", entryid[i++]);
-
- /* Replace 0s with a single '-' */
- g_string_append_c (url, '-');
- while (i < 22 && entryid[i] == 0)
- i++;
-
- /* Last part; note that if the first non-0 byte can be
- * expressed in a single hex digit, we do so. (ie, the 0
- * in the 16's place was also accumulated into the
- * preceding '-'.)
- */
- if (i < 22 && entryid[i] < 0x10)
- g_string_append_printf (url, "%01x", entryid[i++]);
- while (i < 22)
- g_string_append_printf (url, "%02x", entryid[i++]);
-}
-
-#define E2K_PERMANENTURL_INFIX "-FlatUrlSpace-"
-#define E2K_PERMANENTURL_INFIX_LEN (sizeof (E2K_PERMANENTURL_INFIX) - 1)
-
-/**
- * e2k_entryid_to_permanenturl:
- * @entryid: an ENTRYID (specifically, a PR_SOURCE_KEY)
- * @base_uri: base URI of the store containing @entryid
- *
- * Creates a permanenturl based on @entryid and @base_uri.
- *
- * Return value: the permanenturl, which the caller must free.
- **/
-gchar *
-e2k_entryid_to_permanenturl (GByteArray *entryid, const gchar *base_uri)
-{
- GString *url;
- gchar *ret;
-
- g_return_val_if_fail (entryid->len == 22 || entryid->len == 44, NULL);
-
- url = g_string_new (base_uri);
- if (url->str[url->len - 1] != '/')
- g_string_append_c (url, '/');
- g_string_append (url, E2K_PERMANENTURL_INFIX);
- g_string_append_c (url, '/');
-
- append_permanenturl_section (url, entryid->data);
- if (entryid->len > 22) {
- g_string_append_c (url, '/');
- append_permanenturl_section (url, entryid->data + 22);
- }
-
- ret = url->str;
- g_string_free (url, FALSE);
- return ret;
-}
-
-#define HEXVAL(c) (isdigit (c) ? (c) - '0' : g_ascii_tolower (c) - 'a' + 10)
-
-static gboolean
-append_entryid_section (GByteArray *entryid, const gchar **permanenturl)
-{
- const gchar *p;
- guint8 buf[44], byte;
- gint endlen;
-
- p = *permanenturl;
- if (strspn (p, "0123456789abcdefABCDEF") != 32)
- return FALSE;
- if (p[32] != '-')
- return FALSE;
- endlen = strspn (p + 33, "0123456789abcdefABCDEF");
- if (endlen > 6)
- return FALSE;
-
- /* Expand to the full form by replacing the "-" with "0"s */
- memcpy (buf, p, 32);
- memset (buf + 32, '0', sizeof (buf) - 32 - endlen);
- memcpy (buf + sizeof (buf) - endlen, p + 33, endlen);
-
- p = (gchar *) buf;
- while (p < (gchar *) buf + sizeof (buf)) {
- byte = (HEXVAL (*p) << 4) + HEXVAL (*(p + 1));
- g_byte_array_append (entryid, &byte, 1);
- p += 2;
- }
-
- *permanenturl += 33 + endlen;
- return TRUE;
-}
-
-/**
- * e2k_permanenturl_to_entryid:
- * @permanenturl: an Exchange permanenturl
- *
- * Creates an ENTRYID (specifically, a PR_SOURCE_KEY) based on
- * @permanenturl
- *
- * Return value: the entryid
- **/
-GByteArray *
-e2k_permanenturl_to_entryid (const gchar *permanenturl)
-{
- GByteArray *entryid;
-
- permanenturl = strstr (permanenturl, E2K_PERMANENTURL_INFIX);
- if (!permanenturl)
- return NULL;
- permanenturl += E2K_PERMANENTURL_INFIX_LEN;
-
- entryid = g_byte_array_new ();
- while (*permanenturl++ == '/') {
- if (!append_entryid_section (entryid, &permanenturl)) {
- g_byte_array_free (entryid, TRUE);
- return NULL;
- }
- }
-
- return entryid;
-}
-
-/**
- * e2k_ascii_strcase_equal
- * @v: a string
- * @v2: another string
- *
- * ASCII-case-insensitive comparison function for use with #GHashTable.
- *
- * Return value: %TRUE if @v and @v2 are ASCII-case-insensitively
- * equal, %FALSE if not.
- **/
-gint
-e2k_ascii_strcase_equal (gconstpointer v, gconstpointer v2)
-{
- return !g_ascii_strcasecmp (v, v2);
-}
-
-/**
- * e2k_ascii_strcase_hash
- * @v: a string
- *
- * ASCII-case-insensitive hash function for use with #GHashTable.
- *
- * Return value: An ASCII-case-insensitive hashing of @v.
- **/
-guint
-e2k_ascii_strcase_hash (gconstpointer v)
-{
- /* case-insensitive g_str_hash */
-
- const guchar *p = v;
- guint h = g_ascii_tolower (*p);
-
- if (h) {
- for (p += 1; *p != '\0'; p++)
- h = (h << 5) - h + g_ascii_tolower (*p);
- }
-
- return h;
-}
-
-/**
- * e2k_restriction_folders_only:
- * @rn: a restriction
- *
- * Examines @rn, and determines if it can only return folders
- *
- * Return value: %TRUE if @rn will cause only folders to be returned
- **/
-gboolean
-e2k_restriction_folders_only (E2kRestriction *rn)
-{
- gint i;
-
- if (!rn)
- return FALSE;
-
- switch (rn->type) {
- case E2K_RESTRICTION_PROPERTY:
- if (strcmp (rn->res.property.pv.prop.name,
- E2K_PR_DAV_IS_COLLECTION) != 0)
- return FALSE;
-
- /* return TRUE if it's "= TRUE" or "!= FALSE" */
- return (rn->res.property.relop == E2K_RELOP_EQ) ==
- (rn->res.property.pv.value != NULL);
-
- case E2K_RESTRICTION_AND:
- for (i = 0; i < rn->res.and.nrns; i++) {
- if (e2k_restriction_folders_only (rn->res.and.rns[i]))
- return TRUE;
- }
- return FALSE;
-
- case E2K_RESTRICTION_OR:
- for (i = 0; i < rn->res.or.nrns; i++) {
- if (!e2k_restriction_folders_only (rn->res.or.rns[i]))
- return FALSE;
- }
- return TRUE;
-
- case E2K_RESTRICTION_NOT:
- return !e2k_restriction_folders_only (rn->res.not.rn);
-
- case E2K_RESTRICTION_COMMENT:
- return e2k_restriction_folders_only (rn->res.comment.rn);
-
- default:
- return FALSE;
- }
-}
-
-/* From MAPIDEFS.H */
-static const gchar MAPI_ONE_OFF_UID[] = {
- 0x81, 0x2b, 0x1f, 0xa4, 0xbe, 0xa3, 0x10, 0x19,
- 0x9d, 0x6e, 0x00, 0xdd, 0x01, 0x0f, 0x54, 0x02
-};
-#define MAPI_ONE_OFF_UNICODE 0x8000
-#define MAPI_ONE_OFF_NO_RICH_INFO 0x0001
-#define MAPI_ONE_OFF_MYSTERY_FLAG 0x1000
-
-/**
- * e2k_entryid_generate_oneoff:
- * @display_name: the display name of the user
- * @email: the email address
- * @unicode: %TRUE to generate a Unicode ENTRYID (in which case
- * @display_name should be UTF-8), %FALSE for an ASCII ENTRYID.
- *
- * Constructs a "one-off" ENTRYID value that can be used as a MAPI
- * recipient (eg, for a message forwarding server-side rule),
- * corresponding to @display_name and @email.
- *
- * Return value: the recipient ENTRYID
- **/
-GByteArray *
-e2k_entryid_generate_oneoff (const gchar *display_name, const gchar *email, gboolean unicode)
-{
- GByteArray *entryid;
-
- entryid = g_byte_array_new ();
-
- e2k_rule_append_uint32 (entryid, 0);
- g_byte_array_append (entryid, (guint8 *) MAPI_ONE_OFF_UID, sizeof (MAPI_ONE_OFF_UID));
- e2k_rule_append_uint16 (entryid, 0);
- e2k_rule_append_uint16 (entryid,
- MAPI_ONE_OFF_NO_RICH_INFO |
- MAPI_ONE_OFF_MYSTERY_FLAG |
- (unicode ? MAPI_ONE_OFF_UNICODE : 0));
-
- if (unicode) {
- e2k_rule_append_unicode (entryid, display_name);
- e2k_rule_append_unicode (entryid, "SMTP");
- e2k_rule_append_unicode (entryid, email);
- } else {
- e2k_rule_append_string (entryid, display_name);
- e2k_rule_append_string (entryid, "SMTP");
- e2k_rule_append_string (entryid, email);
- }
-
- return entryid;
-}
-
-static const gchar MAPI_LOCAL_UID[] = {
- 0xdc, 0xa7, 0x40, 0xc8, 0xc0, 0x42, 0x10, 0x1a,
- 0xb4, 0xb9, 0x08, 0x00, 0x2b, 0x2f, 0xe1, 0x82
-};
-
-/**
- * e2k_entryid_generate_local:
- * @exchange_dn: the Exchange 5.5-style DN of the local user
- *
- * Constructs an ENTRYID value that can be used as a MAPI
- * recipient (eg, for a message forwarding server-side rule),
- * corresponding to the local user identified by @exchange_dn.
- *
- * Return value: the recipient ENTRYID
- **/
-GByteArray *
-e2k_entryid_generate_local (const gchar *exchange_dn)
-{
- GByteArray *entryid;
-
- entryid = g_byte_array_new ();
-
- e2k_rule_append_uint32 (entryid, 0);
- g_byte_array_append (entryid, (guint8 *) MAPI_LOCAL_UID, sizeof (MAPI_LOCAL_UID));
- e2k_rule_append_uint16 (entryid, 1);
- e2k_rule_append_uint16 (entryid, 0);
- e2k_rule_append_string (entryid, exchange_dn);
-
- return entryid;
-}
-
-static const gchar MAPI_CONTACT_UID[] = {
- 0xfe, 0x42, 0xaa, 0x0a, 0x18, 0xc7, 0x1a, 0x10,
- 0xe8, 0x85, 0x0b, 0x65, 0x1c, 0x24, 0x00, 0x00
-};
-
-/**
- * e2k_entryid_generate_contact:
- * @contact_entryid: the #PR_ENTRYID of an item in the user's Contacts
- * folder.
- * @nth_address: which of the contact's email addresses to use.
- *
- * Constructs an ENTRYID value that can be used as a MAPI recipient
- * (eg, for a message forwarding server-side rule), corresponding to
- * the Contacts folder entry identified by @contact_entryid.
- *
- * Return value: the recipient ENTRYID
- **/
-GByteArray *
-e2k_entryid_generate_contact (GByteArray *contact_entryid, gint nth_address)
-{
- GByteArray *entryid;
-
- entryid = g_byte_array_new ();
-
- e2k_rule_append_uint32 (entryid, 0);
- g_byte_array_append (entryid, (guint8 *) MAPI_CONTACT_UID, sizeof (MAPI_CONTACT_UID));
- e2k_rule_append_uint32 (entryid, 3);
- e2k_rule_append_uint32 (entryid, 4);
- e2k_rule_append_uint32 (entryid, nth_address);
- e2k_rule_append_uint32 (entryid, contact_entryid->len);
- g_byte_array_append (entryid, contact_entryid->data, contact_entryid->len);
-
- return entryid;
-}
-
-/**
- * e2k_search_key_generate:
- * @addrtype: the type of @address (usually "SMTP" or "EX")
- * @address: the address data
- *
- * Constructs a PR_SEARCH_KEY value for @address
- *
- * Return value: the search key
- **/
-GByteArray *
-e2k_search_key_generate (const gchar *addrtype, const gchar *address)
-{
- GByteArray *search_key;
- guint8 *p;
-
- search_key = g_byte_array_new ();
- g_byte_array_append (search_key, (guint8 *) addrtype, strlen (addrtype));
- g_byte_array_append (search_key, (guint8 *) ":", 1);
- g_byte_array_append (search_key, (guint8 *) address, strlen (address));
- g_byte_array_append (search_key, (guint8 *) "", 1);
-
- for (p = search_key->data; *p; p++)
- *p = g_ascii_toupper (*p);
-
- return search_key;
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef E2K_UTILS_H
-#define E2K_UTILS_H
-
-#include <time.h>
-#include "e2k-types.h"
-
-time_t e2k_parse_timestamp (const gchar *timestamp);
-gchar *e2k_make_timestamp (time_t when);
-gchar *e2k_make_timestamp_rfc822 (time_t when);
-
-time_t e2k_systime_to_time_t (guint32 systime);
-guint32 e2k_systime_from_time_t (time_t tt);
-
-time_t e2k_filetime_to_time_t (guint64 filetime);
-guint64 e2k_filetime_from_time_t (time_t tt);
-
-gchar *e2k_lf_to_crlf (const gchar *in);
-gchar *e2k_crlf_to_lf (const gchar *in);
-
-gchar *e2k_strdup_with_trailing_slash (const gchar *path);
-
-const gchar *e2k_entryid_to_dn (GByteArray *entryid);
-
-gchar *e2k_entryid_to_permanenturl (GByteArray *entryid,
- const gchar *base_uri);
-GByteArray *e2k_permanenturl_to_entryid (const gchar *permanenturl);
-
-gint e2k_ascii_strcase_equal (gconstpointer v,
- gconstpointer v2);
-guint e2k_ascii_strcase_hash (gconstpointer v);
-
-gboolean e2k_restriction_folders_only (E2kRestriction *rn);
-
-GByteArray *e2k_entryid_generate_oneoff (const gchar *display_name,
- const gchar *email,
- gboolean unicode);
-GByteArray *e2k_entryid_generate_local (const gchar *exchange_dn);
-GByteArray *e2k_entryid_generate_contact (GByteArray *contact_entryid,
- gint nth_address);
-GByteArray *e2k_search_key_generate (const gchar *addrtype,
- const gchar *address);
-
-#endif /* E2K_UTILS_H */
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2003, 2004 Novell, Inc. */
-
-#ifndef __E2K_VALIDATE_H_
-#define __E2K_VALIDATE_H_
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-typedef enum {
- E2K_AUTOCONFIG_USE_GAL_DEFAULT, /* try ntlm if available and then basic if not or failed */
-
- E2K_AUTOCONFIG_USE_GAL_BASIC,
- /*E2K_AUTOCONFIG_USE_GAL_SASL,*/
- E2K_AUTOCONFIG_USE_GAL_NTLM
-} E2kAutoconfigGalAuthPref;
-
-typedef struct {
- gchar *host;
- gchar *ad_server;
- E2kAutoconfigGalAuthPref ad_auth;
- gchar *mailbox;
- gchar *owa_path;
- gboolean is_ntlm;
-}ExchangeParams;
-
-typedef enum {
- E2K_AUTOCONFIG_OK,
- E2K_AUTOCONFIG_REDIRECT,
- E2K_AUTOCONFIG_TRY_SSL,
- E2K_AUTOCONFIG_AUTH_ERROR,
- E2K_AUTOCONFIG_AUTH_ERROR_TRY_DOMAIN,
- E2K_AUTOCONFIG_AUTH_ERROR_TRY_BASIC,
- E2K_AUTOCONFIG_AUTH_ERROR_TRY_NTLM,
- E2K_AUTOCONFIG_EXCHANGE_5_5,
- E2K_AUTOCONFIG_NOT_EXCHANGE,
- E2K_AUTOCONFIG_NO_OWA,
- E2K_AUTOCONFIG_NO_MAILBOX,
- E2K_AUTOCONFIG_CANT_BPROPFIND,
- E2K_AUTOCONFIG_CANT_RESOLVE,
- E2K_AUTOCONFIG_CANT_CONNECT,
- E2K_AUTOCONFIG_CANCELLED,
- E2K_AUTOCONFIG_FAILED
-} E2kAutoconfigResult;
-
-gboolean e2k_validate_user (const gchar *owa_url, gchar *key, gchar **user,
- ExchangeParams *exchange_params,
- gboolean *remember_password,
- E2kAutoconfigResult *result,
- GtkWindow *parent);
-
-G_END_DECLS
-
-#endif /* __EXCHANGE_VALIDATE_H_ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2001-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "e2k-xml-utils.h"
-#include <stdlib.h>
-#include <libxml/HTMLparser.h>
-#include <libxml/parserInternals.h>
-#include <libxml/xmlmemory.h>
-
-static void
-my_xml_parser_error_handler (gpointer ctx, const gchar *msg, ...)
-{
- ;
-}
-
-/**
- * e2k_parse_xml:
- * @buf: the data to parse
- * @len: the length of the buffer, or -1 if it is '\0'-terminated
- *
- * Parses the XML document in @buf.
- *
- * Return value: a pointer to an #xmlDoc
- **/
-xmlDoc *
-e2k_parse_xml (const gchar *buf, gint len)
-{
- static xmlSAXHandler *sax;
- xmlParserCtxtPtr ctxt;
- xmlDoc *doc;
-
- g_return_val_if_fail (buf != NULL, NULL);
-
- if (!sax) {
- xmlInitParser();
- sax = xmlMalloc (sizeof (xmlSAXHandler));
-#if LIBXML_VERSION > 20600
- xmlSAXVersion (sax, 2);
-#else
- memcpy (sax, &xmlDefaultSAXHandler, sizeof (xmlSAXHandler));
-#endif
- sax->warning = my_xml_parser_error_handler;
- sax->error = my_xml_parser_error_handler;
- }
-
- if (len == -1)
- len = strlen (buf);
- ctxt = xmlCreateMemoryParserCtxt (buf, len);
- if (!ctxt)
- return NULL;
-
- xmlFree (ctxt->sax);
- ctxt->sax = sax;
-#if LIBXML_VERSION > 20600
- ctxt->sax2 = 1;
- ctxt->str_xml = xmlDictLookup (ctxt->dict, BAD_CAST "xml", 3);
- ctxt->str_xmlns = xmlDictLookup (ctxt->dict, BAD_CAST "xmlns", 5);
- ctxt->str_xml_ns = xmlDictLookup (ctxt->dict, XML_XML_NAMESPACE, 36);
-#endif
-
- /* We set recover to TRUE because Exchange will let you
- * put control-characters into data, which will make the
- * XML be not well-formed.
- */
- ctxt->recovery = TRUE;
- ctxt->vctxt.error = my_xml_parser_error_handler;
- ctxt->vctxt.warning = my_xml_parser_error_handler;
-
- xmlParseDocument (ctxt);
-
- doc = ctxt->myDoc;
- ctxt->sax = NULL;
- xmlFreeParserCtxt (ctxt);
-
- return doc;
-}
-
-/**
- * e2k_parse_html:
- * @buf: the data to parse
- * @len: the length of the buffer, or -1 if it is '\0'-terminated
- *
- * Parses the HTML document in @buf.
- *
- * Return value: a pointer to an #xmlDoc
- **/
-xmlDoc *
-e2k_parse_html (const gchar *buf, gint len)
-{
- xmlDoc *doc;
-#if LIBXML_VERSION > 20600
- static xmlSAXHandler *sax;
- htmlParserCtxtPtr ctxt;
-
- g_return_val_if_fail (buf != NULL, NULL);
-
- if (!sax) {
- xmlInitParser();
- sax = xmlMalloc (sizeof (htmlSAXHandler));
- memcpy (sax, &htmlDefaultSAXHandler, sizeof (xmlSAXHandlerV1));
- sax->warning = my_xml_parser_error_handler;
- sax->error = my_xml_parser_error_handler;
- }
-
- if (len == -1)
- len = strlen (buf);
- ctxt = htmlCreateMemoryParserCtxt (buf, len);
- if (!ctxt)
- return NULL;
-
- xmlFree (ctxt->sax);
- ctxt->sax = sax;
- ctxt->vctxt.error = my_xml_parser_error_handler;
- ctxt->vctxt.warning = my_xml_parser_error_handler;
-
- htmlParseDocument (ctxt);
- doc = ctxt->myDoc;
-
- ctxt->sax = NULL;
- htmlFreeParserCtxt (ctxt);
-
-#else /* LIBXML_VERSION <= 20600 */
- gchar *buf_copy = g_strndup (buf, len);
-
- doc = htmlParseDoc (buf_copy, NULL);
- g_free (buf_copy);
-#endif
-
- return doc;
-}
-
-/**
- * e2k_g_string_append_xml_escaped:
- * @string: a %GString containing XML data
- * @value: data to append to @string
- *
- * Appends @value to @string, escaping any characters that can't appear
- * unencoded in XML text (eg, "<").
- **/
-void
-e2k_g_string_append_xml_escaped (GString *string, const gchar *value)
-{
- while (*value) {
- switch (*value) {
- case '<':
- g_string_append (string, "<");
- break;
- case '>':
- g_string_append (string, ">");
- break;
- case '&':
- g_string_append (string, "&");
- break;
- case '"':
- g_string_append (string, """);
- break;
-
- default:
- g_string_append_c (string, *value);
- break;
- }
- value++;
- }
-}
-
-/**
- * e2k_xml_find:
- * @node: a node of an xml document
- * @name: the name of the element to find
- *
- * Starts or continues a pre-order depth-first search of an xml
- * document for an element named @name. @node is used as the starting
- * point of the search, but is not examined itself.
- *
- * To search the complete document, pass the root node of the document
- * as @node on the first call, and then on each successive call,
- * pass the previous match as @node.
- *
- * Return value: the first matching element after @node, or %NULL when
- * there are no more matches.
- **/
-xmlNode *
-e2k_xml_find (xmlNode *node, const gchar *name)
-{
- return e2k_xml_find_in (node, NULL, name);
-}
-
-/**
- * e2k_xml_find_in:
- * @node: a node of an xml document
- * @top: top of the search space
- * @name: the name of the element to find
- *
- * Starts or continues a pre-order depth-first search of a subset of
- * an xml document for an element named @name. @node is used as the
- * starting point of the search, but is not examined itself. @top is
- * the upper-most node that will be examined.
- *
- * To search the complete tree under a given node, pass that node as
- * both @node and @top on the first call, and then on each successive
- * call, pass the previous match as @node (with the original node
- * still as @top).
- *
- * Return value: the first matching element after @node, or %NULL when
- * there are no more matches.
- **/
-xmlNode *
-e2k_xml_find_in (xmlNode *node, xmlNode *top, const gchar *name)
-{
- g_return_val_if_fail (name != NULL, NULL);
-
- while (node) {
- /* If the current node has children, then the first
- * child is the next node to examine. If it doesn't
- * have children but does have a younger sibling, then
- * that sibling is next up. Otherwise, climb back up
- * the tree until we find a node that does have a
- * younger sibling.
- */
- if (node->children)
- node = node->children;
- else {
- while (node && !node->next && node != top)
- node = node->parent;
- if (!node || node == top)
- return NULL;
- node = node->next;
- }
-
- if (node->name && !strcmp ((gchar *) node->name, name))
- return node;
- }
-
- return NULL;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __E2K_XML_UTILS_H__
-#define __E2K_XML_UTILS_H__
-
-#include <string.h>
-
-#include "e2k-types.h"
-#include <libxml/parser.h>
-
-#define E2K_XML_HEADER "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
-
-xmlDoc *e2k_parse_xml (const gchar *buf, gint len);
-xmlDoc *e2k_parse_html (const gchar *buf, gint len);
-
-#define E2K_IS_NODE(node, nspace, nname) \
- (!xmlStrcmp ((node)->name, (xmlChar *) (nname)) && \
- (node)->ns && !xmlStrcmp ((node)->ns->href, (xmlChar *) (nspace)))
-
-void e2k_g_string_append_xml_escaped (GString *string, const gchar *value);
-
-xmlNode *e2k_xml_find (xmlNode *node, const gchar *name);
-xmlNode *e2k_xml_find_in (xmlNode *node, xmlNode *top, const gchar *name);
-
-#endif
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2001-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* WebDAV test program / utility */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <libsoup/soup-misc.h>
-
-#include "e2k-context.h"
-#include "e2k-restriction.h"
-#include "e2k-security-descriptor.h"
-#include "e2k-sid.h"
-#include "e2k-xml-utils.h"
-
-#include "e2k-propnames.h"
-#include "e2k-propnames.c"
-
-#include "test-utils.h"
-
-static E2kContext *ctx;
-static E2kOperation op;
-
-static const gchar *folder_tree_props[] = {
- E2K_PR_DAV_DISPLAY_NAME,
- E2K_PR_EXCHANGE_FOLDER_CLASS
-};
-static const gint n_folder_tree_props = sizeof (folder_tree_props) / sizeof (folder_tree_props[0]);
-
-static void
-display_folder_tree (E2kContext *ctx, gchar *top)
-{
- E2kRestriction *rn;
- E2kResultIter *iter;
- E2kResult *result;
- gint status;
- const gchar *name, *class;
-
- e2k_operation_init (&op);
- rn = e2k_restriction_prop_bool (E2K_PR_DAV_IS_COLLECTION,
- E2K_RELOP_EQ, TRUE);
- iter = e2k_context_search_start (ctx, &op, top,
- folder_tree_props,
- n_folder_tree_props,
- rn, NULL, TRUE);
- e2k_restriction_unref (rn);
-
- while ((result = e2k_result_iter_next (iter))) {
- name = e2k_properties_get_prop (result->props,
- E2K_PR_DAV_DISPLAY_NAME);
- class = e2k_properties_get_prop (result->props,
- E2K_PR_EXCHANGE_FOLDER_CLASS);
-
- printf ("%s:\n %s, %s\n", result->href,
- name, class ? class : "(No Outlook folder class)");
- }
- status = e2k_result_iter_free (iter);
- e2k_operation_free (&op);
-
- test_abort_if_http_error (status);
- test_quit ();
-}
-
-static void
-list_contents (E2kContext *ctx, gchar *top, gboolean reverse)
-{
- E2kRestriction *rn;
- E2kResultIter *iter;
- E2kResult *result;
- const gchar *prop;
- gint status;
-
- e2k_operation_init (&op);
- prop = E2K_PR_DAV_DISPLAY_NAME;
- rn = e2k_restriction_prop_bool (E2K_PR_DAV_IS_COLLECTION,
- E2K_RELOP_EQ, FALSE);
- iter = e2k_context_search_start (ctx, &op, top, &prop, 1,
- rn, NULL, !reverse);
- e2k_restriction_unref (rn);
-
- while ((result = e2k_result_iter_next (iter))) {
- printf ("%3d %s (%s)\n", e2k_result_iter_get_index (iter),
- result->href,
- (gchar *)e2k_properties_get_prop (result->props,
- E2K_PR_DAV_DISPLAY_NAME));
- }
- status = e2k_result_iter_free (iter);
- e2k_operation_free (&op);
-
- test_abort_if_http_error (status);
- test_quit ();
-}
-
-static gint
-mp_compar (gconstpointer k, gconstpointer m)
-{
- const gchar *key = k;
- struct mapi_proptag *mp = (gpointer)m;
-
- return strncmp (key, mp->proptag, 5);
-}
-
-static void
-print_propname (const gchar *propname)
-{
- struct mapi_proptag *mp;
-
- printf (" %s", propname);
-
- if (!strncmp (propname, E2K_NS_MAPI_PROPTAG, sizeof (E2K_NS_MAPI_PROPTAG) - 1)) {
- mp = bsearch (propname + 42, mapi_proptags, nmapi_proptags,
- sizeof (struct mapi_proptag), mp_compar);
- if (mp)
- printf (" (%s)", mp->name);
- }
-
- printf (":\n");
-}
-
-static void
-print_binary (GByteArray *data)
-{
- guchar *start, *end, *p;
-
- end = data->data + data->len;
- for (start = data->data; start < end; start += 16) {
- printf (" ");
- for (p = start; p < end && p < start + 16; p++)
- printf ("%02x ", *p);
- while (p++ < start + 16)
- printf (" ");
- printf (" ");
- for (p = start; p < end && p < start + 16; p++)
- printf ("%c", isprint (*p) ? *p : '.');
- printf ("\n");
- }
-}
-
-typedef struct {
- const gchar *propname;
- E2kPropType type;
- gpointer value;
-} EBrowseProp;
-
-static gint
-prop_compar (gconstpointer a, gconstpointer b)
-{
- EBrowseProp **pa = (gpointer)a;
- EBrowseProp **pb = (gpointer)b;
-
- return strcmp ((*pa)->propname, (*pb)->propname);
-}
-
-static void
-print_prop (EBrowseProp *prop)
-{
- print_propname (prop->propname);
-
- switch (prop->type) {
- case E2K_PROP_TYPE_BINARY:
- print_binary (prop->value);
- break;
-
- case E2K_PROP_TYPE_STRING_ARRAY:
- case E2K_PROP_TYPE_INT_ARRAY:
- {
- GPtrArray *array = prop->value;
- gint i;
-
- for (i = 0; i < array->len; i++)
- printf (" %s\n", (gchar *)array->pdata[i]);
- break;
- }
-
- case E2K_PROP_TYPE_BINARY_ARRAY:
- {
- GPtrArray *array = prop->value;
- gint i;
-
- for (i = 0; i < array->len; i++) {
- print_binary (array->pdata[i]);
- printf ("\n");
- }
- break;
- }
-
- case E2K_PROP_TYPE_XML:
- printf (" (xml)\n");
- break;
-
- case E2K_PROP_TYPE_STRING:
- default:
- printf (" %s\n", (gchar *)prop->value);
- break;
- }
-}
-
-static void
-add_prop (const gchar *propname, E2kPropType type, gpointer value, gpointer props)
-{
- EBrowseProp *prop;
-
- prop = g_new0 (EBrowseProp, 1);
- prop->propname = propname;
- prop->type = type;
- prop->value = value;
- g_ptr_array_add (props, prop);
-}
-
-static void
-print_properties (E2kResult *results, gint nresults)
-{
- GPtrArray *props;
- gint i;
-
- if (nresults != 1) {
- printf ("Got %d results?\n", nresults);
- test_quit ();
- return;
- }
-
- printf ("%s\n", results[0].href);
- props = g_ptr_array_new ();
- e2k_properties_foreach (results[0].props, add_prop, props);
- qsort (props->pdata, props->len, sizeof (gpointer), prop_compar);
-
- for (i = 0; i < props->len; i++)
- print_prop (props->pdata[i]);
-
- test_quit ();
-}
-
-static void
-got_all_properties (SoupMessage *msg, gpointer ctx)
-{
- E2kResult *results;
- gint nresults;
-
- test_abort_if_http_error (msg->status_code);
-
- e2k_results_from_multistatus (msg, &results, &nresults);
- test_abort_if_http_error (msg->status_code);
- print_properties (results, nresults);
- e2k_results_free (results, nresults);
-}
-
-#define ALL_PROPS \
-"<?xml version=\"1.0\" encoding=\"utf-8\" ?>" \
-"<propfind xmlns=\"DAV:\" xmlns:e=\"http://schemas.microsoft.com/exchange/\">" \
-" <allprop>" \
-" <e:allprop/>" \
-" </allprop>" \
-"</propfind>"
-
-static void
-get_all_properties (E2kContext *ctx, gchar *uri)
-{
- SoupMessage *msg;
-
- msg = e2k_soup_message_new_full (ctx, uri, "PROPFIND",
- "text/xml", SOUP_BUFFER_USER_OWNED,
- ALL_PROPS, strlen (ALL_PROPS));
- soup_message_add_header (msg->request_headers, "Brief", "t");
- soup_message_add_header (msg->request_headers, "Depth", "0");
-
- e2k_context_queue_message (ctx, msg, got_all_properties, ctx);
-}
-
-static void
-get_property (E2kContext *ctx, gchar *uri, gchar *prop)
-{
- E2kHTTPStatus status;
- E2kResult *results;
- gint nresults, i;
-
- if (!strncmp (prop, "PR_", 3)) {
- for (i = 0; i < nmapi_proptags; i++)
- if (!strcmp (mapi_proptags[i].name, prop)) {
- prop = g_strconcat (E2K_NS_MAPI_PROPTAG,
- mapi_proptags[i].proptag,
- NULL);
- break;
- }
- }
-
- e2k_operation_init (&op);
- status = e2k_context_propfind (ctx, &op, uri,
- (const gchar **)&prop, 1,
- &results, &nresults);
- e2k_operation_free (&op);
- test_abort_if_http_error (status);
- print_properties (results, nresults);
- e2k_results_free (results, nresults);
-}
-
-static void
-get_fav_properties(E2kContext *ctx, gchar *uri)
-{
- E2kRestriction *rn;
- E2kResultIter *iter;
- E2kResult *result;
- const gchar *prop;
- gint status;
- gchar *eml_str, *top = uri, fav_uri[1024];
-
- /* list the contents and search for the favorite properties */
- e2k_operation_init (&op);
- prop = E2K_PR_DAV_DISPLAY_NAME;
- rn = e2k_restriction_prop_bool (E2K_PR_DAV_IS_COLLECTION,
- E2K_RELOP_EQ, FALSE);
- iter = e2k_context_search_start (ctx, &op, top, &prop, 1,
- rn, NULL, FALSE);
- e2k_restriction_unref (rn);
-
- while ((result = e2k_result_iter_next (iter))) {
- strcpy(fav_uri, uri);
- eml_str = strstr(result->href, "Shortcuts");
- eml_str = eml_str + strlen("Shortcuts");
-
- strcat(fav_uri, eml_str);
-
- printf("\nNAME:\n");
- get_property (ctx, fav_uri, PR_FAV_DISPLAY_NAME);
- printf("\nALIAS:\n");
- get_property (ctx, fav_uri, PR_FAV_DISPLAY_ALIAS);
- printf("\nPUBLIC SOURCE KEY:\n");
- get_property (ctx, fav_uri, PR_FAV_PUBLIC_SOURCE_KEY);
- printf("\nPARENT SOURCE KEY:\n");
- get_property (ctx, fav_uri, PR_FAV_PARENT_SOURCE_KEY);
- printf("\nAUTO SUBFOLDERS:\n");
- get_property (ctx, fav_uri, PR_FAV_AUTOSUBFOLDERS);
- printf("\nLEVEL MASK:\n");
- get_property (ctx, fav_uri, PR_FAV_LEVEL_MASK);
- printf("\nINHERIT AUTO:\n");
- get_property (ctx, fav_uri, PR_FAV_INHERIT_AUTO);
- printf("\nDEL SUBS:\n");
- get_property (ctx, fav_uri, PR_FAV_DEL_SUBS);
- printf("\n\t\t=================================================\n");
-
- memset(fav_uri, 0, 1024);
- }
- status = e2k_result_iter_free (iter);
- e2k_operation_free (&op);
-
- test_abort_if_http_error (status);
- test_quit ();
-}
-
-static void
-get_sd (E2kContext *ctx, gchar *uri)
-{
- const gchar *props[] = {
- E2K_PR_EXCHANGE_SD_BINARY,
- E2K_PR_EXCHANGE_SD_XML,
- };
- E2kHTTPStatus status;
- E2kResult *results;
- gint nresults;
- xmlNodePtr xml_form;
- GByteArray *binary_form;
- E2kSecurityDescriptor *sd;
- E2kPermissionsRole role;
- guint32 perms;
- GList *sids, *s;
- E2kSid *sid;
-
- e2k_operation_init (&op);
- status = e2k_context_propfind (ctx, &op, uri, props, 2,
- &results, &nresults);
- e2k_operation_free (&op);
- test_abort_if_http_error (status);
-
- if (nresults == 0)
- goto done;
-
- 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 done;
-
- xmlElemDump (stdout, NULL, xml_form);
- printf ("\n");
-
- print_binary (binary_form);
- printf ("\n");
-
- sd = e2k_security_descriptor_new (xml_form, binary_form);
- if (!sd) {
- printf ("(Could not parse)\n");
- goto done;
- }
-
- sids = e2k_security_descriptor_get_sids (sd);
- for (s = sids; s; s = s->next) {
- sid = s->data;
- perms = e2k_security_descriptor_get_permissions (sd, sid);
- role = e2k_permissions_role_find (perms);
- printf ("%s: %s (0x%lx)\n",
- e2k_sid_get_display_name (sid),
- e2k_permissions_role_get_name (role),
- (gulong)perms);
- }
- g_list_free (sids);
-
- if (!e2k_security_descriptor_to_binary (sd))
- printf ("\nSD is malformed.\n");
- g_object_unref (sd);
-
- done:
- test_quit ();
-}
-
-static void
-get_body (E2kContext *ctx, gchar *uri)
-{
- E2kHTTPStatus status;
- gchar *body;
- gint len;
-
- e2k_operation_init (&op);
- status = e2k_context_get (ctx, &op, uri, NULL, &body, &len);
- e2k_operation_free (&op);
- test_abort_if_http_error (status);
-
- fwrite (body, 1, len, stdout);
- test_quit ();
-}
-
-static void
-delete (E2kContext *ctx, gchar *uri)
-{
- E2kHTTPStatus status;
-
- e2k_operation_init (&op);
- status = e2k_context_delete (ctx, &op, uri);
- e2k_operation_free (&op);
- test_abort_if_http_error (status);
- test_quit ();
-}
-
-static void
-notify (E2kContext *ctx, const gchar *uri,
- E2kContextChangeType type, gpointer user_data)
-{
- switch (type) {
- case E2K_CONTEXT_OBJECT_CHANGED:
- printf ("Changed\n");
- break;
- case E2K_CONTEXT_OBJECT_ADDED:
- printf ("Added\n");
- break;
- case E2K_CONTEXT_OBJECT_REMOVED:
- printf ("Removed\n");
- break;
- case E2K_CONTEXT_OBJECT_MOVED:
- printf ("Moved\n");
- break;
- }
-}
-
-static void
-subscribe (E2kContext *ctx, gchar *uri)
-{
- e2k_context_subscribe (ctx, uri,
- E2K_CONTEXT_OBJECT_CHANGED, 0,
- notify, NULL);
- e2k_context_subscribe (ctx, uri,
- E2K_CONTEXT_OBJECT_ADDED, 0,
- notify, NULL);
- e2k_context_subscribe (ctx, uri,
- E2K_CONTEXT_OBJECT_REMOVED, 0,
- notify, NULL);
- e2k_context_subscribe (ctx, uri,
- E2K_CONTEXT_OBJECT_MOVED, 0,
- notify, NULL);
-}
-
-static void
-move (E2kContext *ctx, gchar *from, gchar *to, gboolean delete)
-{
- GPtrArray *source_hrefs;
- E2kResultIter *iter;
- E2kResult *result;
- E2kHTTPStatus status;
-
- source_hrefs = g_ptr_array_new ();
- g_ptr_array_add (source_hrefs, "");
-
- e2k_operation_init (&op);
- iter = e2k_context_transfer_start (ctx, &op, from, to,
- source_hrefs, delete);
- g_ptr_array_free (source_hrefs, TRUE);
-
- result = e2k_result_iter_next (iter);
- if (result) {
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (result->status))
- printf ("Failed: %d\n", result->status);
- else {
- printf ("moved to %s\n",
- (gchar *)e2k_properties_get_prop (result->props,
- E2K_PR_DAV_LOCATION));
- }
- }
- status = e2k_result_iter_free (iter);
- e2k_operation_free (&op);
-
- test_abort_if_http_error (status);
- test_quit ();
-}
-
-static void
-name (E2kContext *ctx, gchar *alias, gchar *uri_prefix)
-{
- E2kHTTPStatus status;
- gchar *uri, *body;
- gint len;
- xmlDoc *doc;
- xmlNode *item, *node;
- gchar *data;
-
- uri = g_strdup_printf ("%s?Cmd=galfind&AN=%s", uri_prefix, alias);
- e2k_operation_init (&op);
- status = e2k_context_get_owa (ctx, &op, uri, TRUE, &body, &len);
- e2k_operation_free (&op);
- test_abort_if_http_error (status);
-
- doc = e2k_parse_xml (body, len);
-
- if ((node = e2k_xml_find (doc->children, "error")))
- printf ("Error: %s\n", xmlNodeGetContent (node));
- else {
- item = doc->children;
- while ((item = e2k_xml_find (item, "item"))) {
- for (node = item->children; node; node = node->next) {
- if (node->type == XML_ELEMENT_NODE) {
- data = xmlNodeGetContent (node);
- if (data && *data)
- printf ("%s: %s\n", node->name, data);
- xmlFree (data);
- }
- }
- }
- }
-
- xmlFreeDoc (doc);
- test_quit ();
-}
-
-static void
-put (E2kContext *ctx, const gchar *file, const gchar *uri)
-{
- struct stat st;
- gchar *buf;
- gint fd;
- E2kHTTPStatus status;
-
- fd = open (file, O_RDONLY);
- if (fd == -1 || fstat (fd, &st) == -1) {
- fprintf (stderr, "%s\n", g_strerror (errno));
- exit (1);
- }
- buf = g_malloc (st.st_size);
- read (fd, buf, st.st_size);
- close (fd);
-
- e2k_operation_init (&op);
- status = e2k_context_put (ctx, &op, uri,
- "message/rfc822", buf, st.st_size,
- NULL);
- e2k_operation_free (&op);
- test_abort_if_http_error (status);
- test_quit ();
-}
-
-static gpointer
-cancel (gpointer op)
-{
- e2k_operation_cancel (op);
- return NULL;
-}
-
-static void
-quit (gint sig)
-{
- static pthread_t cancel_thread;
-
- /* Can't cancel from here because we might be
- * inside a malloc.
- */
- if (!cancel_thread) {
- pthread_create (&cancel_thread, NULL, cancel, &op);
- } else
- exit (0);
-}
-
-static void
-usage (void)
-{
- printf ("usage: ebrowse -t URI (shallow folder tree)\n");
- printf (" ebrowse [-l | -L ] URI (contents listing [back/forward])\n");
- printf (" ebrowse [ -p | -P prop ] URI (look up all/one prop)\n");
- printf (" ebrowse -S URI (look up security descriptor)\n");
- printf (" ebrowse -b URI (fetch body)\n");
- printf (" ebrowse -q FILE URI (put body)\n");
- printf (" ebrowse -d URI (delete)\n");
- printf (" ebrowse -s URI (subscribe and listen)\n");
- printf (" ebrowse [ -m | -c ] SRC DEST (move/copy)\n");
- printf (" ebrowse -n ALIAS URI (lookup name)\n");
- printf (" ebrowse -f URI (lookup favorite folder props)\n");
- exit (1);
-}
-
-const gchar *test_program_name = "ebrowse";
-
-void
-test_main (gint argc, gchar **argv)
-{
- gchar *uri;
-
- signal (SIGINT, quit);
-
- uri = argv[argc - 1];
- ctx = test_get_context (uri);
-
- switch (argv[1][1]) {
- case 't':
- display_folder_tree (ctx, uri);
- break;
-
- case 'l':
- list_contents (ctx, uri, FALSE);
- break;
-
- case 'L':
- list_contents (ctx, uri, TRUE);
- break;
-
- case 'b':
- get_body (ctx, uri);
- break;
-
- case 'd':
- delete (ctx, uri);
- break;
-
- case 'p':
- get_all_properties (ctx, uri);
- break;
-
- case 'P':
- get_property (ctx, uri, argv[2]);
- break;
-
- case 'S':
- get_sd (ctx, uri);
- break;
-
- case 's':
- subscribe (ctx, uri);
- break;
-
- case 'm':
- case 'c':
- move (ctx, argv[2], uri, argv[1][1] == 'm');
- break;
-
- case 'n':
- name (ctx, argv[2], uri);
- break;
-
- case 'q':
- put (ctx, argv[2], uri);
- break;
-
- case 'f':
- get_fav_properties(ctx, uri);
- break;
-
- default:
- usage ();
- }
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2002-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* Free/Busy test program. Note though that this uses the code in
- * e2k-freebusy.c, which is not currently used by Connector itself.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-
-#include "e2k-freebusy.h"
-#include "e2k-global-catalog.h"
-#include "test-utils.h"
-
-const gchar *test_program_name = "fbtest";
-
-void
-test_main (gint argc, gchar **argv)
-{
- E2kGlobalCatalog *gc;
- E2kGlobalCatalogStatus status;
- E2kGlobalCatalogEntry *entry;
- const gchar *server, *email;
- E2kContext *ctx;
- E2kFreebusy *fb;
- E2kFreebusyEvent event;
- gint ti, bi, oi;
- gchar *public_uri;
- struct tm tm;
- time_t t;
-
- if (argc != 3) {
- fprintf (stderr, "Usage: %s server email-addr\n", argv[0]);
- exit (1);
- }
-
- server = argv[1];
- email = argv[2];
-
- gc = test_get_gc (server);
-
- status = e2k_global_catalog_lookup (
- gc, NULL, E2K_GLOBAL_CATALOG_LOOKUP_BY_EMAIL,
- email, E2K_GLOBAL_CATALOG_LOOKUP_LEGACY_EXCHANGE_DN,
- &entry);
-
- if (status != E2K_GLOBAL_CATALOG_OK) {
- fprintf (stderr, "Lookup failed: %d\n", status);
- test_quit ();
- return;
- }
-
- public_uri = g_strdup_printf ("http://%s/public", server);
- ctx = test_get_context (public_uri);
- fb = e2k_freebusy_new (ctx, public_uri, entry->legacy_exchange_dn);
- g_free (public_uri);
- g_object_unref (ctx);
-
- if (!fb) {
- fprintf (stderr, "Could not get fb props\n");
- test_quit ();
- return;
- }
-
- if (!fb->events[E2K_BUSYSTATUS_ALL]->len) {
- printf ("No data\n");
- test_quit ();
- return;
- }
-
- printf (" 6am 9am noon 3pm 6pm\n");
-
- ti = bi = oi = 0;
- for (t = fb->start; t < fb->end; t += 30 * 60) {
- if ((t - fb->start) % (24 * 60 * 60) == 0) {
- tm = *localtime (&t);
- printf ("\n%02d-%02d: ", tm.tm_mon + 1, tm.tm_mday);
- }
-
- for (; oi < fb->events[E2K_BUSYSTATUS_OOF]->len; oi++) {
- event = g_array_index (fb->events[E2K_BUSYSTATUS_OOF],
- E2kFreebusyEvent, oi);
- if (event.end <= t)
- continue;
- if (event.start < t + (30 * 60)) {
- printf ("O");
- goto next;
- }
- if (event.start > t)
- break;
- }
- for (; bi < fb->events[E2K_BUSYSTATUS_BUSY]->len; bi++) {
- event = g_array_index (fb->events[E2K_BUSYSTATUS_BUSY],
- E2kFreebusyEvent, bi);
- if (event.end <= t)
- continue;
- if (event.start < t + (30 * 60)) {
- printf ("X");
- goto next;
- }
- if (event.start > t)
- break;
- }
- for (; ti < fb->events[E2K_BUSYSTATUS_TENTATIVE]->len; ti++) {
- event = g_array_index (fb->events[E2K_BUSYSTATUS_TENTATIVE],
- E2kFreebusyEvent, ti);
- if (event.end <= t)
- continue;
- if (event.start < t + (30 * 60)) {
- printf ("t");
- goto next;
- }
- if (event.start > t)
- break;
- }
- printf (".");
-
- next:
- if ((t - fb->start) % (60 * 60))
- printf (" ");
- }
- printf ("\n");
-
- test_quit ();
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2002-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* Global Catalog test program */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <pthread.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "e2k-global-catalog.h"
-#include "e2k-sid.h"
-#include "test-utils.h"
-
-E2kGlobalCatalog *gc;
-E2kOperation op;
-
-static void
-do_lookup (E2kGlobalCatalog *gc, const gchar *user)
-{
- E2kGlobalCatalogStatus status;
- E2kGlobalCatalogEntry *entry;
- E2kGlobalCatalogLookupType type;
- guint32 flags;
- gint i, pwd_exp_days;
- gdouble maxAge;
-
- if (*user == '/')
- type = E2K_GLOBAL_CATALOG_LOOKUP_BY_LEGACY_EXCHANGE_DN;
- else if (strchr (user, '@'))
- type = E2K_GLOBAL_CATALOG_LOOKUP_BY_EMAIL;
- else
- type = E2K_GLOBAL_CATALOG_LOOKUP_BY_DN;
-
- flags = E2K_GLOBAL_CATALOG_LOOKUP_SID |
- E2K_GLOBAL_CATALOG_LOOKUP_EMAIL |
- E2K_GLOBAL_CATALOG_LOOKUP_MAILBOX |
- E2K_GLOBAL_CATALOG_LOOKUP_LEGACY_EXCHANGE_DN |
- E2K_GLOBAL_CATALOG_LOOKUP_DELEGATES |
- E2K_GLOBAL_CATALOG_LOOKUP_DELEGATORS |
- E2K_GLOBAL_CATALOG_LOOKUP_QUOTA |
- E2K_GLOBAL_CATALOG_LOOKUP_ACCOUNT_CONTROL;
-
- e2k_operation_init (&op);
- status = e2k_global_catalog_lookup (gc, &op, type, user, flags, &entry);
- // e2k_operation_free (&op);
-
- switch (status) {
- case E2K_GLOBAL_CATALOG_OK:
- break;
- case E2K_GLOBAL_CATALOG_NO_SUCH_USER:
- printf ("No entry for %s\n", user);
- test_quit ();
- return;
- case E2K_GLOBAL_CATALOG_NO_DATA:
- printf ("Entry for %s contains no data\n", user);
- test_quit ();
- return;
- case E2K_GLOBAL_CATALOG_AUTH_FAILED:
- printf ("Authentication failed (try DOMAIN\\username)\n");
- test_quit ();
- return;
- default:
- printf ("Error looking up user\n");
- test_quit ();
- return;
- }
-
- printf ("%s (%s)\n", entry->display_name, entry->dn);
- if (entry->email)
- printf (" email: %s\n", entry->email);
- if (entry->mailbox)
- printf (" mailbox: %s on %s\n", entry->mailbox, entry->exchange_server);
- if (entry->legacy_exchange_dn)
- printf (" Exchange 5.5 DN: %s\n", entry->legacy_exchange_dn);
- if (entry->sid)
- printf (" sid: %s\n", e2k_sid_get_string_sid (entry->sid));
- if (entry->delegates) {
- printf (" delegates:\n");
- for (i = 0; i < entry->delegates->len; i++)
- printf (" %s\n", (gchar *)entry->delegates->pdata[i]);
- }
- if (entry->delegators) {
- printf (" delegators:\n");
- for (i = 0; i < entry->delegators->len; i++)
- printf (" %s\n", (gchar *)entry->delegators->pdata[i]);
- }
-
- if (entry->quota_warn || entry->quota_nosend || entry->quota_norecv )
- printf (" Mail Quota Info:\n");
- if (entry->quota_warn)
- printf (" Issue Quota warning at : %d\n", entry->quota_warn);
- if (entry->quota_nosend)
- printf (" Stop sending mails at : %d\n", entry->quota_nosend);
- if (entry->quota_norecv)
- printf (" Stop sending and recieving mails at : %d\n", entry->quota_norecv);
- if (entry->user_account_control)
- printf (" user_account_control : %d\n", entry->user_account_control);
-
- maxAge = lookup_passwd_max_age (gc, &op);
- printf("Password max age is %f \n", maxAge);
- pwd_exp_days = (maxAge * 0.000000100)/86400;
- printf("Password expiery period is %d \n", pwd_exp_days);
-
- e2k_operation_free (&op);
-
- e2k_global_catalog_entry_free (gc, entry);
- test_quit ();
-}
-
-static gchar *
-lookup_dn (E2kGlobalCatalog *gc, const gchar *id)
-{
- E2kGlobalCatalogEntry *entry;
- E2kGlobalCatalogLookupType type;
- E2kGlobalCatalogStatus status;
- gchar *dn;
-
- if (id[0] == '/')
- type = E2K_GLOBAL_CATALOG_LOOKUP_BY_LEGACY_EXCHANGE_DN;
- else if (strchr (id, '@'))
- type = E2K_GLOBAL_CATALOG_LOOKUP_BY_EMAIL;
- else
- return g_strdup (id);
-
- e2k_operation_init (&op);
- status = e2k_global_catalog_lookup (gc, &op, type, id, 0, &entry);
- e2k_operation_free (&op);
-
- switch (status) {
- case E2K_GLOBAL_CATALOG_OK:
- break;
- case E2K_GLOBAL_CATALOG_NO_SUCH_USER:
- printf ("No entry for %s\n", id);
- exit (1);
- break;
- default:
- printf ("Error looking up user %s\n", id);
- exit (1);
- break;
- }
-
- dn = g_strdup (entry->dn);
- e2k_global_catalog_entry_free (gc, entry);
-
- return dn;
-}
-
-static void
-do_modify (E2kGlobalCatalog *gc, const gchar *user,
- gint deleg_op, const gchar *delegate)
-{
- gchar *self_dn, *deleg_dn;
- E2kGlobalCatalogStatus status;
-
- self_dn = lookup_dn (gc, user);
- deleg_dn = lookup_dn (gc, delegate);
-
- e2k_operation_init (&op);
- if (deleg_op == '+')
- status = e2k_global_catalog_add_delegate (gc, &op, self_dn, deleg_dn);
- else
- status = e2k_global_catalog_remove_delegate (gc, &op, self_dn, deleg_dn);
- e2k_operation_free (&op);
-
- switch (status) {
- case E2K_GLOBAL_CATALOG_OK:
- printf ("Done\n");
- break;
- case E2K_GLOBAL_CATALOG_BAD_DATA:
- printf ("Invalid delegate DN\n");
- break;
- case E2K_GLOBAL_CATALOG_NO_DATA:
- printf ("No such delegate to remove\n");
- break;
- case E2K_GLOBAL_CATALOG_EXISTS:
- printf ("That user is already a delegate\n");
- break;
- default:
- printf ("Failed\n");
- break;
- }
-
- test_quit ();
-}
-
-static gpointer
-cancel (gpointer data)
-{
- e2k_operation_cancel (&op);
- return NULL;
-}
-
-static void
-quit (gint sig)
-{
- static pthread_t cancel_thread;
-
- if (!cancel_thread) {
- pthread_create (&cancel_thread, NULL, cancel, NULL);
- } else
- exit (0);
-}
-
-const gchar *test_program_name = "gctest";
-
-void
-test_main (gint argc, gchar **argv)
-{
- const gchar *server;
-
- if (argc < 3 || argc > 4 ||
- (argc == 4 && argv[3][0] != '+' && argv[3][0] != '-')) {
- fprintf (stderr, "Usage: %s server email-or-dn [[+|-]delegate]\n", argv[0]);
- exit (1);
- }
-
- signal (SIGINT, quit);
-
- server = argv[1];
- gc = test_get_gc (server);
-
- if (argc == 3)
- do_lookup (gc, argv[2]);
- else
- do_modify (gc, argv[2], argv[3][0], argv[3] + 1);
-
- g_object_unref (gc);
-}
+++ /dev/null
-http://schemas.microsoft.com/mapi/proptag/
-
-The second half of each property name indicates the type:
-0002 PT_SHORT signed 16-bit integer
-0003 PT_LONG signed 32-bit integer
-000a PT_ERROR invalid type (?)
-000b PT_BOOLEAN boolean
-000d PT_OBJECT embedded object
-0014 PT_LONGLONG signed 64-bit integer
-001e PT_STRING8 Locale-encoded string
-001f PT_UNICODE UTF8-encoded string
-0040 PT_SYSTIME 64bit time value
-0048 PT_CLSID GUID
-00fd PT_SRESTRICTION rule condition
-00fe PT_ACTIONS rule actions
-0102 PT_BINARY binary blob
-1xxx PT_MV_xxx multivalued
-
-In general, you can request either the 001e or 001f variant of a
-string.
-
-Not all properties are available via WebDAV. (In particular, none with
-type 000d are.)
-
-(The part below this line is preprocessed into lib/mapi-properties.[ch])
-
-x00010003 PR_ACKNOWLEDGEMENT_MODE
-x0002000b PR_ALTERNATE_RECIPIENT_ALLOWED
-x00030102 PR_AUTHORIZING_USERS
-x0004001f PR_AUTO_FORWARD_COMMENT
-x0005000b PR_AUTO_FORWARDED
-x00060102 PR_CONTENT_CONFIDENTIALITY_ALGORITHM_ID
-x00070102 PR_CONTENT_CORRELATOR
-x0008001f PR_CONTENT_IDENTIFIER
-x00090003 PR_CONTENT_LENGTH
-x000a000b PR_CONTENT_RETURN_REQUESTED
-x000b0102 PR_CONVERSATION_KEY
-x000c0102 PR_CONVERSION_EITS
-x000d000b PR_CONVERSION_WITH_LOSS_PROHIBITED
-x000e0102 PR_CONVERTED_EITS
-x000f0040 PR_DEFERRED_DELIVERY_TIME
-x00100040 PR_DELIVER_TIME
-x00110003 PR_DISCARD_REASON
-x0012000b PR_DISCLOSURE_OF_RECIPIENTS
-x00130102 PR_DL_EXPANSION_HISTORY
-x0014000b PR_DL_EXPANSION_PROHIBITED
-x00150040 PR_EXPIRY_TIME
-x0016000b PR_IMPLICIT_CONVERSION_PROHIBITED
-x00170003 PR_IMPORTANCE
-x00180102 PR_IPM_ID
-x00190040 PR_LATEST_DELIVERY_TIME
-x001a001f PR_MESSAGE_CLASS
-x001b0102 PR_MESSAGE_DELIVERY_ID
-x001e0102 PR_MESSAGE_SECURITY_LABEL
-x001f0102 PR_OBSOLETED_IPMS
-x00200102 PR_ORIGINALLY_INTENDED_RECIPIENT_NAME
-x00210102 PR_ORIGINAL_EITS
-x00220102 PR_ORIGINATOR_CERTIFICATE
-x0023000b PR_ORIGINATOR_DELIVERY_REPORT_REQUESTED
-x00240102 PR_ORIGINATOR_RETURN_ADDRESS
-x00250102 PR_PARENT_KEY
-x00260003 PR_PRIORITY
-x00270102 PR_ORIGIN_CHECK
-x0028000b PR_PROOF_OF_SUBMISSION_REQUESTED
-x0029000b PR_READ_RECEIPT_REQUESTED
-x002a0040 PR_RECEIPT_TIME
-x002b000b PR_RECIPIENT_REASSIGNMENT_PROHIBITED
-x002c0102 PR_REDIRECTION_HISTORY
-x002d0102 PR_RELATED_IPMS
-x002e0003 PR_ORIGINAL_SENSITIVITY
-x002f001f PR_LANGUAGES
-x00300040 PR_REPLY_TIME
-x00310102 PR_REPORT_TAG
-x00320040 PR_REPORT_TIME
-x0033000b PR_RETURNED_IPM
-x00340003 PR_SECURITY
-x0035000b PR_INCOMPLETE_COPY
-x00360003 PR_SENSITIVITY
-x0037001f PR_SUBJECT
-x00380102 PR_SUBJECT_IPM
-x00390040 PR_CLIENT_SUBMIT_TIME
-x003a001f PR_REPORT_NAME
-x003b0102 PR_SENT_REPRESENTING_SEARCH_KEY
-x003c0102 PR_X400_CONTENT_TYPE
-x003d001f PR_SUBJECT_PREFIX
-x003e0003 PR_NON_RECEIPT_REASON
-x003f0102 PR_RECEIVED_BY_ENTRYID
-x0040001f PR_RECEIVED_BY_NAME
-x00410102 PR_SENT_REPRESENTING_ENTRYID
-x0042001f PR_SENT_REPRESENTING_NAME
-x00430102 PR_RCVD_REPRESENTING_ENTRYID
-x0044001f PR_RCVD_REPRESENTING_NAME
-x00450102 PR_REPORT_ENTRYID
-x00460102 PR_READ_RECEIPT_ENTRYID
-x00470102 PR_MESSAGE_SUBMISSION_ID
-x00470102 PR_MTS_ID
-x00470102 PR_MTS_REPORT_ID
-x00480040 PR_PROVIDER_SUBMIT_TIME
-x0049001f PR_ORIGINAL_SUBJECT
-x004a000b PR_DISC_VAL
-x004b001f PR_ORIG_MESSAGE_CLASS
-x004c0102 PR_ORIGINAL_AUTHOR_ENTRYID
-x004d001f PR_ORIGINAL_AUTHOR_NAME
-x004e0040 PR_ORIGINAL_SUBMIT_TIME
-x004f0102 PR_REPLY_RECIPIENT_ENTRIES
-x0050001f PR_REPLY_RECIPIENT_NAMES
-x00510102 PR_RECEIVED_BY_SEARCH_KEY
-x00520102 PR_RCVD_REPRESENTING_SEARCH_KEY
-x00530102 PR_READ_RECEIPT_SEARCH_KEY
-x00540102 PR_REPORT_SEARCH_KEY
-x00550040 PR_ORIGINAL_DELIVERY_TIME
-x00560102 PR_ORIGINAL_AUTHOR_SEARCH_KEY
-x0057000b PR_MESSAGE_TO_ME
-x0058000b PR_MESSAGE_CC_ME
-x0059000b PR_MESSAGE_RECIP_ME
-x005a001f PR_ORIGINAL_SENDER_NAME
-x005b0102 PR_ORIGINAL_SENDER_ENTRYID
-x005c0102 PR_ORIGINAL_SENDER_SEARCH_KEY
-x005d001f PR_ORIGINAL_SENT_REPRESENTING_NAME
-x005e0102 PR_ORIGINAL_SENT_REPRESENTING_ENTRYID
-x005f0102 PR_ORIGINAL_SENT_REPRESENTING_SEARCH_KEY
-x00600040 PR_START_DATE
-x00610040 PR_END_DATE
-x00620003 PR_OWNER_APPT_ID
-x0063000b PR_RESPONSE_REQUESTED
-x0064001f PR_SENT_REPRESENTING_ADDRTYPE
-x0065001f PR_SENT_REPRESENTING_EMAIL_ADDRESS
-x0066001f PR_ORIGINAL_SENDER_ADDRTYPE
-x0067001f PR_ORIGINAL_SENDER_EMAIL_ADDRESS
-x0068001f PR_ORIGINAL_SENT_REPRESENTING_ADDRTYPE
-x0069001f PR_ORIGINAL_SENT_REPRESENTING_EMAIL_ADDRESS
-x0070001f PR_CONVERSATION_TOPIC
-x00710102 PR_CONVERSATION_INDEX
-x0072001f PR_ORIGINAL_DISPLAY_BCC
-x0073001f PR_ORIGINAL_DISPLAY_CC
-x0074001f PR_ORIGINAL_DISPLAY_TO
-x0075001f PR_RECEIVED_BY_ADDRTYPE
-x0076001f PR_RECEIVED_BY_EMAIL_ADDRESS
-x0077001f PR_RCVD_REPRESENTING_ADDRTYPE
-x0078001f PR_RCVD_REPRESENTING_EMAIL_ADDRESS
-x0079001f PR_ORIGINAL_AUTHOR_ADDRTYPE
-x007a001f PR_ORIGINAL_AUTHOR_EMAIL_ADDRESS
-x007b001f PR_ORIGINALLY_INTENDED_RECIP_ADDRTYPE
-x007c001f PR_ORIGINALLY_INTENDED_RECIP_EMAIL_ADDRESS
-x007d001f PR_TRANSPORT_MESSAGE_HEADERS
-x007e0102 PR_DELEGATION
-x007f0102 PR_TNEF_CORRELATION_KEY
-x0c000102 PR_CONTENT_INTEGRITY_CHECK
-x0c010003 PR_EXPLICIT_CONVERSION
-x0c02000b PR_IPM_RETURN_REQUESTED
-x0c030102 PR_MESSAGE_TOKEN
-x0c040003 PR_NDR_REASON_CODE
-x0c050003 PR_NDR_DIAG_CODE
-x0c06000b PR_NON_RECEIPT_NOTIFICATION_REQUESTED
-x0c070003 PR_DELIVERY_POINT
-x0c08000b PR_ORIGINATOR_NON_DELIVERY_REPORT_REQUESTED
-x0c090102 PR_ORIGINATOR_REQUESTED_ALTERNATE_RECIPIENT
-x0c0a000b PR_PHYSICAL_DELIVERY_BUREAU_FAX_DELIVERY
-x0c0b0003 PR_PHYSICAL_DELIVERY_MODE
-x0c0c0003 PR_PHYSICAL_DELIVERY_REPORT_REQUEST
-x0c0d0102 PR_PHYSICAL_FORWARDING_ADDRESS
-x0c0e000b PR_PHYSICAL_FORWARDING_ADDRESS_REQUESTED
-x0c0f000b PR_PHYSICAL_FORWARDING_PROHIBITED
-x0c100102 PR_PHYSICAL_RENDITION_ATTRIBUTES
-x0c110102 PR_PROOF_OF_DELIVERY
-x0c12000b PR_PROOF_OF_DELIVERY_REQUESTED
-x0c130102 PR_RECIPIENT_CERTIFICATE
-x0c14001f PR_RECIPIENT_NUMBER_FOR_ADVICE
-x0c150003 PR_RECIPIENT_TYPE
-x0c160003 PR_REGISTERED_MAIL_TYPE
-x0c17000b PR_REPLY_REQUESTED
-x0c180003 PR_REQUESTED_DELIVERY_METHOD
-x0c190102 PR_SENDER_ENTRYID
-x0c1a001f PR_SENDER_NAME
-x0c1b001f PR_SUPPLEMENTARY_INFO
-x0c1c0003 PR_TYPE_OF_MTS_USER
-x0c1d0102 PR_SENDER_SEARCH_KEY
-x0c1e001f PR_SENDER_ADDRTYPE
-x0c1f001f PR_SENDER_EMAIL_ADDRESS
-x0e000014 PR_CURRENT_VERSION
-x0e01000b PR_DELETE_AFTER_SUBMIT
-x0e02001f PR_DISPLAY_BCC
-x0e03001f PR_DISPLAY_CC
-x0e04001f PR_DISPLAY_TO
-x0e05001f PR_PARENT_DISPLAY
-x0e060040 PR_MESSAGE_DELIVERY_TIME
-x0e070003 PR_MESSAGE_FLAGS
-x0e080003 PR_MESSAGE_SIZE
-x0e080014 PR_MESSAGE_SIZE_EXTENDED
-x0e090102 PR_PARENT_ENTRYID
-x0e0a0102 PR_SENTMAIL_ENTRYID
-x0e0c000b PR_CORRELATE
-x0e0d0102 PR_CORRELATE_MTSID
-x0e0e000b PR_DISCRETE_VALUES
-x0e0f000b PR_RESPONSIBILITY
-x0e100003 PR_SPOOLER_STATUS
-x0e110003 PR_TRANSPORT_STATUS
-x0e12000d PR_MESSAGE_RECIPIENTS
-x0e13000d PR_MESSAGE_ATTACHMENTS
-x0e140003 PR_SUBMIT_FLAGS
-x0e150003 PR_RECIPIENT_STATUS
-x0e160003 PR_TRANSPORT_KEY
-x0e170003 PR_MSG_STATUS
-x0e180003 PR_MESSAGE_DOWNLOAD_TIME
-x0e190014 PR_CREATION_VERSION
-x0e1a0014 PR_MODIFY_VERSION
-x0e1b000b PR_HASATTACH
-x0e1c0003 PR_BODY_CRC
-x0e1d001f PR_NORMALIZED_SUBJECT
-x0e1f000b PR_RTF_IN_SYNC
-x0e200003 PR_ATTACH_SIZE
-x0e210003 PR_ATTACH_NUM
-x0e22000b PR_PREPROCESS
-x0e230003 PR_INTERNET_ARTICLE_NUMBER
-x0e24001f PR_NEWSGROUP_NAME
-x0e250102 PR_ORIGINATING_MTA_CERTIFICATE
-x0e260102 PR_PROOF_OF_SUBMISSION
-x0e270102 PR_NT_SECURITY_DESCRIPTOR
-x0e580102 PR_CREATOR_SID
-x0e590102 PR_LAST_MODIFIER_SID
-x0e5e0048 PR_MIME_HANDLER_CLASSIDS
-x0e610003 PR_URL_COMP_NAME_POSTFIX
-x0e62000b PR_URL_COMP_NAME_SET
-x0e630003 PR_SUBFOLDER_CT
-x0e640003 PR_DELETED_SUBFOLDER_CT
-x0e660040 PR_DELETE_TIME
-x0e670102 PR_AGE_LIMIT
-x0e790003 PR_TRUST_SENDER
-x0e960102 PR_ATTACH_VIRUS_SCAN_INFO
-x0ff40003 PR_ACCESS
-x0ff50003 PR_ROW_TYPE
-x0ff60102 PR_INSTANCE_KEY
-x0ff70003 PR_ACCESS_LEVEL
-x0ff80102 PR_MAPPING_SIGNATURE
-x0ff90102 PR_RECORD_KEY
-x0ffa0102 PR_STORE_RECORD_KEY
-x0ffb0102 PR_STORE_ENTRYID
-x0ffc0102 PR_MINI_ICON
-x0ffd0102 PR_ICON
-x0ffe0003 PR_OBJECT_TYPE
-x0fff0102 PR_ENTRYID
-x0fff0102 PR_MEMBER_ENTRYID
-x1000001f PR_BODY
-x1001001f PR_REPORT_TEXT
-x10020102 PR_ORIGINATOR_AND_DL_EXPANSION_HISTORY
-x10030102 PR_REPORTING_DL_NAME
-x10040102 PR_REPORTING_MTA_CERTIFICATE
-x10060003 PR_RTF_SYNC_BODY_CRC
-x10070003 PR_RTF_SYNC_BODY_COUNT
-x1008001f PR_RTF_SYNC_BODY_TAG
-x10090102 PR_RTF_COMPRESSED
-x10100003 PR_RTF_SYNC_PREFIX_COUNT
-x10110003 PR_RTF_SYNC_TRAILING_COUNT
-x10120102 PR_ORIGINALLY_INTENDED_RECIP_ENTRYID
-x10130102 PR_HTML
-x1030001f PR_INTERNET_APPROVED
-x1031001f PR_INTERNET_CONTROL
-x1032001f PR_INTERNET_DISTRIBUTION
-x1033001f PR_INTERNET_FOLLOWUP_TO
-x10340003 PR_INTERNET_LINES
-x1035001f PR_INTERNET_MESSAGE_ID
-x1036001f PR_INTERNET_NEWSGROUPS
-x1037001f PR_INTERNET_ORGANIZATION
-x1038001f PR_INTERNET_NNTP_PATH
-x1039001f PR_INTERNET_REFERENCES
-x103a001f PR_SUPERSEDES
-x103b0102 PR_POST_FOLDER_ENTRIES
-x103c001f PR_POST_FOLDER_NAMES
-x103d0102 PR_POST_REPLY_FOLDER_ENTRIES
-x103e001f PR_POST_REPLY_FOLDER_NAMES
-x103f0102 PR_POST_REPLY_DENIED
-x1040001f PR_NNTP_XREF
-x1041001f PR_INTERNET_PRECEDENCE
-x1042001f PR_IN_REPLY_TO_ID
-x1043001f PR_LIST_HELP
-x1044001f PR_LIST_SUBSCRIBE
-x1045001f PR_LIST_UNSUBSCRIBE
-x10800003 PR_ACTION
-x10810003 PR_ACTION_FLAG
-x10820040 PR_ACTION_DATE
-x10900003 PR_FLAG_STATUS
-x10910040 PR_FLAG_COMPLETE
-x10c00102 PR_SMTP_TEMP_TBL_DATA
-x10c10003 PR_SMTP_TEMP_TBL_DATA_2
-x10c20102 PR_SMTP_TEMP_TBL_DATA_3
-x10c30040 PR_CAL_START_TIME
-x10c40040 PR_CAL_END_TIME
-x10c50040 PR_CAL_RECURRING_ID
-x10c6001f PR_DAV_SUBMIT_DATA
-x10c70003 PR_CDO_EXPANSION_INDEX
-x10c80102 PR_IFS_INTERNAL_DATA
-x10ca0040 PR_CAL_REMINDER_NEXT_TIME
-x10f1001f PR_OWA_URL
-x10f2000b PR_DISABLE_FULL_FIDELITY
-x10f3001f PR_URL_COMP_NAME
-x10f4000b PR_ATTR_HIDDEN
-x10f5000b PR_ATTR_SYSTEM
-x10f6000b PR_ATTR_READONLY
-x11000102 PR_P1_CONTENT
-x11010102 PR_P1_CONTENT_TYPE
-x30000003 PR_ROWID
-x3001001f PR_DISPLAY_NAME
-x3002001f PR_ADDRTYPE
-x3003001f PR_EMAIL_ADDRESS
-x3004001f PR_COMMENT
-x30050003 PR_DEPTH
-x3006001f PR_PROVIDER_DISPLAY
-x30070040 PR_CREATION_TIME
-x30080040 PR_LAST_MODIFICATION_TIME
-x30090003 PR_RESOURCE_FLAGS
-x300a001f PR_PROVIDER_DLL_NAME
-x300b0102 PR_SEARCH_KEY
-x300c0102 PR_PROVIDER_UID
-x300d0003 PR_PROVIDER_ORDINAL
-x3301001f PR_FORM_VERSION
-x33020048 PR_FORM_CLSID
-x3303001f PR_FORM_CONTACT_NAME
-x3304001f PR_FORM_CATEGORY
-x3305001f PR_FORM_CATEGORY_SUB
-x33061003 PR_FORM_HOST_MAP
-x3307000b PR_FORM_HIDDEN
-x3308001f PR_FORM_DESIGNER_NAME
-x33090048 PR_FORM_DESIGNER_GUID
-x330a0003 PR_FORM_MESSAGE_BEHAVIOR
-x3400000b PR_DEFAULT_STORE
-x340d0003 PR_STORE_SUPPORT_MASK
-x340e0003 PR_STORE_STATE
-x34100102 PR_IPM_SUBTREE_SEARCH_KEY
-x34110102 PR_IPM_OUTBOX_SEARCH_KEY
-x34120102 PR_IPM_WASTEBASKET_SEARCH_KEY
-x34130102 PR_IPM_SENTMAIL_SEARCH_KEY
-x34140102 PR_MDB_PROVIDER
-x3415000d PR_RECEIVE_FOLDER_SETTINGS
-x35df0003 PR_VALID_FOLDER_MASK
-x35e00102 PR_IPM_SUBTREE_ENTRYID
-x35e20102 PR_IPM_OUTBOX_ENTRYID
-x35e30102 PR_IPM_WASTEBASKET_ENTRYID
-x35e40102 PR_IPM_SENTMAIL_ENTRYID
-x35e50102 PR_VIEWS_ENTRYID
-x35e60102 PR_COMMON_VIEWS_ENTRYID
-x35e70102 PR_FINDER_ENTRYID
-x36000003 PR_CONTAINER_FLAGS
-x36010003 PR_FOLDER_TYPE
-x36020003 PR_CONTENT_COUNT
-x36030003 PR_CONTENT_UNREAD
-x3604000d PR_CREATE_TEMPLATES
-x3605000d PR_DETAILS_TABLE
-x3607000d PR_SEARCH
-x3609000b PR_SELECTABLE
-x360a000b PR_SUBFOLDERS
-x360b0003 PR_STATUS
-x360c001f PR_ANR
-x360d1003 PR_CONTENTS_SORT_ORDER
-x360e000d PR_CONTAINER_HIERARCHY
-x360f000d PR_CONTAINER_CONTENTS
-x3610000d PR_FOLDER_ASSOCIATED_CONTENTS
-x36110102 PR_DEF_CREATE_DL
-x36120102 PR_DEF_CREATE_MAILUSER
-x3613001f PR_CONTAINER_CLASS
-x36140014 PR_CONTAINER_MODIFY_VERSION
-x36150102 PR_AB_PROVIDER_ID
-x36160102 PR_DEFAULT_VIEW_ENTRYID
-x36170003 PR_ASSOC_CONTENT_COUNT
-x361c0102 PR_PACKED_NAME_PROPS
-x36d00102 PR_IPM_APPOINTMENT_ENTRYID
-x36d10102 PR_IPM_CONTACT_ENTRYID
-x36d20102 PR_IPM_JOURNAL_ENTRYID
-x36d30102 PR_IPM_NOTE_ENTRYID
-x36d40102 PR_IPM_TASK_ENTRYID
-x36d50102 PR_REMINDERS_ONLINE_ENTRYID
-x36d60102 PR_REMINDERS_OFFLINE_ENTRYID
-x36d70102 PR_IPM_DRAFTS_ENTRYID
-x36d81102 PR_OUTLOOK_2003_ENTRYIDS
-x36df0102 PR_FOLDER_WEBVIEWINFO
-x36e00102 PR_FOLDER_XVIEWINFO_E
-x36e10003 PR_FOLDER_VIEWS_ONLY
-x36e41102 PR_FREEBUSY_ENTRYIDS
-x36e5001f PR_DEF_MSG_CLASS
-x36e6001f PR_DEF_FORM_NAME
-x36e9000b PR_GENERATE_EXCHANGE_VIEWS
-x36ec0003 PR_AGING_PERIOD
-x36ee0003 PR_AGING_GRANULARITY
-x37000102 PR_ATTACHMENT_X400_PARAMETERS
-x3701000d PR_ATTACH_DATA_OBJ
-x37010102 PR_ATTACH_DATA_BIN
-x37020102 PR_ATTACH_ENCODING
-x3703001f PR_ATTACH_EXTENSION
-x3704001f PR_ATTACH_FILENAME
-x37050003 PR_ATTACH_METHOD
-x3707001f PR_ATTACH_LONG_FILENAME
-x3708001f PR_ATTACH_PATHNAME
-x37090102 PR_ATTACH_RENDERING
-x370a0102 PR_ATTACH_TAG
-x370b0003 PR_RENDERING_POSITION
-x370c001f PR_ATTACH_TRANSPORT_NAME
-x370d001f PR_ATTACH_LONG_PATHNAME
-x370e001f PR_ATTACH_MIME_TAG
-x370f0102 PR_ATTACH_ADDITIONAL_INFO
-x3712001f PR_ATTACH_CONTENT_ID
-x3713001f PR_ATTACH_CONTENT_LOCATION
-x37140003 PR_ATTACH_FLAGS
-x3716001f PR_ATTACH_CONTENT_DISPOSITION
-x38800102 PR_SYNCEVENT_SUPPRESS_GUID
-x39000003 PR_DISPLAY_TYPE
-x39020102 PR_TEMPLATEID
-x39040102 PR_PRIMARY_CAPABILITY
-x39fe001f PR_SMTP_ADDRESS
-x39ff001f PR_7BIT_DISPLAY_NAME
-x39ff001f PR_EMS_AB_DISPLAY_NAME_PRINTABLE
-x3a00001f PR_ACCOUNT
-x3a010102 PR_ALTERNATE_RECIPIENT
-x3a02001f PR_CALLBACK_TELEPHONE_NUMBER
-x3a03000b PR_CONVERSION_PROHIBITED
-x3a04000b PR_DISCLOSE_RECIPIENTS
-x3a05001f PR_GENERATION
-x3a06001f PR_GIVEN_NAME
-x3a07001f PR_GOVERNMENT_ID_NUMBER
-x3a08001f PR_BUSINESS_TELEPHONE_NUMBER
-x3a08001f PR_OFFICE_TELEPHONE_NUMBER
-x3a09001f PR_HOME_TELEPHONE_NUMBER
-x3a0a001f PR_INITIALS
-x3a0b001f PR_KEYWORD
-x3a0c001f PR_LANGUAGE
-x3a0d001f PR_LOCATION
-x3a0e000b PR_MAIL_PERMISSION
-x3a0f001f PR_MHS_COMMON_NAME
-x3a10001f PR_ORGANIZATIONAL_ID_NUMBER
-x3a11001f PR_SURNAME
-x3a120102 PR_ORIGINAL_ENTRYID
-x3a13001f PR_ORIGINAL_DISPLAY_NAME
-x3a140102 PR_ORIGINAL_SEARCH_KEY
-x3a15001f PR_POSTAL_ADDRESS
-x3a16001f PR_COMPANY_NAME
-x3a17001f PR_TITLE
-x3a18001f PR_DEPARTMENT_NAME
-x3a19001f PR_OFFICE_LOCATION
-x3a1a001f PR_PRIMARY_TELEPHONE_NUMBER
-x3a1b001f PR_BUSINESS2_TELEPHONE_NUMBER
-x3a1b001f PR_OFFICE2_TELEPHONE_NUMBER
-x3a1c001f PR_CELLULAR_TELEPHONE_NUMBER
-x3a1c001f PR_MOBILE_TELEPHONE_NUMBER
-x3a1d001f PR_RADIO_TELEPHONE_NUMBER
-x3a1e001f PR_CAR_TELEPHONE_NUMBER
-x3a1f001f PR_OTHER_TELEPHONE_NUMBER
-x3a20001f PR_TRANSMITTABLE_DISPLAY_NAME
-x3a21001f PR_BEEPER_TELEPHONE_NUMBER
-x3a21001f PR_PAGER_TELEPHONE_NUMBER
-x3a220102 PR_USER_CERTIFICATE
-x3a23001f PR_PRIMARY_FAX_NUMBER
-x3a24001f PR_BUSINESS_FAX_NUMBER
-x3a25001f PR_HOME_FAX_NUMBER
-x3a26001f PR_BUSINESS_ADDRESS_COUNTRY
-x3a26001f PR_COUNTRY
-x3a27001f PR_BUSINESS_ADDRESS_CITY
-x3a27001f PR_LOCALITY
-x3a28001f PR_BUSINESS_ADDRESS_STATE_OR_PROVINCE
-x3a28001f PR_STATE_OR_PROVINCE
-x3a29001f PR_BUSINESS_ADDRESS_STREET
-x3a29001f PR_STREET_ADDRESS
-x3a2a001f PR_BUSINESS_ADDRESS_POSTAL_CODE
-x3a2a001f PR_POSTAL_CODE
-x3a2b001f PR_BUSINESS_ADDRESS_POST_OFFICE_BOX
-x3a2b001f PR_POST_OFFICE_BOX
-x3a2c001f PR_TELEX_NUMBER
-x3a2d001f PR_ISDN_NUMBER
-x3a2e001f PR_ASSISTANT_TELEPHONE_NUMBER
-x3a2f001f PR_HOME2_TELEPHONE_NUMBER
-x3a30001f PR_ASSISTANT
-x3a40000b PR_SEND_RICH_INFO
-x3a410040 PR_WEDDING_ANNIVERSARY
-x3a420040 PR_BIRTHDAY
-x3a43001f PR_HOBBIES
-x3a44001f PR_MIDDLE_NAME
-x3a45001f PR_DISPLAY_NAME_PREFIX
-x3a46001f PR_PROFESSION
-x3a47001f PR_PREFERRED_BY_NAME
-x3a47001f PR_REFERRED_BY_NAME
-x3a48001f PR_SPOUSE_NAME
-x3a49001f PR_COMPUTER_NETWORK_NAME
-x3a4a001f PR_CUSTOMER_ID
-x3a4b001f PR_TTYTDD_PHONE_NUMBER
-x3a4c001f PR_FTP_SITE
-x3a4d0002 PR_GENDER
-x3a4e001f PR_MANAGER_NAME
-x3a4f001f PR_NICKNAME
-x3a50001f PR_PERSONAL_HOME_PAGE
-x3a51001f PR_BUSINESS_HOME_PAGE
-x3a520048 PR_CONTACT_VERSION
-x3a531102 PR_CONTACT_ENTRYIDS
-x3a54101f PR_CONTACT_ADDRTYPES
-x3a550003 PR_CONTACT_DEFAULT_ADDRESS_INDEX
-x3a56101f PR_CONTACT_EMAIL_ADDRESSES
-x3a57001f PR_COMPANY_MAIN_PHONE_NUMBER
-x3a58101f PR_CHILDRENS_NAMES
-x3a59001f PR_HOME_ADDRESS_CITY
-x3a5a001f PR_HOME_ADDRESS_COUNTRY
-x3a5b001f PR_HOME_ADDRESS_POSTAL_CODE
-x3a5c001f PR_HOME_ADDRESS_STATE_OR_PROVINCE
-x3a5d001f PR_HOME_ADDRESS_STREET
-x3a5e001f PR_HOME_ADDRESS_POST_OFFICE_BOX
-x3a5f001f PR_OTHER_ADDRESS_CITY
-x3a60001f PR_OTHER_ADDRESS_COUNTRY
-x3a61001f PR_OTHER_ADDRESS_POSTAL_CODE
-x3a62001f PR_OTHER_ADDRESS_STATE_OR_PROVINCE
-x3a63001f PR_OTHER_ADDRESS_STREET
-x3a64001f PR_OTHER_ADDRESS_POST_OFFICE_BOX
-x3a701102 PR_USER_X509_CERTIFICATE
-x3a710003 PR_SEND_INTERNET_ENCODING
-x3d000102 PR_STORE_PROVIDERS
-x3d010102 PR_AB_PROVIDERS
-x3d020102 PR_TRANSPORT_PROVIDERS
-x3d04000b PR_DEFAULT_PROFILE
-x3d051102 PR_AB_SEARCH_PATH
-x3d060102 PR_AB_DEFAULT_DIR
-x3d070102 PR_AB_DEFAULT_PAB
-x3d080102 PR_FILTERING_HOOKS
-x3d09001f PR_SERVICE_NAME
-x3d0a001f PR_SERVICE_DLL_NAME
-x3d0b001f PR_SERVICE_ENTRY_NAME
-x3d0c0102 PR_SERVICE_UID
-x3d0d0102 PR_SERVICE_EXTRA_UIDS
-x3d0e0102 PR_SERVICES
-x3d0f101f PR_SERVICE_SUPPORT_FILES
-x3d10101f PR_SERVICE_DELETE_FILES
-x3d110102 PR_AB_SEARCH_PATH_UPDATE
-x3d12001f PR_PROFILE_NAME
-x3d210102 PR_ADMIN_SECURITY_DESCRIPTOR
-x3e00001f PR_IDENTITY_DISPLAY
-x3e010102 PR_IDENTITY_ENTRYID
-x3e020003 PR_RESOURCE_METHODS
-x3e030003 PR_RESOURCE_TYPE
-x3e040003 PR_STATUS_CODE
-x3e050102 PR_IDENTITY_SEARCH_KEY
-x3e060102 PR_OWN_STORE_ENTRYID
-x3e07001f PR_RESOURCE_PATH
-x3e08001f PR_STATUS_STRING
-x3e09000b PR_X400_DEFERRED_DELIVERY_CANCEL
-x3e0a0102 PR_HEADER_FOLDER_ENTRYID
-x3e0b0003 PR_REMOTE_PROGRESS
-x3e0c001f PR_REMOTE_PROGRESS_TEXT
-x3e0d000b PR_REMOTE_VALIDATE_OK
-x3f000003 PR_CONTROL_FLAGS
-x3f010102 PR_CONTROL_STRUCTURE
-x3f020003 PR_CONTROL_TYPE
-x3f030003 PR_DELTAX
-x3f040003 PR_DELTAY
-x3f050003 PR_XPOS
-x3f060003 PR_YPOS
-x3f070102 PR_CONTROL_ID
-x3f080003 PR_INITIAL_DETAILS_PANE
-x3f800014 PR_DID
-x3f810014 PR_SEQID
-x3f820014 PR_DRAFTID
-x3f830040 PR_CHECK_IN_TIME
-x3f84001f PR_CHECK_IN_COMMENT
-x3f850003 PR_VERSION_OP_CODE
-x3f860102 PR_VERSION_OP_DATA
-x3f870003 PR_VERSION_SEQUENCE_NUMBER
-x3f880014 PR_ATTACH_ID
-x3f8d001f PR_PKM_DOC_STATUS
-x3f8e101f PR_MV_PKM_OPERATION_REQ
-x3f8f001f PR_PKM_DOC_INTERNAL_STATE
-x3f900002 PR_VERSIONING_FLAGS
-x3f910102 PR_PKM_LAST_UNAPPROVED_VID
-x3f92101f PR_MV_PKM_VERSION_LABELS
-x3f93101f PR_MV_PKM_VERSION_STATUS
-x3f940102 PR_PKM_INTERNAL_DATA
-x3fc90102 PR_LAST_CONFLICT
-x3fca0102 PR_CONFLICT_MSG_KEY
-x3fd00102 PR_REPL_HEADER
-x3fd10102 PR_REPL_STATUS
-x3fd20102 PR_REPL_CHANGES
-x3fd30102 PR_REPL_RGM
-x3fd40102 PR_RMI
-x3fd50102 PR_INTERNAL_POST_REPLY
-x3fd60040 PR_NTSD_MODIFICATION_TIME
-x3fd8001f PR_PREVIEW_UNREAD
-x3fd9001f PR_PREVIEW
-x3fda001f PR_ABSTRACT
-x3fdb0003 PR_DL_REPORT_FLAGS
-x3fdc0102 PR_BILATERAL_INFO
-x3fdd0003 PR_MSG_BODY_ID
-x3fde0003 PR_INTERNET_CPID
-x3fdf0003 PR_AUTO_RESPONSE_SUPPRESS
-x3fe0000d PR_ACL_TABLE
-x3fe00102 PR_ACL_DATA
-x3fe1000d PR_RULES_TABLE
-x3fe10102 PR_RULES_DATA
-x3fe20003 PR_FOLDER_DESIGN_FLAGS
-x3fe3000b PR_DELEGATED_BY_RULE
-x3fe4000b PR_DESIGN_IN_PROGRESS
-x3fe5000b PR_SECURE_ORIGINATION
-x3fe6000b PR_PUBLISH_IN_ADDRESS_BOOK
-x3fe70003 PR_RESOLVE_METHOD
-x3fe8001f PR_ADDRESS_BOOK_DISPLAY_NAME
-x3fe90003 PR_EFORMS_LOCALE_ID
-x3fea000b PR_HAS_DAMS
-x3feb0003 PR_DEFERRED_SEND_NUMBER
-x3fec0003 PR_DEFERRED_SEND_UNITS
-x3fed0003 PR_EXPIRY_NUMBER
-x3fee0003 PR_EXPIRY_UNITS
-x3fef0040 PR_DEFERRED_SEND_TIME
-x3ff00102 PR_CONFLICT_ENTRYID
-x3ff10003 PR_MESSAGE_LOCALE_ID
-x3ff20102 PR_RULE_TRIGGER_HISTORY
-x3ff30102 PR_MOVE_TO_STORE_ENTRYID
-x3ff40102 PR_MOVE_TO_FOLDER_ENTRYID
-x3ff50003 PR_STORAGE_QUOTA_LIMIT
-x3ff60003 PR_EXCESS_STORAGE_USED
-x3ff7001f PR_SVR_GENERATING_QUOTA_MSG
-x3ff8001f PR_CREATOR_NAME
-x3ff90102 PR_CREATOR_ENTRYID
-x3ffa001f PR_LAST_MODIFIER_NAME
-x3ffb0102 PR_LAST_MODIFIER_ENTRYID
-x3ffc001f PR_REPLY_RECIPIENT_SMTP_PROXIES
-x3ffd0003 PR_MESSAGE_CODEPAGE
-x3ffe0102 PR_EXTENDED_ACL_DATA
-x3fff000b PR_FROM_I_HAVE
-x40000003 PR_NEW_ATTACH
-x40010003 PR_START_EMBED
-x40020003 PR_END_EMBED
-x40030003 PR_START_RECIP
-x40040003 PR_END_RECIP
-x40050003 PR_END_CC_RECIP
-x40060003 PR_END_BCC_RECIP
-x40070003 PR_END_P1_RECIP
-x40090003 PR_START_TOP_FLD
-x400a0003 PR_START_SUB_FLD
-x400b0003 PR_END_FOLDER
-x400c0003 PR_START_MESSAGE
-x400d0003 PR_END_MESSAGE
-x400e0003 PR_END_ATTACH
-x400f0003 PR_EC_WARNING
-x40100003 PR_START_FAI_MSG
-x40110102 PR_NEW_FX_FOLDER
-x40120003 PR_INCR_SYNC_CHG
-x40130003 PR_INCR_SYNC_DEL
-x40140003 PR_INCR_SYNC_END
-x40150003 PR_INCR_SYNC_MSG
-x40160003 PR_FX_DEL_PROP
-x40170003 PR_IDSET_GIVEN
-x40190003 PR_SENDER_FLAGS
-x401a0003 PR_SENT_REPRESENTING_FLAGS
-x401b0003 PR_RCVD_BY_FLAGS
-x401c0003 PR_RCVD_REPRESENTING_FLAGS
-x401d0003 PR_ORIGINAL_SENDER_FLAGS
-x401e0003 PR_ORIGINAL_SENT_REPRESENTING_FLAGS
-x401f0003 PR_REPORT_FLAGS
-x40200003 PR_READ_RECEIPT_FLAGS
-x4021000b PR_SOFT_DELETES
-x402c0102 PR_MESSAGE_SUBMISSION_ID_FROM_CLIENT
-x4030001f PR_SENDER_SIMPLE_DISP_NAME
-x4031001f PR_SENT_REPRESENTING_SIMPLE_DISP_NAME
-x4038001f PR_CREATOR_SIMPLE_DISP_NAME
-x403d001f PR_ORG_ADDR_TYPE
-x403e001f PR_ORG_EMAIL_ADDR
-x40590003 PR_CREATOR_FLAGS
-x405a0003 PR_MODIFIER_FLAGS
-x405b0003 PR_ORIGINATOR_FLAGS
-x405c0003 PR_REPORT_DESTINATION_FLAGS
-x405d0003 PR_ORIGINAL_AUTHOR_FLAGS
-x40610102 PR_ORIGINATOR_SEARCH_KEY
-x40640102 PR_REPORT_DESTINATION_SEARCH_KEY
-x40650003 PR_ER_FLAG
-x40680102 PR_INTERNET_SUBJECT
-x40690102 PR_INTERNET_SENT_REPRESENTING_NAME
-x59020003 PR_INET_MAIL_OVERRIDE_FORMAT
-x59090003 PR_MSG_EDITOR_FORMAT
-x60010003 PR_DOTSTUFF_STATE
-x65a00014 PR_RULE_SERVER_RULE_ID
-x65c20102 PR_REPLY_TEMPLATE_ID
-x65e00102 PR_SOURCE_KEY
-x65e10102 PR_PARENT_SOURCE_KEY
-x65e20102 PR_CHANGE_KEY
-x65e30102 PR_PREDECESSOR_CHANGE_LIST
-x65e40003 PR_SYNCHRONIZE_FLAGS
-x65e5000b PR_AUTO_ADD_NEW_SUBS
-x65e6000b PR_NEW_SUBS_GET_AUTO_ADD
-x65e7001f PR_MESSAGE_SITE_NAME
-x65e8000b PR_MESSAGE_PROCESSED
-x65e90003 PR_RULE_MSG_STATE
-x65ea0003 PR_RULE_MSG_USER_FLAGS
-x65eb001f PR_RULE_MSG_PROVIDER
-x65ec001f PR_RULE_MSG_NAME
-x65ed0003 PR_RULE_MSG_LEVEL
-x65ee0102 PR_RULE_MSG_PROVIDER_DATA
-x65ef0102 PR_RULE_MSG_ACTIONS
-x65f00102 PR_RULE_MSG_CONDITION
-x65f10003 PR_RULE_MSG_CONDITION_LCID
-x65f20002 PR_RULE_MSG_VERSION
-x65f30003 PR_RULE_MSG_SEQUENCE
-x65f4000b PR_PREVENT_MSG_CREATE
-x65f50040 PR_IMAP_INTERNAL_DATE
-x66000003 PR_PROFILE_VERSION
-x66010003 PR_PROFILE_CONFIG_FLAGS
-x6602001f PR_PROFILE_HOME_SERVER
-x6603001f PR_PROFILE_USER
-x66040003 PR_PROFILE_CONNECT_FLAGS
-x66050003 PR_PROFILE_TRANSPORT_FLAGS
-x66060003 PR_PROFILE_UI_STATE
-x6607001f PR_PROFILE_UNRESOLVED_NAME
-x6608001f PR_PROFILE_UNRESOLVED_SERVER
-x66090003 PR_PROFILE_OPEN_FLAGS
-x6609001f PR_PROFILE_BINDING_ORDER
-x660a0003 PR_PROFILE_TYPE
-x660b001f PR_PROFILE_MAILBOX
-x660c001f PR_PROFILE_SERVER
-x660d0003 PR_PROFILE_MAX_RESTRICT
-x660e001f PR_PROFILE_AB_FILES_PATH
-x660f001f PR_PROFILE_FAVFLD_DISPLAY_NAME
-x6610001f PR_PROFILE_OFFLINE_STORE_PATH
-x66110102 PR_PROFILE_OFFLINE_INFO
-x6612001f PR_PROFILE_HOME_SERVER_DN
-x6613101f PR_PROFILE_HOME_SERVER_ADDRS
-x6614001f PR_PROFILE_SERVER_DN
-x6615001f PR_PROFILE_FAVFLD_COMMENT
-x6616001f PR_PROFILE_ALLPUB_DISPLAY_NAME
-x6617001f PR_PROFILE_ALLPUB_COMMENT
-x66180003 PR_DISABLE_WINSOCK
-x6618000b PR_IN_TRANSIT
-x66190003 PR_PROFILE_AUTH_PACKAGE
-x66190102 PR_USER_ENTRYID
-x661a001f PR_USER_NAME
-x661b0102 PR_MAILBOX_OWNER_ENTRYID
-x661c001f PR_MAILBOX_OWNER_NAME
-x661d000b PR_OOF_STATE
-x661e0102 PR_SCHEDULE_FOLDER_ENTRYID
-x661f0102 PR_IPM_DAF_ENTRYID
-x66200102 PR_NON_IPM_SUBTREE_ENTRYID
-x66210102 PR_EFORMS_REGISTRY_ENTRYID
-x66220102 PR_SPLUS_FREE_BUSY_ENTRYID
-x6623001f PR_HIERARCHY_SERVER
-x66230102 PR_OFFLINE_ADDRBOOK_ENTRYID
-x66240102 PR_EFORMS_FOR_LOCALE_ENTRYID
-x66250102 PR_FREE_BUSY_FOR_LOCAL_SITE_ENTRYID
-x66260102 PR_ADDRBOOK_FOR_LOCAL_SITE_ENTRYID
-x66270102 PR_OFFLINE_MESSAGE_ENTRYID
-x66280102 PR_GW_MTSIN_ENTRYID
-x66290102 PR_GW_MTSOUT_ENTRYID
-x662a000b PR_TRANSFER_ENABLED
-x662b0102 PR_TEST_LINE_SPEED
-x662c000d PR_HIERARCHY_SYNCHRONIZER
-x662d000d PR_CONTENTS_SYNCHRONIZER
-x662e000d PR_COLLECTOR
-x662f000d PR_FAST_TRANSFER
-x66300102 PR_IPM_FAVORITES_ENTRYID
-x66310102 PR_IPM_PUBLIC_FOLDERS_ENTRYID
-x6632000b PR_STORE_OFFLINE
-x6634000d PR_CHANGE_ADVISOR
-x6635001f PR_FAVORITES_DEFAULT_NAME
-x66360102 PR_SYS_CONFIG_FOLDER_ENTRYID
-x66370048 PR_CHANGE_NOTIFICATION_GUID
-x66380003 PR_FOLDER_CHILD_COUNT
-x66390003 PR_RIGHTS
-x663a000b PR_HAS_RULES
-x663b0102 PR_ADDRESS_BOOK_ENTRYID
-x663c0102 PR_PUBLIC_FOLDER_ENTRYID
-x663d0003 PR_OFFLINE_FLAGS
-x663e0003 PR_HIERARCHY_CHANGE_NUM
-x663f000b PR_HAS_MODERATOR_RULES
-x66400003 PR_DELETED_MSG_COUNT
-x66410003 PR_DELETED_FOLDER_COUNT
-x66420040 PR_OLDEST_DELETED_ON
-x66430003 PR_DELETED_ASSOC_MSG_COUNT
-x6644001f PR_REPLICA_SERVER
-x66450102 PR_CLIENT_ACTIONS
-x66460102 PR_DAM_ORIGINAL_ENTRYID
-x6647000b PR_DAM_BACK_PATCHED
-x66480003 PR_RULE_ERROR
-x66490003 PR_RULE_ACTION_TYPE
-x664a000b PR_HAS_NAMED_PROPERTIES
-x664b0014 PR_REPLICA_VERSION
-x66500003 PR_RULE_ACTION_NUMBER
-x66510102 PR_RULE_FOLDER_ENTRYID
-x66520102 PR_ACTIVE_USER_ENTRYID
-x66530003 PR_X400_ENVELOPE_TYPE
-x66540040 PR_MSG_FOLD_TIME
-x66550102 PR_ICS_CHANGE_KEY
-x66580003 PR_GW_ADMIN_OPERATIONS
-x66590102 PR_INTERNET_CONTENT
-x665a000b PR_HAS_ATTACH_FROM_IMAIL
-x665b001f PR_ORIGINATOR_NAME
-x665c001f PR_ORIGINATOR_ADDR
-x665d001f PR_ORIGINATOR_ADDRTYPE
-x665e0102 PR_ORIGINATOR_ENTRYID
-x665f0040 PR_ARRIVAL_TIME
-x66600102 PR_TRACE_INFO
-x66610102 PR_SUBJECT_TRACE_INFO
-x66620003 PR_RECIPIENT_NUMBER
-x66630102 PR_MTS_SUBJECT_ID
-x6664001f PR_REPORT_DESTINATION_NAME
-x66650102 PR_REPORT_DESTINATION_ENTRYID
-x66660102 PR_CONTENT_SEARCH_KEY
-x66670102 PR_FOREIGN_ID
-x66680102 PR_FOREIGN_REPORT_ID
-x66690102 PR_FOREIGN_SUBJECT_ID
-x666a0102 PR_INTERNAL_TRACE_INFO
-x666a0102 PR_PROMOTE_PROP_ID_LIST
-x666c000b PR_IN_CONFLICT
-x66700102 PR_LONGTERM_ENTRYID_FROM_TABLE
-x66710014 PR_MEMBER_ID
-x6672001f PR_MEMBER_NAME
-x66730003 PR_MEMBER_RIGHTS
-x66740014 PR_RULE_ID
-x66750102 PR_RULE_IDS
-x66760003 PR_RULE_SEQUENCE
-x66770003 PR_RULE_STATE
-x66780003 PR_RULE_USER_FLAGS
-x667900fd PR_RULE_CONDITION
-x667b001f PR_PROFILE_MOAB
-x667c001f PR_PROFILE_MOAB_GUID
-x667d0003 PR_PROFILE_MOAB_SEQ
-x667f1102 PR_IMPLIED_RESTRICTIONS
-x668000fe PR_RULE_ACTIONS
-x6681001f PR_RULE_PROVIDER
-x6682001f PR_RULE_NAME
-x66830003 PR_RULE_LEVEL
-x66840102 PR_RULE_PROVIDER_DATA
-x66850040 PR_LAST_FULL_BACKUP
-x66870102 PR_PROFILE_ADDR_INFO
-x66890102 PR_PROFILE_OPTIONS_DATA
-x668a0102 PR_EVENTS_ROOT_FOLDER_ENTRYID
-x668a0102 PR_NNTP_ARTICLE_FOLDER_ENTRYID
-x668b0102 PR_NNTP_CONTROL_FOLDER_ENTRYID
-x668c0102 PR_NEWSGROUP_ROOT_FOLDER_ENTRYID
-x668d001f PR_INBOUND_NEWSFEED_DN
-x668e001f PR_OUTBOUND_NEWSFEED_DN
-x668f0040 PR_DELETED_ON
-x66900003 PR_REPLICATION_STYLE
-x66910102 PR_REPLICATION_SCHEDULE
-x66920003 PR_REPLICATION_MESSAGE_PRIORITY
-x66930003 PR_OVERALL_MSG_AGE_LIMIT
-x66940003 PR_REPLICATION_ALWAYS_INTERVAL
-x66950003 PR_REPLICATION_MSG_SIZE
-x6696000b PR_IS_NEWSGROUP_ANCHOR
-x6697000b PR_IS_NEWSGROUP
-x66980102 PR_REPLICA_LIST
-x66990003 PR_OVERALL_AGE_LIMIT
-x669a001f PR_INTERNET_CHARSET
-x669b0014 PR_DELETED_MESSAGE_SIZE_EXTENDED
-x669c0014 PR_DELETED_NORMAL_MESSAGE_SIZE_EXTENDED
-x669d0014 PR_DELETED_ASSOC_MESSAGE_SIZE_EXTENDED
-x669e000b PR_SECURE_IN_SITE
-x66a0001f PR_NT_USER_NAME
-x66a10003 PR_LOCALE_ID
-x66a20040 PR_LAST_LOGON_TIME
-x66a30040 PR_LAST_LOGOFF_TIME
-x66a40003 PR_STORAGE_LIMIT_INFORMATION
-x66a5001f PR_NEWSGROUP_COMPONENT
-x66a60102 PR_NEWSFEED_INFO
-x66a7001f PR_INTERNET_NEWSGROUP_NAME
-x66a80003 PR_FOLDER_FLAGS
-x66a90040 PR_LAST_ACCESS_TIME
-x66aa0003 PR_RESTRICTION_COUNT
-x66ab0003 PR_CATEG_COUNT
-x66ac0003 PR_CACHED_COLUMN_COUNT
-x66ad0003 PR_NORMAL_MSG_W_ATTACH_COUNT
-x66ae0003 PR_ASSOC_MSG_W_ATTACH_COUNT
-x66af0003 PR_RECIPIENT_ON_NORMAL_MSG_COUNT
-x66b00003 PR_RECIPIENT_ON_ASSOC_MSG_COUNT
-x66b10003 PR_ATTACH_ON_NORMAL_MSG_COUNT
-x66b20003 PR_ATTACH_ON_ASSOC_MSG_COUNT
-x66b30003 PR_NORMAL_MESSAGE_SIZE
-x66b30014 PR_NORMAL_MESSAGE_SIZE_EXTENDED
-x66b40003 PR_ASSOC_MESSAGE_SIZE
-x66b40014 PR_ASSOC_MESSAGE_SIZE_EXTENDED
-x66b5001f PR_FOLDER_PATHNAME
-x66b60003 PR_OWNER_COUNT
-x66b70003 PR_CONTACT_COUNT
-x66c30003 PR_CODE_PAGE_ID
-x66c40003 PR_RETENTION_AGE_LIMIT
-x66c5000b PR_DISABLE_PERUSER_READ
-x66c60102 PR_INTERNET_PARSE_STATE
-x66c70102 PR_INTERNET_MESSAGE_INFO
-x6700001f PR_PST_PATH
-x6701000b PR_PST_REMEMBER_PW
-x67020003 PR_OST_ENCRYPTION
-x67020003 PR_PST_ENCRYPTION
-x6703001f PR_PST_PW_SZ_OLD
-x6704001f PR_PST_PW_SZ_NEW
-x67050003 PR_SORT_LOCALE_ID
-x6707001f PR_URL_NAME
-x67090040 PR_LOCAL_COMMIT_TIME
-x670a0040 PR_LOCAL_COMMIT_TIME_MAX
-x670b0003 PR_DELETED_COUNT_TOTAL
-x670c0048 PR_AUTO_RESET
-x67100003 PR_URL_COMP_NAME_HASH
-x67110003 PR_MSG_FOLDER_TEMPLATE_RES_2
-x67120003 PR_RANK
-x6713000b PR_MSG_FOLDER_TEMPLATE_RES_4
-x6714000b PR_MSG_FOLDER_TEMPLATE_RES_5
-x6715000b PR_MSG_FOLDER_TEMPLATE_RES_6
-x67160102 PR_MSG_FOLDER_TEMPLATE_RES_7
-x67170102 PR_MSG_FOLDER_TEMPLATE_RES_8
-x67180102 PR_MSG_FOLDER_TEMPLATE_RES_9
-x6719001f PR_MSG_FOLDER_TEMPLATE_RES_10
-x671a001f PR_MSG_FOLDER_TEMPLATE_RES_11
-x671b001f PR_MSG_FOLDER_TEMPLATE_RES_12
-x671e000b PR_PF_PLATINUM_HOME_MDB
-x671f000b PR_PF_PROXY_REQUIRED
-x67200102 PR_INTERNET_FREE_DOC_INFO
-x67210003 PR_PF_OVER_HARD_QUOTA_LIMIT
-x67220003 PR_PF_MSG_SIZE_LIMIT
-x67430003 PR_CONNECTION_MODULUS
-x6744001f PR_DELIVER_TO_DN
-x67460003 PR_MIME_SIZE
-x67470014 PR_FILE_SIZE_EXTENDED
-x67480014 PR_FID
-x67490014 PR_PARENT_FID
-x674a0014 PR_MID
-x674b0014 PR_CATEG_ID
-x674c0014 PR_PARENT_CATEG_ID
-x674d0014 PR_INST_ID
-x674e0003 PR_INSTANCE_NUM
-x674f0014 PR_ADDRBOOK_MID
-x67500003 PR_ICS_NOTIF
-x67510003 PR_ARTICLE_NUM_NEXT
-x67520003 PR_IMAP_LAST_ARTICLE_ID
-x6753000b PR_NOT_822_RENDERABLE
-x67580102 PR_LTID
-x67590102 PR_CN_EXPORT
-x675a0102 PR_PCL_EXPORT
-x675b1102 PR_CN_MV_EXPORT
-x67790003 PR_PF_QUOTA_STYLE
-x677b0003 PR_PF_STORAGE_QUOTA
-x67830003 PR_SEARCH_FLAGS
-x67aa000b PR_ASSOCIATED
-x67f00102 PR_PROFILE_SECURE_MAILBOX
-x6800001f PR_MAILBEAT_BOUNCE_SERVER
-x68010040 PR_MAILBEAT_REQUEST_SENT
-x6802001f PR_USENET_SITE_NAME
-x68030040 PR_MAILBEAT_REQUEST_RECEIVED
-x68040040 PR_MAILBEAT_REQUEST_PROCESSED
-x68060040 PR_MAILBEAT_REPLY_SENT
-x68070040 PR_MAILBEAT_REPLY_SUBMIT
-x68080040 PR_MAILBEAT_REPLY_RECEIVED
-x68090040 PR_MAILBEAT_REPLY_PROCESSED
-x6844101f PR_DELEGATES_DISPLAY_NAMES
-x68451102 PR_DELEGATES_ENTRYIDS
-x68470003 PR_FREEBUSY_START_RANGE
-x68480003 PR_FREEBUSY_END_RANGE
-x6849001f PR_FREEBUSY_EMAIL_ADDRESS
-x684f1003 PR_FREEBUSY_ALL_MONTHS
-x68501102 PR_FREEBUSY_ALL_EVENTS
-x68511003 PR_FREEBUSY_TENTATIVE_MONTHS
-x68521102 PR_FREEBUSY_TENTATIVE_EVENTS
-x68531003 PR_FREEBUSY_BUSY_MONTHS
-x68541102 PR_FREEBUSY_BUSY_EVENTS
-x68551003 PR_FREEBUSY_OOF_MONTHS
-x68561102 PR_FREEBUSY_OOF_EVENTS
-x68680040 PR_FREEBUSY_LAST_MODIFIED
-x68690003 PR_FREEBUSY_NUM_MONTHS
-x686b1003 PR_DELEGATES_SEE_PRIVATE
-x686c0102 PR_PERSONAL_FREEBUSY
-x686d000b PR_PROCESS_MEETING_REQUESTS
-x686e000b PR_DECLINE_RECURRING_MEETING_REQUESTS
-x686f000b PR_DECLINE_CONFLICTING_MEETING_REQUESTS
-x70010102 PR_VD_BINARY
-x7002001f PR_VD_STRINGS
-x70030003 PR_VD_FLAGS
-x70040102 PR_VD_LINK_TO
-x70050102 PR_VD_VIEW_FOLDER
-x7006001f PR_VD_NAME
-x70070003 PR_VD_VERSION
-x7c00001f PR_FAV_DISPLAY_NAME
-x7c00001f PR_FAV_DISPLAY_ALIAS
-x7c020102 PR_FAV_PUBLIC_SOURCE_KEY
-x7c040102 PR_OST_OSTID
-x7c0a000b PR_STORE_SLOWLINK
-x7d010003 PR_FAV_AUTOSUBFOLDERS
-x7d020102 PR_FAV_PARENT_SOURCE_KEY
-x7d030003 PR_FAV_LEVEL_MASK
-x7d070003 PR_FAV_INHERIT_AUTO
-x7d080102 PR_FAV_DEL_SUBS
-x7ffa0003 PR_ATTACHMENT_LINKID
-x7ffb0040 PR_EXCEPTION_STARTTIME
-x7ffc0040 PR_EXCEPTION_ENDTIME
-x7ffd0003 PR_ATTACHMENT_FLAGS
-x7ffe000b PR_ATTACHMENT_HIDDEN
-x8001000b PR_EMS_AB_DISPLAY_NAME_OVERRIDE
-x80031102 PR_EMS_AB_CA_CERTIFICATE
-x8004001f PR_EMS_AB_FOLDER_PATHNAME
-x8005000d PR_EMS_AB_MANAGER
-x8005001f PR_EMS_AB_MANAGER_T
-x8006000d PR_EMS_AB_HOME_MDB_O
-x8006001f PR_EMS_AB_HOME_MDB
-x8007000d PR_EMS_AB_HOME_MTA_O
-x8007001f PR_EMS_AB_HOME_MTA
-x8008000d PR_EMS_AB_IS_MEMBER_OF_DL
-x8008001f PR_EMS_AB_IS_MEMBER_OF_DL_T
-x8009000d PR_EMS_AB_MEMBER
-x8009001f PR_EMS_AB_MEMBER_T
-x800a001f PR_EMS_AB_AUTOREPLY_MESSAGE
-x800b000b PR_EMS_AB_AUTOREPLY
-x800c000d PR_EMS_AB_OWNER_O
-x800c001f PR_EMS_AB_OWNER
-x800d000d PR_EMS_AB_KM_SERVER_O
-x800d001f PR_EMS_AB_KM_SERVER
-x800e000d PR_EMS_AB_REPORTS
-x800e000d PR_EMS_AB_REPORTS_T
-x800f101f PR_EMS_AB_PROXY_ADDRESSES
-x80100102 PR_EMS_AB_HELP_DATA32
-x8011001f PR_EMS_AB_TARGET_ADDRESS
-x8012101f PR_EMS_AB_TELEPHONE_NUMBER
-x80130102 PR_EMS_AB_NT_SECURITY_DESCRIPTOR
-x8014000d PR_EMS_AB_HOME_MDB_BL_O
-x8014101f PR_EMS_AB_HOME_MDB_BL
-x8015000d PR_EMS_AB_PUBLIC_DELEGATES
-x8015001f PR_EMS_AB_PUBLIC_DELEGATES_T
-x80160102 PR_EMS_AB_CERTIFICATE_REVOCATION_LIST
-x80170102 PR_EMS_AB_ADDRESS_ENTRY_DISPLAY_TABLE
-x80180102 PR_EMS_AB_ADDRESS_SYNTAX
-x80230102 PR_EMS_AB_BUSINESS_ROLES
-x8024000d PR_EMS_AB_OWNER_BL_O
-x8024101f PR_EMS_AB_OWNER_BL
-x80251102 PR_EMS_AB_CROSS_CERTIFICATE_PAIR
-x80261102 PR_EMS_AB_AUTHORITY_REVOCATION_LIST
-x80270102 PR_EMS_AB_ASSOC_NT_ACCOUNT
-x80280040 PR_EMS_AB_EXPIRATION_TIME
-x80290003 PR_EMS_AB_USN_CHANGED
-x802d001f PR_EMS_AB_EXTENSION_ATTRIBUTE_1
-x802e001f PR_EMS_AB_EXTENSION_ATTRIBUTE_2
-x802f001f PR_EMS_AB_EXTENSION_ATTRIBUTE_3
-x8030001f PR_EMS_AB_EXTENSION_ATTRIBUTE_4
-x8031001f PR_EMS_AB_EXTENSION_ATTRIBUTE_5
-x8032001f PR_EMS_AB_EXTENSION_ATTRIBUTE_6
-x8033001f PR_EMS_AB_EXTENSION_ATTRIBUTE_7
-x8034001f PR_EMS_AB_EXTENSION_ATTRIBUTE_8
-x8035001f PR_EMS_AB_EXTENSION_ATTRIBUTE_9
-x8036001f PR_EMS_AB_EXTENSION_ATTRIBUTE_10
-x80371102 PR_EMS_AB_SECURITY_PROTOCOL
-x8038000d PR_EMS_AB_PF_CONTACTS_O
-x8038101f PR_EMS_AB_PF_CONTACTS
-x803a0102 PR_EMS_AB_HELP_DATA16
-x803b001f PR_EMS_AB_HELP_FILE_NAME
-x803c000d PR_EMS_AB_OBJ_DIST_NAME_O
-x803c001f PR_EMS_AB_OBJ_DIST_NAME
-x803d001f PR_EMS_AB_ENCRYPT_ALG_SELECTED_OTHER
-x803e001f PR_EMS_AB_AUTOREPLY_SUBJECT
-x803f000d PR_EMS_AB_HOME_PUBLIC_SERVER_O
-x803f001f PR_EMS_AB_HOME_PUBLIC_SERVER
-x8040101f PR_EMS_AB_ENCRYPT_ALG_LIST_NA
-x8041101f PR_EMS_AB_ENCRYPT_ALG_LIST_OTHER
-x8042001f PR_EMS_AB_IMPORTED_FROM
-x8043001f PR_EMS_AB_ENCRYPT_ALG_SELECTED_NA
-x80440003 PR_EMS_AB_ACCESS_CATEGORY
-x80450102 PR_EMS_AB_ACTIVATION_SCHEDULE
-x80460003 PR_EMS_AB_ACTIVATION_STYLE
-x80470102 PR_EMS_AB_ADDRESS_ENTRY_DISPLAY_TABLE_MSDOS
-x8048001f PR_EMS_AB_ADDRESS_TYPE
-x8049001f PR_EMS_AB_ADMD
-x804a001f PR_EMS_AB_ADMIN_DESCRIPTION
-x804b001f PR_EMS_AB_ADMIN_DISPLAY_NAME
-x804c001f PR_EMS_AB_ADMIN_EXTENSION_DLL
-x804d000d PR_EMS_AB_ALIASED_OBJECT_NAME_O
-x804d001f PR_EMS_AB_ALIASED_OBJECT_NAME
-x804e000d PR_EMS_AB_ALT_RECIPIENT_O
-x804e001f PR_EMS_AB_ALT_RECIPIENT
-x804f000d PR_EMS_AB_ALT_RECIPIENT_BL_O
-x804f101f PR_EMS_AB_ALT_RECIPIENT_BL
-x80500102 PR_EMS_AB_ANCESTOR_ID
-x8051000d PR_EMS_AB_ASSOC_REMOTE_DXA_O
-x8051101f PR_EMS_AB_ASSOC_REMOTE_DXA
-x80520003 PR_EMS_AB_ASSOCIATION_LIFETIME
-x8053000d PR_EMS_AB_AUTH_ORIG_BL_O
-x8053101f PR_EMS_AB_AUTH_ORIG_BL
-x8054001f PR_EMS_AB_AUTHORIZED_DOMAIN
-x80550102 PR_EMS_AB_AUTHORIZED_PASSWORD
-x8056001f PR_EMS_AB_AUTHORIZED_USER
-x8057101f PR_EMS_AB_BUSINESS_CATEGORY
-x8058000d PR_EMS_AB_CAN_CREATE_PF_O
-x8058101f PR_EMS_AB_CAN_CREATE_PF
-x8059000d PR_EMS_AB_CAN_CREATE_PF_BL_O
-x8059101f PR_EMS_AB_CAN_CREATE_PF_BL
-x805a000d PR_EMS_AB_CAN_CREATE_PF_DL_O
-x805a101f PR_EMS_AB_CAN_CREATE_PF_DL
-x805b000d PR_EMS_AB_CAN_CREATE_PF_DL_BL_O
-x805b101f PR_EMS_AB_CAN_CREATE_PF_DL_BL
-x805c000d PR_EMS_AB_CAN_NOT_CREATE_PF_O
-x805c101f PR_EMS_AB_CAN_NOT_CREATE_PF
-x805d000d PR_EMS_AB_CAN_NOT_CREATE_PF_BL_O
-x805d101f PR_EMS_AB_CAN_NOT_CREATE_PF_BL
-x805e000d PR_EMS_AB_CAN_NOT_CREATE_PF_DL_O
-x805e101f PR_EMS_AB_CAN_NOT_CREATE_PF_DL
-x805f000d PR_EMS_AB_CAN_NOT_CREATE_PF_DL_BL_O
-x805f101f PR_EMS_AB_CAN_NOT_CREATE_PF_DL_BL
-x8060000b PR_EMS_AB_CAN_PRESERVE_DNS
-x80610003 PR_EMS_AB_CLOCK_ALERT_OFFSET
-x8062000b PR_EMS_AB_CLOCK_ALERT_REPAIR
-x80630003 PR_EMS_AB_CLOCK_WARNING_OFFSET
-x8064000b PR_EMS_AB_CLOCK_WARNING_REPAIR
-x8065001f PR_EMS_AB_COMPUTER_NAME
-x8066101f PR_EMS_AB_CONNECTED_DOMAINS
-x80670003 PR_EMS_AB_CONTAINER_INFO
-x80680003 PR_EMS_AB_COST
-x8069001f PR_EMS_AB_COUNTRY_NAME
-x806a0003 PR_EMS_AB_DELIV_CONT_LENGTH
-x806b1102 PR_EMS_AB_DELIV_EITS
-x806c1102 PR_EMS_AB_DELIV_EXT_CONT_TYPES
-x806d000b PR_EMS_AB_DELIVER_AND_REDIRECT
-x806e0003 PR_EMS_AB_DELIVERY_MECHANISM
-x806f101f PR_EMS_AB_DESCRIPTION
-x8070101f PR_EMS_AB_DESTINATION_INDICATOR
-x8071001f PR_EMS_AB_DIAGNOSTIC_REG_KEY
-x8072000d PR_EMS_AB_DL_MEM_REJECT_PERMS_BL_O
-x8072101f PR_EMS_AB_DL_MEM_REJECT_PERMS_BL
-x8073000d PR_EMS_AB_DL_MEM_SUBMIT_PERMS_BL_O
-x8073101f PR_EMS_AB_DL_MEM_SUBMIT_PERMS_BL
-x80741102 PR_EMS_AB_DL_MEMBER_RULE
-x8075000d PR_EMS_AB_DOMAIN_DEF_ALT_RECIP_O
-x8075001f PR_EMS_AB_DOMAIN_DEF_ALT_RECIP
-x8076001f PR_EMS_AB_DOMAIN_NAME
-x80770102 PR_EMS_AB_DSA_SIGNATURE
-x8078000b PR_EMS_AB_DXA_ADMIN_COPY
-x8079000b PR_EMS_AB_DXA_ADMIN_FORWARD
-x807a0003 PR_EMS_AB_DXA_ADMIN_UPDATE
-x807b000b PR_EMS_AB_DXA_APPEND_REQCN
-x807c000d PR_EMS_AB_DXA_CONF_CONTAINER_LIST_O
-x807c101f PR_EMS_AB_DXA_CONF_CONTAINER_LIST
-x807d0040 PR_EMS_AB_DXA_CONF_REQ_TIME
-x807e001f PR_EMS_AB_DXA_CONF_SEQ
-x807f0003 PR_EMS_AB_DXA_CONF_SEQ_USN
-x80800003 PR_EMS_AB_DXA_EXCHANGE_OPTIONS
-x8081000b PR_EMS_AB_DXA_EXPORT_NOW
-x80820003 PR_EMS_AB_DXA_FLAGS
-x8083001f PR_EMS_AB_DXA_IMP_SEQ
-x80840040 PR_EMS_AB_DXA_IMP_SEQ_TIME
-x80850003 PR_EMS_AB_DXA_IMP_SEQ_USN
-x8086000b PR_EMS_AB_DXA_IMPORT_NOW
-x8087101f PR_EMS_AB_DXA_IN_TEMPLATE_MAP
-x8088000d PR_EMS_AB_DXA_LOCAL_ADMIN_O
-x8088001f PR_EMS_AB_DXA_LOCAL_ADMIN
-x80890003 PR_EMS_AB_DXA_LOGGING_LEVEL
-x808a001f PR_EMS_AB_DXA_NATIVE_ADDRESS_TYPE
-x808b101f PR_EMS_AB_DXA_OUT_TEMPLATE_MAP
-x808c001f PR_EMS_AB_DXA_PASSWORD
-x808d0003 PR_EMS_AB_DXA_PREV_EXCHANGE_OPTIONS
-x808e000b PR_EMS_AB_DXA_PREV_EXPORT_NATIVE_ONLY
-x808f0003 PR_EMS_AB_DXA_PREV_IN_EXCHANGE_SENSITIVITY
-x8090000d PR_EMS_AB_DXA_PREV_REMOTE_ENTRIES_O
-x8090001f PR_EMS_AB_DXA_PREV_REMOTE_ENTRIES
-x80910003 PR_EMS_AB_DXA_PREV_REPLICATION_SENSITIVITY
-x80920003 PR_EMS_AB_DXA_PREV_TEMPLATE_OPTIONS
-x80930003 PR_EMS_AB_DXA_PREV_TYPES
-x8094001f PR_EMS_AB_DXA_RECIPIENT_CP
-x8095000d PR_EMS_AB_DXA_REMOTE_CLIENT_O
-x8095001f PR_EMS_AB_DXA_REMOTE_CLIENT
-x8096001f PR_EMS_AB_DXA_REQ_SEQ
-x80970040 PR_EMS_AB_DXA_REQ_SEQ_TIME
-x80980003 PR_EMS_AB_DXA_REQ_SEQ_USN
-x8099001f PR_EMS_AB_DXA_REQNAME
-x809a001f PR_EMS_AB_DXA_SVR_SEQ
-x809b0040 PR_EMS_AB_DXA_SVR_SEQ_TIME
-x809c0003 PR_EMS_AB_DXA_SVR_SEQ_USN
-x809d0003 PR_EMS_AB_DXA_TASK
-x809e0003 PR_EMS_AB_DXA_TEMPLATE_OPTIONS
-x809f0040 PR_EMS_AB_DXA_TEMPLATE_TIMESTAMP
-x80a00003 PR_EMS_AB_DXA_TYPES
-x80a1000d PR_EMS_AB_DXA_UNCONF_CONTAINER_LIST_O
-x80a1101f PR_EMS_AB_DXA_UNCONF_CONTAINER_LIST
-x80a20003 PR_EMS_AB_ENCAPSULATION_METHOD
-x80a3000b PR_EMS_AB_ENCRYPT
-x80a4000b PR_EMS_AB_EXPAND_DLS_LOCALLY
-x80a5000d PR_EMS_AB_EXPORT_CONTAINERS_O
-x80a5101f PR_EMS_AB_EXPORT_CONTAINERS
-x80a6000b PR_EMS_AB_EXPORT_CUSTOM_RECIPIENTS
-x80a7000b PR_EMS_AB_EXTENDED_CHARS_ALLOWED
-x80a81102 PR_EMS_AB_EXTENSION_DATA
-x80a9101f PR_EMS_AB_EXTENSION_NAME
-x80aa101f PR_EMS_AB_EXTENSION_NAME_INHERITED
-x80ab1102 PR_EMS_AB_FACSIMILE_TELEPHONE_NUMBER
-x80ac0102 PR_EMS_AB_FILE_VERSION
-x80ad000b PR_EMS_AB_FILTER_LOCAL_ADDRESSES
-x80ae000d PR_EMS_AB_FOLDERS_CONTAINER_O
-x80ae001f PR_EMS_AB_FOLDERS_CONTAINER
-x80af0003 PR_EMS_AB_GARBAGE_COLL_PERIOD
-x80b0001f PR_EMS_AB_GATEWAY_LOCAL_CRED
-x80b1001f PR_EMS_AB_GATEWAY_LOCAL_DESIG
-x80b2101f PR_EMS_AB_GATEWAY_PROXY
-x80b30102 PR_EMS_AB_GATEWAY_ROUTING_TREE
-x80b40040 PR_EMS_AB_GWART_LAST_MODIFIED
-x80b5000d PR_EMS_AB_HAS_FULL_REPLICA_NCS_O
-x80b5101f PR_EMS_AB_HAS_FULL_REPLICA_NCS
-x80b6000d PR_EMS_AB_HAS_MASTER_NCS_O
-x80b6101f PR_EMS_AB_HAS_MASTER_NCS
-x80b70003 PR_EMS_AB_HEURISTICS
-x80b8000b PR_EMS_AB_HIDE_DL_MEMBERSHIP
-x80b9000b PR_EMS_AB_HIDE_FROM_ADDRESS_BOOK
-x80ba000d PR_EMS_AB_IMPORT_CONTAINER_O
-x80ba001f PR_EMS_AB_IMPORT_CONTAINER
-x80bb0003 PR_EMS_AB_IMPORT_SENSITIVITY
-x80bc000d PR_EMS_AB_INBOUND_SITES_O
-x80bc101f PR_EMS_AB_INBOUND_SITES
-x80bd0003 PR_EMS_AB_INSTANCE_TYPE
-x80be101f PR_EMS_AB_INTERNATIONAL_ISDN_NUMBER
-x80bf0102 PR_EMS_AB_INVOCATION_ID
-x80c0000b PR_EMS_AB_IS_DELETED
-x80c1000b PR_EMS_AB_IS_SINGLE_VALUED
-x80c21102 PR_EMS_AB_KCC_STATUS
-x80c3101f PR_EMS_AB_KNOWLEDGE_INFORMATION
-x80c40003 PR_EMS_AB_LINE_WRAP
-x80c50003 PR_EMS_AB_LINK_ID
-x80c6001f PR_EMS_AB_LOCAL_BRIDGE_HEAD
-x80c7001f PR_EMS_AB_LOCAL_BRIDGE_HEAD_ADDRESS
-x80c8000b PR_EMS_AB_LOCAL_INITIAL_TURN
-x80c9000d PR_EMS_AB_LOCAL_SCOPE_O
-x80c9101f PR_EMS_AB_LOCAL_SCOPE
-x80ca001f PR_EMS_AB_LOG_FILENAME
-x80cb0003 PR_EMS_AB_LOG_ROLLOVER_INTERVAL
-x80cc000b PR_EMS_AB_MAINTAIN_AUTOREPLY_HISTORY
-x80cd0003 PR_EMS_AB_MAPI_DISPLAY_TYPE
-x80ce0003 PR_EMS_AB_MAPI_ID
-x80cf0003 PR_EMS_AB_MDB_BACKOFF_INTERVAL
-x80d00003 PR_EMS_AB_MDB_MSG_TIME_OUT_PERIOD
-x80d10003 PR_EMS_AB_MDB_OVER_QUOTA_LIMIT
-x80d20003 PR_EMS_AB_MDB_STORAGE_QUOTA
-x80d30003 PR_EMS_AB_MDB_UNREAD_LIMIT
-x80d4000b PR_EMS_AB_MDB_USE_DEFAULTS
-x80d5000b PR_EMS_AB_MESSAGE_TRACKING_ENABLED
-x80d6000b PR_EMS_AB_MONITOR_CLOCK
-x80d7000b PR_EMS_AB_MONITOR_SERVERS
-x80d8000b PR_EMS_AB_MONITOR_SERVICES
-x80d9000d PR_EMS_AB_MONITORED_CONFIGURATIONS_O
-x80d9101f PR_EMS_AB_MONITORED_CONFIGURATIONS
-x80da000d PR_EMS_AB_MONITORED_SERVERS_O
-x80da101f PR_EMS_AB_MONITORED_SERVERS
-x80db101f PR_EMS_AB_MONITORED_SERVICES
-x80dc0003 PR_EMS_AB_MONITORING_ALERT_DELAY
-x80dd0003 PR_EMS_AB_MONITORING_ALERT_UNITS
-x80de0003 PR_EMS_AB_MONITORING_AVAILABILITY_STYLE
-x80df0102 PR_EMS_AB_MONITORING_AVAILABILITY_WINDOW
-x80e0000d PR_EMS_AB_MONITORING_CACHED_VIA_MAIL_O
-x80e0101f PR_EMS_AB_MONITORING_CACHED_VIA_MAIL
-x80e1000d PR_EMS_AB_MONITORING_CACHED_VIA_RPC_O
-x80e1101f PR_EMS_AB_MONITORING_CACHED_VIA_RPC
-x80e21102 PR_EMS_AB_MONITORING_ESCALATION_PROCEDURE
-x80e30003 PR_EMS_AB_MONITORING_HOTSITE_POLL_INTERVAL
-x80e40003 PR_EMS_AB_MONITORING_HOTSITE_POLL_UNITS
-x80e50003 PR_EMS_AB_MONITORING_MAIL_UPDATE_INTERVAL
-x80e60003 PR_EMS_AB_MONITORING_MAIL_UPDATE_UNITS
-x80e70003 PR_EMS_AB_MONITORING_NORMAL_POLL_INTERVAL
-x80e80003 PR_EMS_AB_MONITORING_NORMAL_POLL_UNITS
-x80e9000d PR_EMS_AB_MONITORING_RECIPIENTS_O
-x80e9101f PR_EMS_AB_MONITORING_RECIPIENTS
-x80ea000d PR_EMS_AB_MONITORING_RECIPIENTS_NDR_O
-x80ea101f PR_EMS_AB_MONITORING_RECIPIENTS_NDR
-x80eb0003 PR_EMS_AB_MONITORING_RPC_UPDATE_INTERVAL
-x80ec0003 PR_EMS_AB_MONITORING_RPC_UPDATE_UNITS
-x80ed0003 PR_EMS_AB_MONITORING_WARNING_DELAY
-x80ee0003 PR_EMS_AB_MONITORING_WARNING_UNITS
-x80ef001f PR_EMS_AB_MTA_LOCAL_CRED
-x80f0001f PR_EMS_AB_MTA_LOCAL_DESIG
-x80f10102 PR_EMS_AB_N_ADDRESS
-x80f20003 PR_EMS_AB_N_ADDRESS_TYPE
-x80f3001f PR_EMS_AB_NT_MACHINE_NAME
-x80f40003 PR_EMS_AB_NUM_OF_OPEN_RETRIES
-x80f50003 PR_EMS_AB_NUM_OF_TRANSFER_RETRIES
-x80f60003 PR_EMS_AB_OBJECT_CLASS_CATEGORY
-x80f70003 PR_EMS_AB_OBJECT_VERSION
-x80f8000d PR_EMS_AB_OFF_LINE_AB_CONTAINERS_O
-x80f8101f PR_EMS_AB_OFF_LINE_AB_CONTAINERS
-x80f90102 PR_EMS_AB_OFF_LINE_AB_SCHEDULE
-x80fa000d PR_EMS_AB_OFF_LINE_AB_SERVER_O
-x80fa001f PR_EMS_AB_OFF_LINE_AB_SERVER
-x80fb0003 PR_EMS_AB_OFF_LINE_AB_STYLE
-x80fc0003 PR_EMS_AB_OID_TYPE
-x80fd0102 PR_EMS_AB_OM_OBJECT_CLASS
-x80fe0003 PR_EMS_AB_OM_SYNTAX
-x80ff000b PR_EMS_AB_OOF_REPLY_TO_ORIGINATOR
-x81000003 PR_EMS_AB_OPEN_RETRY_INTERVAL
-x8101101f PR_EMS_AB_ORGANIZATION_NAME
-x8102101f PR_EMS_AB_ORGANIZATIONAL_UNIT_NAME
-x81030102 PR_EMS_AB_ORIGINAL_DISPLAY_TABLE
-x81040102 PR_EMS_AB_ORIGINAL_DISPLAY_TABLE_MSDOS
-x8105000d PR_EMS_AB_OUTBOUND_SITES_O
-x8105101f PR_EMS_AB_OUTBOUND_SITES
-x81060102 PR_EMS_AB_P_SELECTOR
-x81070102 PR_EMS_AB_P_SELECTOR_INBOUND
-x81080102 PR_EMS_AB_PER_MSG_DIALOG_DISPLAY_TABLE
-x81090102 PR_EMS_AB_PER_RECIP_DIALOG_DISPLAY_TABLE
-x810a0102 PR_EMS_AB_PERIOD_REP_SYNC_TIMES
-x810b0003 PR_EMS_AB_PERIOD_REPL_STAGGER
-x810c1102 PR_EMS_AB_POSTAL_ADDRESS
-x810d1003 PR_EMS_AB_PREFERRED_DELIVERY_METHOD
-x810e001f PR_EMS_AB_PRMD
-x810f001f PR_EMS_AB_PROXY_GENERATOR_DLL
-x8110000d PR_EMS_AB_PUBLIC_DELEGATES_BL_O
-x8110101f PR_EMS_AB_PUBLIC_DELEGATES_BL
-x81110102 PR_EMS_AB_QUOTA_NOTIFICATION_SCHEDULE
-x81120003 PR_EMS_AB_QUOTA_NOTIFICATION_STYLE
-x81130003 PR_EMS_AB_RANGE_LOWER
-x81140003 PR_EMS_AB_RANGE_UPPER
-x8115001f PR_EMS_AB_RAS_CALLBACK_NUMBER
-x8116001f PR_EMS_AB_RAS_PHONE_NUMBER
-x8117001f PR_EMS_AB_RAS_PHONEBOOK_ENTRY_NAME
-x8118001f PR_EMS_AB_RAS_REMOTE_SRVR_NAME
-x81191102 PR_EMS_AB_REGISTERED_ADDRESS
-x811a001f PR_EMS_AB_REMOTE_BRIDGE_HEAD
-x811b001f PR_EMS_AB_REMOTE_BRIDGE_HEAD_ADDRESS
-x811c000d PR_EMS_AB_REMOTE_OUT_BH_SERVER_O
-x811c001f PR_EMS_AB_REMOTE_OUT_BH_SERVER
-x811d000d PR_EMS_AB_REMOTE_SITE_O
-x811d001f PR_EMS_AB_REMOTE_SITE
-x811e0003 PR_EMS_AB_REPLICATION_SENSITIVITY
-x811f0003 PR_EMS_AB_REPLICATION_STAGGER
-x8120000b PR_EMS_AB_REPORT_TO_ORIGINATOR
-x8121000b PR_EMS_AB_REPORT_TO_OWNER
-x81220003 PR_EMS_AB_REQ_SEQ
-x8123000d PR_EMS_AB_RESPONSIBLE_LOCAL_DXA_O
-x8123001f PR_EMS_AB_RESPONSIBLE_LOCAL_DXA
-x8124000d PR_EMS_AB_RID_SERVER_O
-x8124001f PR_EMS_AB_RID_SERVER
-x8125000d PR_EMS_AB_ROLE_OCCUPANT_O
-x8125101f PR_EMS_AB_ROLE_OCCUPANT
-x8126101f PR_EMS_AB_ROUTING_LIST
-x81270003 PR_EMS_AB_RTS_CHECKPOINT_SIZE
-x81280003 PR_EMS_AB_RTS_RECOVERY_TIMEOUT
-x81290003 PR_EMS_AB_RTS_WINDOW_SIZE
-x812a000d PR_EMS_AB_RUNS_ON_O
-x812a101f PR_EMS_AB_RUNS_ON
-x812b0102 PR_EMS_AB_S_SELECTOR
-x812c0102 PR_EMS_AB_S_SELECTOR_INBOUND
-x812d0003 PR_EMS_AB_SEARCH_FLAGS
-x812e1102 PR_EMS_AB_SEARCH_GUIDE
-x812f000d PR_EMS_AB_SEE_ALSO_O
-x812f101f PR_EMS_AB_SEE_ALSO
-x8130101f PR_EMS_AB_SERIAL_NUMBER
-x81310003 PR_EMS_AB_SERVICE_ACTION_FIRST
-x81320003 PR_EMS_AB_SERVICE_ACTION_OTHER
-x81330003 PR_EMS_AB_SERVICE_ACTION_SECOND
-x81340003 PR_EMS_AB_SERVICE_RESTART_DELAY
-x8135001f PR_EMS_AB_SERVICE_RESTART_MESSAGE
-x81360003 PR_EMS_AB_SESSION_DISCONNECT_TIMER
-x8137101f PR_EMS_AB_SITE_AFFINITY
-x8138101f PR_EMS_AB_SITE_PROXY_SPACE
-x81390040 PR_EMS_AB_SPACE_LAST_COMPUTED
-x813a001f PR_EMS_AB_STREET_ADDRESS
-x813b000d PR_EMS_AB_SUB_REFS_O
-x813b101f PR_EMS_AB_SUB_REFS
-x813c0003 PR_EMS_AB_SUBMISSION_CONT_LENGTH
-x813d1102 PR_EMS_AB_SUPPORTED_APPLICATION_CONTEXT
-x813e000d PR_EMS_AB_SUPPORTING_STACK_O
-x813e101f PR_EMS_AB_SUPPORTING_STACK
-x813f000d PR_EMS_AB_SUPPORTING_STACK_BL_O
-x813f101f PR_EMS_AB_SUPPORTING_STACK_BL
-x81400102 PR_EMS_AB_T_SELECTOR
-x81410102 PR_EMS_AB_T_SELECTOR_INBOUND
-x8142101f PR_EMS_AB_TARGET_MTAS
-x81431102 PR_EMS_AB_TELETEX_TERMINAL_IDENTIFIER
-x81440003 PR_EMS_AB_TEMP_ASSOC_THRESHOLD
-x81450003 PR_EMS_AB_TOMBSTONE_LIFETIME
-x8146001f PR_EMS_AB_TRACKING_LOG_PATH_NAME
-x81470003 PR_EMS_AB_TRANS_RETRY_MINS
-x81480003 PR_EMS_AB_TRANS_TIMEOUT_MINS
-x81490003 PR_EMS_AB_TRANSFER_RETRY_INTERVAL
-x814a0003 PR_EMS_AB_TRANSFER_TIMEOUT_NON_URGENT
-x814b0003 PR_EMS_AB_TRANSFER_TIMEOUT_NORMAL
-x814c0003 PR_EMS_AB_TRANSFER_TIMEOUT_URGENT
-x814d0003 PR_EMS_AB_TRANSLATION_TABLE_USED
-x814e000b PR_EMS_AB_TRANSPORT_EXPEDITED_DATA
-x814f0003 PR_EMS_AB_TRUST_LEVEL
-x81500003 PR_EMS_AB_TURN_REQUEST_THRESHOLD
-x8151000b PR_EMS_AB_TWO_WAY_ALTERNATE_FACILITY
-x8152000d PR_EMS_AB_UNAUTH_ORIG_BL_O
-x8152101f PR_EMS_AB_UNAUTH_ORIG_BL
-x81531102 PR_EMS_AB_USER_PASSWORD
-x81540003 PR_EMS_AB_USN_CREATED
-x81550003 PR_EMS_AB_USN_DSA_LAST_OBJ_REMOVED
-x81560003 PR_EMS_AB_USN_LAST_OBJ_REM
-x81570003 PR_EMS_AB_USN_SOURCE
-x8158101f PR_EMS_AB_X121_ADDRESS
-x81590102 PR_EMS_AB_X25_CALL_USER_DATA_INCOMING
-x815a0102 PR_EMS_AB_X25_CALL_USER_DATA_OUTGOING
-x815b0102 PR_EMS_AB_X25_FACILITIES_DATA_INCOMING
-x815c0102 PR_EMS_AB_X25_FACILITIES_DATA_OUTGOING
-x815d0102 PR_EMS_AB_X25_LEASED_LINE_PORT
-x815e000b PR_EMS_AB_X25_LEASED_OR_SWITCHED
-x815f001f PR_EMS_AB_X25_REMOTE_MTA_PHONE
-x81600102 PR_EMS_AB_X400_ATTACHMENT_TYPE
-x81610003 PR_EMS_AB_X400_SELECTOR_SYNTAX
-x81620102 PR_EMS_AB_X500_ACCESS_CONTROL_LIST
-x81630003 PR_EMS_AB_XMIT_TIMEOUT_NON_URGENT
-x81640003 PR_EMS_AB_XMIT_TIMEOUT_NORMAL
-x81650003 PR_EMS_AB_XMIT_TIMEOUT_URGENT
-x81660102 PR_EMS_AB_SITE_FOLDER_GUID
-x8167000d PR_EMS_AB_SITE_FOLDER_SERVER_O
-x8167001f PR_EMS_AB_SITE_FOLDER_SERVER
-x81680003 PR_EMS_AB_REPLICATION_MAIL_MSG_SIZE
-x81690102 PR_EMS_AB_MAXIMUM_OBJECT_ID
-x8170101f PR_EMS_AB_NETWORK_ADDRESS
-x8171101f PR_EMS_AB_LDAP_DISPLAY_NAME
-x81730003 PR_EMS_AB_SCHEMA_FLAGS
-x8174000d PR_EMS_AB_BRIDGEHEAD_SERVERS_O
-x8174101f PR_EMS_AB_BRIDGEHEAD_SERVERS
-x8175001f PR_EMS_AB_WWW_HOME_PAGE
-x8176001f PR_EMS_AB_NNTP_CONTENT_FORMAT
-x8177001f PR_EMS_AB_POP_CONTENT_FORMAT
-x81780003 PR_EMS_AB_LANGUAGE
-x8179001f PR_EMS_AB_POP_CHARACTER_SET
-x817a0003 PR_EMS_AB_USN_INTERSITE
-x817b001f PR_EMS_AB_SUB_SITE
-x817c1003 PR_EMS_AB_SCHEMA_VERSION
-x817d001f PR_EMS_AB_NNTP_CHARACTER_SET
-x817e000b PR_EMS_AB_USE_SERVER_VALUES
-x817f0003 PR_EMS_AB_ENABLED_PROTOCOLS
-x81800102 PR_EMS_AB_CONNECTION_LIST_FILTER
-x8181101f PR_EMS_AB_AVAILABLE_AUTHORIZATION_PACKAGES
-x8182101f PR_EMS_AB_CHARACTER_SET_LIST
-x8183000b PR_EMS_AB_USE_SITE_VALUES
-x8184101f PR_EMS_AB_ENABLED_AUTHORIZATION_PACKAGES
-x8185001f PR_EMS_AB_CHARACTER_SET
-x81860003 PR_EMS_AB_CONTENT_TYPE
-x8187000b PR_EMS_AB_ANONYMOUS_ACCESS
-x81880102 PR_EMS_AB_CONTROL_MSG_FOLDER_ID
-x8189001f PR_EMS_AB_USENET_SITE_NAME
-x818a0102 PR_EMS_AB_CONTROL_MSG_RULES
-x818b001f PR_EMS_AB_AVAILABLE_DISTRIBUTIONS
-x818d0102 PR_EMS_AB_OUTBOUND_HOST
-x818e101f PR_EMS_AB_INBOUND_HOST
-x818f0003 PR_EMS_AB_OUTGOING_MSG_SIZE_LIMIT
-x81900003 PR_EMS_AB_INCOMING_MSG_SIZE_LIMIT
-x8191000b PR_EMS_AB_SEND_TNEF
-x81920102 PR_EMS_AB_AUTHORIZED_PASSWORD_CONFIRM
-x8193001f PR_EMS_AB_INBOUND_NEWSFEED
-x81940003 PR_EMS_AB_NEWSFEED_TYPE
-x8195001f PR_EMS_AB_OUTBOUND_NEWSFEED
-x81960102 PR_EMS_AB_NEWSGROUP_LIST
-x8197101f PR_EMS_AB_NNTP_DISTRIBUTIONS
-x8198001f PR_EMS_AB_NEWSGROUP
-x8199001f PR_EMS_AB_MODERATOR
-x819a001f PR_EMS_AB_AUTHENTICATION_TO_USE
-x819b000b PR_EMS_AB_HTTP_PUB_GAL
-x819c0003 PR_EMS_AB_HTTP_PUB_GAL_LIMIT
-x819e1102 PR_EMS_AB_HTTP_PUB_PF
-x81a1001f PR_EMS_AB_X500_RDN
-x81a2001f PR_EMS_AB_X500_NC
-x81a3101f PR_EMS_AB_REFERRAL_LIST
-x81a4000b PR_EMS_AB_NNTP_DISTRIBUTIONS_FLAG
-x81a5000d PR_EMS_AB_ASSOC_PROTOCOL_CFG_NNTP_O
-x81a5001f PR_EMS_AB_ASSOC_PROTOCOL_CFG_NNTP
-x81a6000d PR_EMS_AB_NNTP_NEWSFEEDS_O
-x81a6101f PR_EMS_AB_NNTP_NEWSFEEDS
-x81a8000b PR_EMS_AB_ENABLED_PROTOCOL_CFG
-x81a9101f PR_EMS_AB_HTTP_PUB_AB_ATTRIBUTES
-x81ab101f PR_EMS_AB_HTTP_SERVERS
-x81ac000b PR_EMS_AB_MODERATED
-x81ad001f PR_EMS_AB_RAS_ACCOUNT
-x81ae0102 PR_EMS_AB_RAS_PASSWORD
-x81af0102 PR_EMS_AB_INCOMING_PASSWORD
-x81b0000b PR_EMS_AB_OUTBOUND_HOST_TYPE
-x81b1000b PR_EMS_AB_PROXY_GENERATION_ENABLED
-x81b20102 PR_EMS_AB_ROOT_NEWSGROUPS_FOLDER_ID
-x81b3000b PR_EMS_AB_CONNECTION_TYPE
-x81b40003 PR_EMS_AB_CONNECTION_LIST_FILTER_TYPE
-x81b50003 PR_EMS_AB_PORT_NUMBER
-x81b6101f PR_EMS_AB_PROTOCOL_SETTINGS
-x81b7001f PR_EMS_AB_GROUP_BY_ATTR_1
-x81b8001f PR_EMS_AB_GROUP_BY_ATTR_2
-x81b9001f PR_EMS_AB_GROUP_BY_ATTR_3
-x81ba001f PR_EMS_AB_GROUP_BY_ATTR_4
-x81be001f PR_EMS_AB_VIEW_SITE
-x81bf001f PR_EMS_AB_VIEW_CONTAINER_1
-x81c0001f PR_EMS_AB_VIEW_CONTAINER_2
-x81c1001f PR_EMS_AB_VIEW_CONTAINER_3
-x81c20040 PR_EMS_AB_PROMO_EXPIRATION
-x81c3101f PR_EMS_AB_DISABLED_GATEWAY_PROXY
-x81c40102 PR_EMS_AB_COMPROMISED_KEY_LIST
-x81c5000d PR_EMS_AB_INSADMIN_O
-x81c5001f PR_EMS_AB_INSADMIN
-x81c6000b PR_EMS_AB_OVERRIDE_NNTP_CONTENT_FORMAT
-x81c7000d PR_EMS_AB_OBJ_VIEW_CONTAINERS_O
-x81c7101f PR_EMS_AB_OBJ_VIEW_CONTAINERS
-x8c180003 PR_EMS_AB_VIEW_FLAGS
-x8c19001f PR_EMS_AB_GROUP_BY_ATTR_VALUE_STR
-x8c1a000d PR_EMS_AB_GROUP_BY_ATTR_VALUE_DN_O
-x8c1a001f PR_EMS_AB_GROUP_BY_ATTR_VALUE_DN
-x8c1b1102 PR_EMS_AB_VIEW_DEFINITION
-x8c1c0102 PR_EMS_AB_MIME_TYPES
-x8c1d0003 PR_EMS_AB_LDAP_SEARCH_CFG
-x8c1e000d PR_EMS_AB_INBOUND_DN_O
-x8c1e001f PR_EMS_AB_INBOUND_DN
-x8c1f000b PR_EMS_AB_INBOUND_NEWSFEED_TYPE
-x8c20000b PR_EMS_AB_INBOUND_ACCEPT_ALL
-x8c21000b PR_EMS_AB_ENABLED
-x8c22000b PR_EMS_AB_PRESERVE_INTERNET_CONTENT
-x8c23000b PR_EMS_AB_DISABLE_DEFERRED_COMMIT
-x8c24000b PR_EMS_AB_CLIENT_ACCESS_ENABLED
-x8c25000b PR_EMS_AB_REQUIRE_SSL
-x8c26001f PR_EMS_AB_ANONYMOUS_ACCOUNT
-x8c270102 PR_EMS_AB_CERTIFICATE_CHAIN_V3
-x8c280102 PR_EMS_AB_CERTIFICATE_REVOCATION_LIST_V3
-x8c290102 PR_EMS_AB_CERTIFICATE_REVOCATION_LIST_V1
-x8c301102 PR_EMS_AB_CROSS_CERTIFICATE_CRL
-x8c31000b PR_EMS_AB_SEND_EMAIL_MESSAGE
-x8c32000b PR_EMS_AB_ENABLE_COMPATIBILITY
-x8c33101f PR_EMS_AB_SMIME_ALG_LIST_NA
-x8c34101f PR_EMS_AB_SMIME_ALG_LIST_OTHER
-x8c35001f PR_EMS_AB_SMIME_ALG_SELECTED_NA
-x8c36001f PR_EMS_AB_SMIME_ALG_SELECTED_OTHER
-x8c37000b PR_EMS_AB_DEFAULT_MESSAGE_FORMAT
-x8c38001f PR_EMS_AB_TYPE
-x8c3a0003 PR_EMS_AB_DO_OAB_VERSION
-x8c3b0102 PR_EMS_AB_VOICE_MAIL_SYSTEM_GUID
-x8c3c001f PR_EMS_AB_VOICE_MAIL_USER_ID
-x8c3d001f PR_EMS_AB_VOICE_MAIL_PASSWORD
-x8c3e0102 PR_EMS_AB_VOICE_MAIL_RECORDED_NAME
-x8c3f101f PR_EMS_AB_VOICE_MAIL_GREETINGS
-x8c401102 PR_EMS_AB_VOICE_MAIL_FLAGS
-x8c410003 PR_EMS_AB_VOICE_MAIL_VOLUME
-x8c420003 PR_EMS_AB_VOICE_MAIL_SPEED
-x8c431003 PR_EMS_AB_VOICE_MAIL_RECORDING_LENGTH
-x8c44001f PR_EMS_AB_DISPLAY_NAME_SUFFIX
-x8c451102 PR_EMS_AB_ATTRIBUTE_CERTIFICATE
-x8c461102 PR_EMS_AB_DELTA_REVOCATION_LIST
-x8c471102 PR_EMS_AB_SECURITY_POLICY
-x8c48000b PR_EMS_AB_SUPPORT_SMIME_SIGNATURES
-x8c49000b PR_EMS_AB_DELEGATE_USER
-x8c50000b PR_EMS_AB_LIST_PUBLIC_FOLDERS
-x8c51001f PR_EMS_AB_LABELEDURI
-x8c52000b PR_EMS_AB_RETURN_EXACT_MSG_SIZE
-x8c53001f PR_EMS_AB_GENERATION_QUALIFIER
-x8c54001f PR_EMS_AB_HOUSE_IDENTIFIER
-x8c550102 PR_EMS_AB_SUPPORTED_ALGORITHMS
-x8c56001f PR_EMS_AB_DMD_NAME
-x8c57001f PR_EMS_AB_EXTENSION_ATTRIBUTE_11
-x8c58001f PR_EMS_AB_EXTENSION_ATTRIBUTE_12
-x8c59001f PR_EMS_AB_EXTENSION_ATTRIBUTE_13
-x8c60001f PR_EMS_AB_EXTENSION_ATTRIBUTE_14
-x8c61001f PR_EMS_AB_EXTENSION_ATTRIBUTE_15
-x8c620003 PR_EMS_AB_REPLICATED_OBJECT_VERSION
-x8c63001f PR_EMS_AB_MAIL_DROP
-x8c64001f PR_EMS_AB_FORWARDING_ADDRESS
-x8c650102 PR_EMS_AB_FORM_DATA
-x8c66001f PR_EMS_AB_OWA_SERVER
-x8c67001f PR_EMS_AB_EMPLOYEE_NUMBER
-x8c68001f PR_EMS_AB_TELEPHONE_PERSONAL_PAGER
-x8c69001f PR_EMS_AB_EMPLOYEE_TYPE
-x8c6a1102 PR_EMS_AB_TAGGED_X509_CERT
-x8c6b001f PR_EMS_AB_PERSONAL_TITLE
-x8c6c001f PR_EMS_AB_LANGUAGE_ISO639
-xf000000d PR_EMS_AB_OTHER_RECIPS
-xfff8101f PR_EMS_AB_CHILD_RDNS
-xfff9001f PR_EMS_AB_HIERARCHY_PATH
-xfffa0102 PR_EMS_AB_OBJECT_OID
-xfffb000b PR_EMS_AB_IS_MASTER
-xfffc0102 PR_EMS_AB_PARENT_ENTRYID
-xfffd0003 PR_EMS_AB_CONTAINERID
-xfffd0003 PR_EMS_AB_DOS_ENTRYID
-xfffe001f PR_EMS_AB_SERVER
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2002-2004 Novell, Inc. */
-
-#ifndef __MAPI_H__
-#define __MAPI_H__
-
-G_BEGIN_DECLS
-
-typedef enum {
- MAPI_ACCESS_MODIFY = (1 << 0),
- MAPI_ACCESS_READ = (1 << 1),
- MAPI_ACCESS_DELETE = (1 << 2),
- MAPI_ACCESS_CREATE_HIERARCHY = (1 << 3),
- MAPI_ACCESS_CREATE_CONTENTS = (1 << 4),
- MAPI_ACCESS_CREATE_ASSOCIATED = (1 << 5)
-} MapiAccess;
-
-typedef enum {
- cdoSingle = 0, /* non-recurring appointment */
- cdoMaster = 1, /* recurring appointment */
- cdoInstance = 2, /* single instance of recurring appointment */
- cdoException = 3 /* exception to recurring appointment */
-} CdoInstanceTypes;
-
-typedef enum {
- MAPI_STORE = 0x1, /* Message Store */
- MAPI_ADDRBOOK = 0x2, /* Address Book */
- MAPI_FOLDER = 0x3, /* Folder */
- MAPI_ABCONT = 0x4, /* Address Book Container */
- MAPI_MESSAGE = 0x5, /* Message */
- MAPI_MAILUSER = 0x6, /* Individual Recipient */
- MAPI_ATTACH = 0x7, /* Attachment */
- MAPI_DISTLIST = 0x8, /* Distribution List Recipient */
- MAPI_PROFSECT = 0x9, /* Profile Section */
- MAPI_STATUS = 0xA, /* Status Object */
- MAPI_SESSION = 0xB, /* Session */
- MAPI_FORMINFO = 0xC /* Form Information */
-} MapiObjectType;
-
-typedef enum {
-/* For address book contents tables */
- DT_MAILUSER = 0x00000000,
- DT_DISTLIST = 0x00000001,
- DT_FORUM = 0x00000002,
- DT_AGENT = 0x00000003,
- DT_ORGANIZATION = 0x00000004,
- DT_PRIVATE_DISTLIST = 0x00000005,
- DT_REMOTE_MAILUSER = 0x00000006,
-/* For address book hierarchy tables */
- DT_MODIFIABLE = 0x00010000,
- DT_GLOBAL = 0x00020000,
- DT_LOCAL = 0x00030000,
- DT_WAN = 0x00040000,
- DT_NOT_SPECIFIC = 0x00050000,
-/* For folder hierarchy tables */
- DT_FOLDER = 0x01000000,
- DT_FOLDER_LINK = 0x02000000,
- DT_FOLDER_SPECIAL = 0x04000000
-} MapiPrDisplayType;
-
-typedef enum {
- MAPI_ORIG = 0,
- MAPI_TO = 1,
- MAPI_CC = 2,
- MAPI_BCC = 3
-} MapiPrRecipientType;
-
-typedef enum {
- MAPI_MSGFLAG_READ = 0x0001,
- MAPI_MSGFLAG_UNMODIFIED = 0x0002,
- MAPI_MSGFLAG_SUBMIT = 0x0004,
- MAPI_MSGFLAG_UNSENT = 0x0008,
- MAPI_MSGFLAG_HASATTACH = 0x0010,
- MAPI_MSGFLAG_FROMME = 0x0020,
- MAPI_MSGFLAG_ASSOCIATED = 0x0040,
- MAPI_MSGFLAG_RESEND = 0x0080,
- MAPI_MSGFLAG_RN_PENDING = 0x0100,
- MAPI_MSGFLAG_NRN_PENDING = 0x0200,
- MAPI_MSGFLAG_ORIGIN_X400 = 0x1000,
- MAPI_MSGFLAG_ORIGIN_INTERNET = 0x2000,
- MAPI_MSGFLAG_ORIGIN_MISC_EXT = 0x8000
-} MapiPrMessageFlags;
-
-typedef enum {
- MAPI_ACTION_REPLIED = 261,
- MAPI_ACTION_FORWARDED = 262
-} MapiPrAction;
-
-typedef enum {
- MAPI_ACTION_FLAG_REPLIED_TO_SENDER = 102,
- MAPI_ACTION_FLAG_REPLIED_TO_ALL = 103,
- MAPI_ACTION_FLAG_FORWARDED = 104
-} MapiPrActionFlag;
-
-typedef enum {
- MAPI_FOLLOWUP_UNFLAGGED = 0,
- MAPI_FOLLOWUP_COMPLETED = 1,
- MAPI_FOLLOWUP_FLAGGED = 2
-} MapiPrFlagStatus;
-
-typedef enum {
- MAPI_PRIO_URGENT = 1,
- MAPI_PRIO_NORMAL = 0,
- MAPI_PRIO_NONURGENT = -1
-} MapiPrPriority;
-
-typedef enum {
- MAPI_SENSITIVITY_NONE = 0,
- MAPI_SENSITIVITY_PERSONAL = 1,
- MAPI_SENSITIVITY_PRIVATE = 2,
- MAPI_SENSITIVITY_COMPANY_CONFIDENTIAL = 3
-} MapiPrSensitivity;
-
-typedef enum {
- MAPI_IMPORTANCE_LOW = 0,
- MAPI_IMPORTANCE_NORMAL = 1,
- MAPI_IMPORTANCE_HIGH = 2
-} MapiPrImportance;
-
-G_END_DECLS
-
-#endif /* __MAPI_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2003-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* Server-side rule test program */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <ctype.h>
-#include <string.h>
-
-#include "e2k-context.h"
-#include "e2k-propnames.h"
-#include "e2k-rule.h"
-#include "e2k-rule-xml.h"
-#include "test-utils.h"
-
-const gchar *test_program_name = "ruletest";
-
-static const gchar *rules_props[] = {
- PR_RULES_DATA,
-};
-static const gint n_rules_props = sizeof (rules_props) / sizeof (rules_props[0]);
-
-void
-test_main (gint argc, gchar **argv)
-{
- const gchar *url;
- E2kContext *ctx;
- E2kHTTPStatus status;
- E2kResult *results;
- gint nresults;
- GByteArray *ba;
- E2kRules *rules;
- xmlDoc *doc;
-
- if (argc != 2) {
- fprintf (stderr, "Usage: %s URL\n", argv[0]);
- exit (1);
- }
- url = argv[1];
-
- ctx = test_get_context (url);
- status = e2k_context_propfind (ctx, NULL, url,
- rules_props, n_rules_props,
- &results, &nresults);
- test_abort_if_http_error (status);
-
- ba = e2k_properties_get_prop (results[0].props, PR_RULES_DATA);
- if (!ba) {
- printf ("No rules\n");
- goto done;
- }
-
- rules = e2k_rules_from_binary (ba);
- if (!rules) {
- printf ("Could not parse rules\n");
- goto done;
- }
-
- doc = e2k_rules_to_xml (rules);
- if (doc) {
- xmlDocFormatDump (stdout, doc, TRUE);
- xmlFreeDoc (doc);
- } else
- printf ("Could not convert normal rules to XML\n");
-
- e2k_rules_free (rules);
- e2k_results_free (results, nresults);
-
- done:
- test_quit ();
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2001-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include <libedataserverui/e-passwords.h>
-#include <gtk/gtk.h>
-
-#include "e2k-context.h"
-#include "e2k-global-catalog.h"
-#include "e2k-uri.h"
-
-#include "test-utils.h"
-
-extern const gchar *test_program_name;
-
-/**
- * test_ask_password:
- * @prompt: prompt string
- *
- * Prints @prompt followed by ": " and waits for the user to type
- * a password (with echoing disabled).
- *
- * Return value: the password (or %NULL if stdin is not a tty).
- **/
-gchar *
-test_ask_password (const gchar *prompt)
-{
- gchar *password;
- struct termios t;
- gint old_lflag;
- gchar buf[80];
-
- if (tcgetattr (STDIN_FILENO, &t) != 0)
- return NULL;
-
- old_lflag = t.c_lflag;
- t.c_lflag = (t.c_lflag | ICANON | ECHONL) & ~ECHO;
- tcsetattr (STDIN_FILENO, TCSANOW, &t);
-
- fprintf (stderr, "%s: ", prompt);
- fflush (stdout);
-
- /* For some reason, fgets can return EINTR on
- * Linux if ECHO is false...
- */
- do
- password = fgets (buf, sizeof (buf), stdin);
- while (password == NULL && errno == EINTR);
-
- t.c_lflag = old_lflag;
- tcsetattr (STDIN_FILENO, TCSANOW, &t);
-
- if (!password)
- exit (1);
- return g_strndup (password, strcspn (password, "\n"));
-}
-
-/**
- * test_get_password:
- * @user: username to get the password for
- * @host: Exchange (or global catalog) server name
- *
- * Tries to get a password for @user on @host, by looking it up in
- * the Evolution password database or by prompting the user.
- *
- * Return value: the password, or %NULL if it could not be determined.
- **/
-const gchar *
-test_get_password (const gchar *user, const gchar *host)
-{
- static gchar *password = NULL;
- gchar *prompt;
-
- if (password)
- return password;
-
- if (host) {
- gchar *key;
-
- key = g_strdup_printf ("exchange://%s@%s", user, host);
- password = e_passwords_get_password ("Exchange", key);
- g_free (key);
- }
-
- if (!password) {
- if (host) {
- prompt = g_strdup_printf ("Password for %s@%s",
- user, host);
- } else
- prompt = g_strdup_printf ("Password for %s", user);
-
- password = test_ask_password (prompt);
- g_free (prompt);
- }
-
- return password;
-}
-
-/**
- * test_get_context:
- * @uri: an Exchange HTTP/HTTPS URI
- *
- * Creates an %E2kContext based on @uri. If @uri does not contain a
- * username, the user's local username will be used. If it does not
- * contain a password, test_get_password() will be called to get one.
- *
- * Return value: the new %E2kContext (always; if an error occurs,
- * test_get_context() will exit the program).
- **/
-E2kContext *
-test_get_context (const gchar *uri)
-{
- E2kContext *ctx;
- E2kUri *euri;
-
- ctx = e2k_context_new (uri);
- if (!ctx) {
- fprintf (stderr, "Could not parse %s as URI\n", uri);
- exit (1);
- }
-
- euri = e2k_uri_new (uri);
- if (!euri->user)
- euri->user = g_strdup (g_get_user_name ());
- if (!euri->passwd)
- euri->passwd = g_strdup (test_get_password (euri->user, euri->host));
-
- e2k_context_set_auth (ctx, euri->user, euri->domain,
- euri->authmech, euri->passwd);
-
- e2k_uri_free (euri);
- return ctx;
-}
-
-/**
- * test_get_gc:
- * @server: the global catalog server to contact
- *
- * Creates an %E2kGlobalCatalog for the server @server.
- * test_get_password() will be called to get a password.
- *
- * Return value: the new %E2kGlobalCatalog (always; if an error occurs,
- * test_get_gc() will exit the program).
- **/
-E2kGlobalCatalog *
-test_get_gc (const gchar *server)
-{
- E2kGlobalCatalog *gc;
- const gchar *password;
- gchar *user, *p;
-
- if (strchr (server, '@')) {
- user = g_strdup (server);
- p = strchr (user, '@');
- *p = '\0';
- server = p + 1;
- } else
- user = g_strdup (g_get_user_name ());
-
- password = test_get_password (user, server);
- gc = e2k_global_catalog_new (server, -1, user, NULL, password, E2K_AUTOCONFIG_USE_GAL_DEFAULT);
- if (!gc) {
- fprintf (stderr, "Could not create GC\n");
- exit (1);
- }
- g_free (user);
-
- return gc;
-}
-
-static gchar **global_argv;
-static gint global_argc;
-static GMainLoop *loop;
-
-/**
- * test_main:
- * @argc: argc
- * @argv: argv
- *
- * test-utils.o includes a main() function that calls various
- * initialization routines, starts the main loop, and then calls
- * test_main(). So test_main() is the entry point for a
- * test-utils-using program.
- **/
-
-/**
- * test_quit:
- *
- * Cleanly quits a test program.
- **/
-void
-test_quit (void)
-{
- g_main_loop_quit (loop);
-}
-
-/**
- * test_abort_if_http_error:
- * @status: an HTTP status code
- *
- * Checks if @status is an HTTP or libsoup error, and if so, prints
- * the error message and exits.
- **/
-void
-test_abort_if_http_error (E2kHTTPStatus status)
-{
- if (E2K_HTTP_STATUS_IS_TRANSPORT_ERROR (status)) {
- fprintf (stderr, "\n%s\n", soup_status_get_phrase (status));
- exit (1);
- } else if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
- fprintf (stderr, "\n%d\n", status);
- exit (1);
- }
-}
-
-static gboolean
-idle_run (gpointer data)
-{
- test_main (global_argc, global_argv);
- return FALSE;
-}
-
-gint
-main (gint argc, gchar **argv)
-{
- gtk_init (&argc, &argv);
-
- global_argc = argc;
- global_argv = argv;
-
- loop = g_main_loop_new (NULL, TRUE);
- g_idle_add (idle_run, NULL);
- g_main_loop_run (loop);
-
- return 0;
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef TEST_UTILS_H
-#define TEST_UTILS_H
-
-#include "e2k-types.h"
-#include "e2k-http-utils.h"
-
-void test_main (gint argc,
- gchar **argv);
-void test_quit (void);
-
-const gchar *test_get_password (const gchar *user,
- const gchar *host);
-E2kContext *test_get_context (const gchar *uri);
-E2kGlobalCatalog *test_get_gc (const gchar *server);
-
-void test_abort_if_http_error (E2kHTTPStatus status);
-
-/* lower-level util */
-gchar *test_ask_password (const gchar *prompt);
-
-#endif /* TEST_UTILS_H */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2002-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/*
- * This program takes account URL as input and dups E2KUri structure
- * values
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-
-#include "e2k-uri.h"
-#include "test-utils.h"
-
-const gchar *test_program_name = "urltest";
-
-static void
-dump_uri (E2kUri *euri) {
- const gchar *temp;
-
- printf ("URI contents \n");
- printf ("==================== \n");
-
- if (euri->protocol)
- printf("Protocol : %s \n", euri->protocol);
- else
- printf ("Protocol : NULL \n");
- if (euri->user)
- printf("User : %s \n", euri->user);
- else
- printf ("User : NULL \n");
- if (euri->domain)
- printf("Domain : %s \n", euri->domain);
- else
- printf ("Domain : NULL \n");
- if (euri->authmech)
- printf("Authmech : %s \n", euri->authmech);
- else
- printf ("Authmech : NULL \n");
- if (euri->passwd)
- printf("Password : %s \n", euri->passwd);
- else
- printf ("Password : NULL \n");
- if (euri->host)
- printf("Host : %s \n", euri->host);
- else
- printf ("Host : NULL \n");
- if (euri->port)
- printf("Port : %d \n", euri->port);
- else
- printf ("Port : NULL \n");
- if (euri->path)
- printf("Path : %s \n", euri->path);
- else
- printf ("Path : NULL \n");
- if (euri->params) {
- printf("\nParams : \n");
- temp = e2k_uri_get_param (euri, "ad_server");
- if (temp) printf ("\tAd server = %s\n", temp);
- else printf ("\tAd server = NULL \n");
-
- temp = e2k_uri_get_param (euri, "ad_limit");
- if (temp) printf ("\tAd Limit = %s\n", temp);
- else printf ("\tAd Limit = NULL\n");
-
- temp = e2k_uri_get_param (euri, "passwd_exp_warn_period");
- if (temp) printf ("\tPasswd expiry warn period = %s\n", temp);
- else printf ("\tPasswd expiry warn period = NULL \n");
-
- temp = e2k_uri_get_param (euri, "offline_sync");
- if (temp) printf ("\tOffline Sync = %s\n", temp);
- else printf ("\tOffline Sync = NULL \n");
-
- temp = e2k_uri_get_param (euri, "owa_path");
- if (temp) printf ("\tOwa path = %s\n", temp);
- else printf ("\tOwa path = NULL \n");
-
- temp = e2k_uri_get_param (euri, "pf_server");
- if (temp) printf ("\tPf server = %s\n", temp);
- else printf ("\tPf server = NULL \n");
-
- temp = e2k_uri_get_param (euri, "use_ssl");
- if (temp) printf ("\tSSL = %s\n", temp);
- else printf ("\tSSL = NULL\n");
-
- temp = e2k_uri_get_param (euri, "mailbox");
- if (temp) printf ("\tMailbox = %s\n", temp);
- else printf ("\tMailbox = NULL \n");
-
- temp = e2k_uri_get_param (euri, "filter");
- if (temp) printf ("\tFilter = %s\n", temp);
- else printf ("\tFilter = NULL \n");
-
- temp = e2k_uri_get_param (euri, "filter_junk");
- if (temp) printf ("\tFilter junk = %s\n", temp);
- else printf ("\tFilter junk = NULL \n");
-
- temp = e2k_uri_get_param (euri, "filter_junk_inbox");
- if (temp) printf ("\tFilter junk inbox = %s\n", temp);
- else printf ("\tFilter junk inbox = NULL \n");
-
- temp = e2k_uri_get_param (euri, "owa_protocol");
- if (temp) printf ("\tOwa protocol = %s\n", temp);
- else printf ("\tOwa protocol = NULL \n");
-
- temp = e2k_uri_get_param (euri, "owa_url");
- if (temp) printf ("\tOwa url = %s\n", temp);
- else printf ("\tOwa url = NULL \n");
- }
- else
- printf ("Params : NULL \n");
- if (euri->query)
- printf("Query : %s \n", euri->query);
- else
- printf ("Query : NULL \n");
- if (euri->fragment)
- printf("Fragment : %s \n", euri->fragment);
- else
- printf ("Fragment : NULL \n");
-}
-
-void
-test_main (gint argc, gchar **argv)
-{
- const gchar *url;
- E2kUri *euri;
-
- if (argc != 2) {
- fprintf (stderr, "Usage: %s url \n", argv[0]);
- exit (1);
- }
-
- url = argv[1];
- euri = e2k_uri_new (url);
- dump_uri (euri);
- test_quit ();
-}
+++ /dev/null
-if OS_WIN32
-WIN32_BOOTSTRAP_LIBS = \
- $(top_builddir)/win32/libedataserverui-1.2.la
-endif
-
-lib_LTLIBRARIES = \
- libexchange-storage-1.2.la
-
-# Fix the code to not use E_DATA_SERVER_UI_CFLAGS
-
-libexchange_storage_1_2_la_CPPFLAGS = \
- $(AM_CPPFLAGS) \
- -DG_LOG_DOMAIN=\"evolution-exchange-storage\" \
- -DPREFIX=\"$(prefix)\" \
- -DSYSCONFDIR=\""$(sysconfdir)"\" \
- -DDATADIR=\""$(datadir)"\" \
- -DLIBDIR=\""$(datadir)"\" \
- -DCONNECTOR_LOCALEDIR=\""$(localedir)\"" \
- -DCONNECTOR_GLADEDIR=\""$(gladedir)"\" \
- -I$(top_builddir)/servers/exchange/lib \
- -I$(top_srcdir) \
- -I$(top_srcdir)/servers/exchange/lib \
- -I$(top_srcdir)/servers/exchange/xntlm \
- $(KRB5_CFLAGS) \
- $(LDAP_CFLAGS) \
- $(SOUP_CFLAGS) \
- $(E_DATA_SERVER_CFLAGS) \
- $(E_DATA_SERVER_UI_CFLAGS)
-
-libexchange_storage_1_2_la_SOURCES = \
- e-folder.c \
- e-folder.h \
- e-folder-exchange.c \
- e-folder-exchange.h \
- e-folder-tree.c \
- e-folder-tree.h \
- e-folder-type-registry.c \
- e-folder-type-registry.h \
- e-storage.c \
- e-storage.h \
- exchange-account.c \
- exchange-account.h \
- exchange-esource.c \
- exchange-esource.h \
- exchange-folder-size.c \
- exchange-folder-size.h \
- exchange-hierarchy-favorites.c \
- exchange-hierarchy-favorites.h \
- exchange-hierarchy-foreign.c \
- exchange-hierarchy-foreign.h \
- exchange-hierarchy-gal.c \
- exchange-hierarchy-gal.h \
- exchange-hierarchy-somedav.c \
- exchange-hierarchy-somedav.h \
- exchange-hierarchy-webdav.c \
- exchange-hierarchy-webdav.h \
- exchange-hierarchy.c \
- exchange-hierarchy.h \
- exchange-oof.c \
- exchange-oof.h \
- exchange-types.h
-
-libexchange_storage_1_2_la_LIBADD = \
- $(WIN32_BOOTSTRAP_LIBS) \
- $(top_builddir)/servers/exchange/lib/libexchange.la \
- $(top_builddir)/servers/exchange/xntlm/libxntlm.la \
- $(top_builddir)/libedataserver/libedataserver-1.2.la \
- $(E_DATA_SERVER_LIBS) \
- $(E_DATA_SERVER_UI_LIBS) \
- $(LDAP_LIBS) \
- $(SOUP_LIBS) \
- $(SOCKET_LIBS)
-
-libexchange_storage_1_2_la_LDFLAGS = \
- $(KRB5_LIBS) \
- $(NO_UNDEFINED) \
- -version-info $(LIBEXCHANGE_STORAGE_CURRENT):$(LIBEXCHANGE_STORAGE_REVISION):$(LIBEXCHANGE_STORAGE_AGE)
-
-libexchange_storageincludedir = $(privincludedir)/exchange
-
-libexchange_storageinclude_HEADERS = \
- e-folder.h \
- e-folder-exchange.h \
- e-storage.h \
- exchange-account.h \
- exchange-constants.h \
- exchange-folder-size.h \
- exchange-hierarchy.h \
- exchange-hierarchy-somedav.h \
- exchange-hierarchy-webdav.h \
- exchange-hierarchy-foreign.h \
- exchange-oof.h \
- exchange-types.h \
- exchange-esource.h
-
-%-$(API_VERSION).pc: %.pc
- cp $< $@
-
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = libexchange-storage-$(API_VERSION).pc
-
-EXTRA_DIST = $(pkgconfig_DATA:-$(API_VERSION).pc=.pc.in)
-
-DISTCLEANFILES = $(pkgconfig_DATA)
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2002-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/xmlmemory.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-
-#include "libedataserver/e-source-list.h"
-#include "libedataserver/e-data-server-util.h"
-#include "libedataserver/e-xml-utils.h"
-
-#include "e-folder-exchange.h"
-#include "e2k-path.h"
-#include "e2k-uri.h"
-#include "exchange-account.h"
-#include "exchange-esource.h"
-#include "exchange-hierarchy.h"
-
-#define d(x)
-
-struct _EFolderExchangePrivate {
- ExchangeHierarchy *hier;
- gchar *internal_uri, *permanent_uri;
- gchar *outlook_class, *storage_dir;
- gchar *path;
- gint64 folder_size;
- gboolean has_subfolders;
- gboolean rescan_tree;
-};
-
-#define PARENT_TYPE E_TYPE_FOLDER
-static EFolderClass *parent_class = NULL;
-
-#define EF_CLASS(hier) (E_FOLDER_CLASS (G_OBJECT_GET_CLASS (hier)))
-
-static void dispose (GObject *object);
-static void finalize (GObject *object);
-
-static void
-class_init (GObjectClass *object_class)
-{
- parent_class = g_type_class_ref (PARENT_TYPE);
-
- /* methods */
- object_class->dispose = dispose;
- object_class->finalize = finalize;
-}
-
-static void
-init (GObject *object)
-{
- EFolderExchange *folder = E_FOLDER_EXCHANGE (object);
-
- folder->priv = g_new0 (EFolderExchangePrivate, 1);
- folder->priv->rescan_tree = TRUE;
-}
-
-static void
-dispose (GObject *object)
-{
- EFolderExchange *folder = E_FOLDER_EXCHANGE (object);
-
- if (folder->priv->hier) {
- g_object_unref (folder->priv->hier);
- folder->priv->hier = NULL;
- }
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-finalize (GObject *object)
-{
- EFolderExchange *folder = E_FOLDER_EXCHANGE (object);
-
- g_free (folder->priv->internal_uri);
- g_free (folder->priv->permanent_uri);
- g_free (folder->priv->outlook_class);
- g_free (folder->priv->storage_dir);
- g_free (folder->priv->path);
- g_free (folder->priv);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-E2K_MAKE_TYPE (e_folder_exchange, EFolderExchange, class_init, init, PARENT_TYPE)
-
-static gchar *
-sanitize_path (const gchar *path)
-{
- gchar **comps;
- gchar *new_path = NULL;
-
- if (!path)
- return g_strdup(""); /* ??? or NULL? */
-
- comps = g_strsplit (path, ";", 2);
- if (comps[1])
- new_path = g_strdup_printf ("%s%s", comps[0], comps[1]);
- else if (comps[0])
- new_path = g_strdup (comps[0]);
-
- g_strfreev (comps);
- return new_path;
-}
-
-#define d(x)
-
-/**
- * e_folder_exchange_new:
- * @hier: the #ExchangeHierarchy containing the new folder
- * @name: the display name of the folder
- * @type: the Evolution type of the folder (eg, "mail")
- * @outlook_class: the Outlook IPM class of the folder (eg, "IPM.Note")
- * @physical_uri: the "exchange:" URI of the folder
- * @internal_uri: the "http:" URI of the folder
- *
- * Return value: a new #EFolderExchange
- **/
-EFolder *
-e_folder_exchange_new (ExchangeHierarchy *hier, const gchar *name,
- const gchar *type, const gchar *outlook_class,
- const gchar *physical_uri, const gchar *internal_uri)
-{
- EFolderExchange *efe;
- EFolder *ef;
- gchar *sanitized_path;
-
- g_return_val_if_fail (EXCHANGE_IS_HIERARCHY (hier), NULL);
- g_return_val_if_fail (name != NULL, NULL);
- g_return_val_if_fail (type != NULL, NULL);
- g_return_val_if_fail (physical_uri != NULL, NULL);
- g_return_val_if_fail (internal_uri != NULL, NULL);
-
- d(g_print ("e_folder_exchange_new: name=[%s], type=[%s], internal_uri=[%s], physical_uri=[%s]\n",
- name, type, internal_uri, physical_uri));
-
- efe = g_object_new (E_TYPE_FOLDER_EXCHANGE, NULL);
- ef = (EFolder *)efe;
-
- e_folder_construct (ef, name, type, "");
-
- efe->priv->hier = hier;
- g_object_ref (hier);
-
- efe->priv->internal_uri = g_strdup (internal_uri);
- e_folder_set_physical_uri (ef, physical_uri);
-
- sanitized_path = sanitize_path (e2k_uri_path (physical_uri));
- e2k_uri_decode (sanitized_path);
- efe->priv->path = sanitized_path;
- d(g_print ("e_folder_exchange_new: sanitized=[%s]\n", sanitized_path));
-
- efe->priv->outlook_class = g_strdup (outlook_class);
-
- /* Add ESources */
- if (hier->type == EXCHANGE_HIERARCHY_PERSONAL ||
- hier->type == EXCHANGE_HIERARCHY_FAVORITES) {
-
- if ((strcmp (type, "calendar") == 0) ||
- (strcmp (type, "calendar/public") == 0)) {
- add_folder_esource (hier->account,
- EXCHANGE_CALENDAR_FOLDER,
- name,
- physical_uri);
- }
- else if ((strcmp (type, "tasks") == 0) ||
- (strcmp (type, "tasks/public") == 0)) {
- add_folder_esource (hier->account,
- EXCHANGE_TASKS_FOLDER,
- name,
- physical_uri);
- }
- else if ((strcmp (type, "contacts") == 0) ||
- (strcmp (type, "contacts/public") == 0)) {
- add_folder_esource (hier->account,
- EXCHANGE_CONTACTS_FOLDER,
- name,
- physical_uri);
- }
- }
- return ef;
-}
-
-/**
- * e_folder_exchange_get_internal_uri:
- * @folder: an #EFolderExchange
- *
- * Returns the folder's internal (http/https) URI. The caller
- * should not cache this value, since it may change if the server
- * sends a redirect when we try to use it.
- *
- * Return value: @folder's internal (http/https) URI
- **/
-const gchar *
-e_folder_exchange_get_internal_uri (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
-
- return E_FOLDER_EXCHANGE (folder)->priv->internal_uri;
-}
-
-/**
- * e_folder_exchange_set_internal_uri:
- * @folder: an #EFolderExchange
- * @internal_uri: new internal_uri value
- *
- * Updates @folder's internal URI to reflect a redirection response
- * from the server.
- **/
-void
-e_folder_exchange_set_internal_uri (EFolder *folder, const gchar *internal_uri)
-{
- EFolderExchange *efe;
-
- g_return_if_fail (E_IS_FOLDER_EXCHANGE (folder));
- g_return_if_fail (internal_uri != NULL);
-
- efe = E_FOLDER_EXCHANGE (folder);
- g_free (efe->priv->internal_uri);
- efe->priv->internal_uri = g_strdup (internal_uri);
-}
-
-/**
- * e_folder_exchange_get_path:
- * @folder: an #EFolderExchange
- *
- * Return value: @folder's path within its Evolution storage
- **/
-const gchar *
-e_folder_exchange_get_path (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
-
- return E_FOLDER_EXCHANGE (folder)->priv->path;
-}
-
-/**
- * e_folder_exchange_get_permanent_uri:
- * @folder: an #EFolderExchange
- *
- * Returns the folder's permanent URI. See docs/entryids for more
- * details.
- *
- * Return value: @folder's permanent URI
- **/
-const gchar *
-e_folder_exchange_get_permanent_uri (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
-
- return E_FOLDER_EXCHANGE (folder)->priv->permanent_uri;
-}
-
-/**
- * e_folder_exchange_set_permanent_uri:
- * @folder: an #EFolderExchange
- * @permanent_uri: permanent_uri value
- *
- * Sets @folder's permanent URI (which must, for obvious reasons, have
- * previously been unset).
- **/
-void
-e_folder_exchange_set_permanent_uri (EFolder *folder, const gchar *permanent_uri)
-{
- EFolderExchange *efe;
-
- g_return_if_fail (E_IS_FOLDER_EXCHANGE (folder));
-
- efe = E_FOLDER_EXCHANGE (folder);
- g_return_if_fail (efe->priv->permanent_uri == NULL && permanent_uri != NULL);
-
- efe->priv->permanent_uri = g_strdup (permanent_uri);
-}
-
-/**
- * e_folder_exchange_get_folder_size:
- * @folder: an #EFolderExchange
- *
- * Returns the folder's size. See docs/entryids for more
- * details.
- *
- * Return value: @folder's size
- **/
-gint64
-e_folder_exchange_get_folder_size (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), -1);
-
- return E_FOLDER_EXCHANGE (folder)->priv->folder_size;
-}
-
-/**
- * e_folder_exchange_set_folder_size:
- * @folder: an #EFolderExchange
- * @folder_size: folder size
- *
- * Sets @folder's folder_size
- **/
-void
-e_folder_exchange_set_folder_size (EFolder *folder, gint64 folder_size)
-{
- EFolderExchange *efe;
-
- g_return_if_fail (E_IS_FOLDER_EXCHANGE (folder));
-
- efe = E_FOLDER_EXCHANGE (folder);
-
- efe->priv->folder_size = folder_size;
-}
-
-/**
- * e_folder_exchange_get_has_subfolders:
- * @folder: an #EFolderExchange
- *
- * Return value: whether or not @folder has subfolders
- **/
-gboolean
-e_folder_exchange_get_has_subfolders (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), FALSE);
-
- return E_FOLDER_EXCHANGE (folder)->priv->has_subfolders;
-}
-
-/**
- * e_folder_exchange_set_has_subfolders
- * @folder: an #EFolderExchange
- * @has_subfolders: whether or not @folder has subfolders
- *
- * Sets @folder's has_subfolders flag.
- **/
-void
-e_folder_exchange_set_has_subfolders (EFolder *folder,
- gboolean has_subfolders)
-{
- g_return_if_fail (E_IS_FOLDER_EXCHANGE (folder));
-
- E_FOLDER_EXCHANGE (folder)->priv->has_subfolders = has_subfolders;
-}
-
-/**
- * e_folder_exchange_get_rescan_tree:
- * @folder: an #EFolderExchange
- *
- * Return value: whether or not to rescan @folder tree
- **/
-gboolean
-e_folder_exchange_get_rescan_tree (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), FALSE);
-
- return E_FOLDER_EXCHANGE (folder)->priv->rescan_tree;
-}
-
-/**
- * e_folder_exchange_set_rescan_tree
- * @folder: an #EFolderExchange
- * @rescan_tree: whether or not @folder needs to be rescanned
- *
- * Sets @folder's has_subfolders flag.
- **/
-void
-e_folder_exchange_set_rescan_tree (EFolder *folder,
- gboolean rescan_tree)
-{
- g_return_if_fail (E_IS_FOLDER_EXCHANGE (folder));
-
- E_FOLDER_EXCHANGE (folder)->priv->rescan_tree = rescan_tree;
-}
-
-/**
- * e_folder_exchange_get_outlook_class:
- * @folder: an #EFolderExchange
- *
- * Return value: @folder's Outlook IPM class
- **/
-const gchar *
-e_folder_exchange_get_outlook_class (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
-
- return E_FOLDER_EXCHANGE (folder)->priv->outlook_class;
-}
-
-/**
- * e_folder_exchange_get_hierarchy
- * @folder: an #EFolderExchange
- *
- * Return value: @folder's hierarchy
- **/
-ExchangeHierarchy *
-e_folder_exchange_get_hierarchy (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
-
- return E_FOLDER_EXCHANGE (folder)->priv->hier;
-}
-
-/**
- * e_folder_exchange_get_storage_file:
- * @folder: an #EFolderExchange
- * @filename: name of a file
- *
- * This returns a unique filename ending in @filename in the local
- * storage space reserved for @folder.
- *
- * Return value: the full filename, which must be freed.
- **/
-gchar *
-e_folder_exchange_get_storage_file (EFolder *folder, const gchar *filename)
-{
- EFolderExchange *efe;
- gchar *path;
-
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
-
- efe = (EFolderExchange *)folder;
-
- if (!efe->priv->storage_dir) {
- efe->priv->storage_dir = e_path_to_physical (
- efe->priv->hier->account->storage_dir,
- efe->priv->path);
- g_mkdir_with_parents (efe->priv->storage_dir, 0755);
- }
-
- path = g_build_filename (efe->priv->storage_dir, filename, NULL);
- return path;
-}
-
-/**
- * e_folder_exchange_save_to_file:
- * @folder: the folder
- * @filename: a filename
- *
- * Saves all relevant information about @folder to @filename.
- *
- * Return value: success or failure
- **/
-gboolean
-e_folder_exchange_save_to_file (EFolder *folder, const gchar *filename)
-{
- xmlDoc *doc;
- xmlNode *root;
- const gchar *name, *type, *outlook_class;
- const gchar *physical_uri, *internal_uri, *permanent_uri;
- gchar *folder_size;
- gint64 fsize;
- gint status;
-
- name = e_folder_get_name (folder);
- type = e_folder_get_type_string (folder);
- outlook_class = e_folder_exchange_get_outlook_class (folder);
- physical_uri = e_folder_get_physical_uri (folder);
- internal_uri = e_folder_exchange_get_internal_uri (folder);
- permanent_uri = e_folder_exchange_get_permanent_uri (folder);
-
- g_return_val_if_fail (name && type && physical_uri && internal_uri,
- FALSE);
-
- if ((fsize = e_folder_exchange_get_folder_size (folder)) >= 0)
- folder_size = g_strdup_printf ("%" G_GINT64_FORMAT, fsize);
- else
- return FALSE;
-
- doc = xmlNewDoc ((xmlChar *) "1.0");
- root = xmlNewDocNode (doc, NULL, (xmlChar *) "connector-folder", NULL);
- xmlNewProp (root, (xmlChar *) "version", (xmlChar *) "1");
- xmlDocSetRootElement (doc, root);
-
- xmlNewChild (
- root, NULL,
- (xmlChar *) "displayname",
- (xmlChar *) name);
- xmlNewChild (
- root, NULL,
- (xmlChar *) "type",
- (xmlChar *) type);
- xmlNewChild (
- root, NULL,
- (xmlChar *) "outlook_class",
- (xmlChar *) outlook_class);
- xmlNewChild (
- root, NULL,
- (xmlChar *) "physical_uri",
- (xmlChar *) physical_uri);
- xmlNewChild (
- root, NULL,
- (xmlChar *) "internal_uri",
- (xmlChar *) internal_uri);
- xmlNewChild (
- root, NULL,
- (xmlChar *) "folder_size",
- (xmlChar *) folder_size);
- if (permanent_uri)
- xmlNewChild (
- root, NULL,
- (xmlChar *) "permanent_uri",
- (xmlChar *) permanent_uri);
-
- status = e_xml_save_file (filename, doc);
-
- if (status < 0)
- g_unlink (filename);
-
- xmlFreeDoc (doc);
-
- g_free (folder_size);
-
- return status == 0;
-}
-
-/**
- * e_folder_exchange_new_from_file:
- * @hier: the hierarchy to create the folder under
- * @filename: a filename
- *
- * Loads information about a folder from a saved file.
- *
- * Return value: the folder, or %NULL on a failed load.
- **/
-EFolder *
-e_folder_exchange_new_from_file (ExchangeHierarchy *hier, const gchar *filename)
-{
- EFolder *folder = NULL;
- xmlDoc *doc;
- xmlNode *root, *node;
- xmlChar *version, *display_name = NULL;
- xmlChar *type = NULL, *outlook_class = NULL;
- xmlChar *physical_uri = NULL, *internal_uri = NULL;
- xmlChar *permanent_uri = NULL;
- xmlChar *folder_size = NULL;
-
- doc = e_xml_parse_file (filename);
-
- if (!doc)
- return NULL;
-
- root = xmlDocGetRootElement (doc);
- if (root == NULL || strcmp ((gchar *) root->name, "connector-folder") != 0) {
- xmlFreeDoc (doc);
- return NULL;
- }
- version = xmlGetProp (root, (xmlChar *) "version");
- if (!version) {
- xmlFreeDoc (doc);
- return NULL;
- }
- if (strcmp ((gchar *) version, "1") != 0) {
- xmlFreeDoc (doc);
- xmlFree (version);
- return NULL;
- }
- xmlFree (version);
-
- node = e_xml_get_child_by_name (root, (xmlChar *) "displayname");
- if (!node)
- goto done;
- display_name = xmlNodeGetContent (node);
-
- node = e_xml_get_child_by_name (root, (xmlChar *) "type");
- if (!node)
- goto done;
- type = xmlNodeGetContent (node);
-
- node = e_xml_get_child_by_name (root, (xmlChar *) "outlook_class");
- if (!node)
- goto done;
- outlook_class = xmlNodeGetContent (node);
-
- node = e_xml_get_child_by_name (root, (xmlChar *) "physical_uri");
- if (!node)
- goto done;
- physical_uri = xmlNodeGetContent (node);
-
- node = e_xml_get_child_by_name (root, (xmlChar *) "internal_uri");
- if (!node)
- goto done;
- internal_uri = xmlNodeGetContent (node);
-
- if (!display_name || !type || !physical_uri || !internal_uri)
- goto done;
-
- folder = e_folder_exchange_new (
- hier,
- (gchar *) display_name,
- (gchar *) type,
- (gchar *) outlook_class,
- (gchar *) physical_uri,
- (gchar *) internal_uri);
-
- node = e_xml_get_child_by_name (root, (xmlChar *) "permanent_uri");
- if (node) {
- permanent_uri = xmlNodeGetContent (node);
- e_folder_exchange_set_permanent_uri (folder, (gchar *) permanent_uri);
- }
-
- node = e_xml_get_child_by_name (root, (xmlChar *) "folder_size");
- if (node) {
- folder_size = xmlNodeGetContent (node);
- e_folder_exchange_set_folder_size (folder, atoi ((gchar *) folder_size));
- }
-
- done:
- xmlFree (display_name);
- xmlFree (type);
- xmlFree (outlook_class);
- xmlFree (physical_uri);
- xmlFree (internal_uri);
- xmlFree (permanent_uri);
- xmlFree (folder_size);
- xmlFreeDoc (doc);
-
- return folder;
-}
-
-/* E2kContext wrappers */
-#define E_FOLDER_EXCHANGE_CONTEXT(efe) (exchange_account_get_context (((EFolderExchange *)efe)->priv->hier->account))
-#define E_FOLDER_EXCHANGE_URI(efe) (((EFolderExchange *)efe)->priv->internal_uri)
-
-/**
- * e_folder_exchange_propfind:
- * @folder: the folder
- * @op: pointer to an #E2kOperation to use for cancellation
- * @props: array of properties to find
- * @nprops: length of @props
- * @results: on return, the results
- * @nresults: length of @results
- *
- * Performs a PROPFIND operation on @folder. This is a convenience
- * wrapper around e2k_context_propfind(), qv.
- *
- * Return value: the HTTP status
- **/
-E2kHTTPStatus
-e_folder_exchange_propfind (EFolder *folder, E2kOperation *op,
- const gchar **props, gint nprops,
- E2kResult **results, gint *nresults)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), E2K_HTTP_MALFORMED);
-
- return e2k_context_propfind (
- E_FOLDER_EXCHANGE_CONTEXT (folder), op,
- E_FOLDER_EXCHANGE_URI (folder),
- props, nprops, results, nresults);
-}
-
-/**
- * e_folder_exchange_bpropfind_start:
- * @folder: the folder
- * @op: pointer to an #E2kOperation to use for cancellation
- * @hrefs: array of URIs, relative to @folder
- * @nhrefs: length of @hrefs
- * @props: array of properties to find
- * @nprops: length of @props
- *
- * Begins a BPROPFIND (bulk PROPFIND) operation on @folder for @hrefs.
- * This is a convenience wrapper around e2k_context_bpropfind_start(),
- * qv.
- *
- * Return value: an iterator for getting the results
- **/
-E2kResultIter *
-e_folder_exchange_bpropfind_start (EFolder *folder, E2kOperation *op,
- const gchar **hrefs, gint nhrefs,
- const gchar **props, gint nprops)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
-
- return e2k_context_bpropfind_start (
- E_FOLDER_EXCHANGE_CONTEXT (folder), op,
- E_FOLDER_EXCHANGE_URI (folder),
- hrefs, nhrefs, props, nprops);
-}
-
-/**
- * e_folder_exchange_search_start:
- * @folder: the folder
- * @op: pointer to an #E2kOperation to use for cancellation
- * @props: the properties to search for
- * @nprops: size of @props array
- * @rn: the search restriction
- * @orderby: if non-%NULL, the field to sort the search results by
- * @ascending: %TRUE for an ascending search, %FALSE for descending.
- *
- * Begins a SEARCH on the contents of @folder. This is a convenience
- * wrapper around e2k_context_search_start(), qv.
- *
- * Return value: an iterator for returning the search results
- **/
-E2kResultIter *
-e_folder_exchange_search_start (EFolder *folder, E2kOperation *op,
- const gchar **props, gint nprops,
- E2kRestriction *rn, const gchar *orderby,
- gboolean ascending)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
-
- return e2k_context_search_start (
- E_FOLDER_EXCHANGE_CONTEXT (folder), op,
- E_FOLDER_EXCHANGE_URI (folder),
- props, nprops, rn, orderby, ascending);
-}
-
-/**
- * e_folder_exchange_subscribe:
- * @folder: the folder to subscribe to notifications on
- * @type: the type of notification to subscribe to
- * @min_interval: the minimum interval (in seconds) between
- * notifications.
- * @callback: the callback to call when a notification has been
- * received
- * @user_data: data to pass to @callback.
- *
- * This subscribes to change notifications of the given @type on
- * @folder. This is a convenience wrapper around
- * e2k_context_subscribe(), qv.
- **/
-void
-e_folder_exchange_subscribe (EFolder *folder,
- E2kContextChangeType type, gint min_interval,
- E2kContextChangeCallback callback,
- gpointer user_data)
-{
- g_return_if_fail (E_IS_FOLDER_EXCHANGE (folder));
-
- e2k_context_subscribe (E_FOLDER_EXCHANGE_CONTEXT (folder),
- E_FOLDER_EXCHANGE_URI (folder),
- type, min_interval, callback, user_data);
-}
-
-/**
- * e_folder_exchange_unsubscribe:
- * @folder: the folder to unsubscribe from
- *
- * Unsubscribes to all notifications on @folder. This is a convenience
- * wrapper around e2k_context_unsubscribe(), qv.
- **/
-void
-e_folder_exchange_unsubscribe (EFolder *folder)
-{
- E2kContext *ctx;
-
- g_return_if_fail (E_IS_FOLDER_EXCHANGE (folder));
-
- /* FIXME : This is a hack as of now. The free_folder in mail-stub
- gets called when we are in offline and the context is NULL then. */
- ctx = E_FOLDER_EXCHANGE_CONTEXT (folder);
- if (ctx) {
- e2k_context_unsubscribe (E_FOLDER_EXCHANGE_CONTEXT (folder),
- E_FOLDER_EXCHANGE_URI (folder));
- }
-}
-
-/**
- * e_folder_exchange_transfer_start:
- * @source: the source folder
- * @op: pointer to an #E2kOperation to use for cancellation
- * @dest: the destination folder
- * @source_hrefs: an array of hrefs to move, relative to @source_folder
- * @delete_originals: whether or not to delete the original objects
- *
- * Starts a BMOVE or BCOPY (depending on @delete_originals) operation
- * on @source. This is a convenience wrapper around
- * e2k_context_transfer_start(), qv.
- *
- * Return value: the iterator for the results
- **/
-E2kResultIter *
-e_folder_exchange_transfer_start (EFolder *source, E2kOperation *op,
- EFolder *dest, GPtrArray *source_hrefs,
- gboolean delete_originals)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (source), NULL);
-
- return e2k_context_transfer_start (E_FOLDER_EXCHANGE_CONTEXT (source), op,
- E_FOLDER_EXCHANGE_URI (source),
- E_FOLDER_EXCHANGE_URI (dest),
- source_hrefs, delete_originals);
-}
-
-/**
- * e_folder_exchange_put_new:
- * @folder: the folder to PUT the new item into
- * @op: pointer to an #E2kOperation to use for cancellation
- * @object_name: base name of the new object (not URI-encoded)
- * @test_callback: callback to use to test possible object URIs
- * @user_data: data for @test_callback
- * @content_type: MIME Content-Type of the data
- * @body: data to PUT
- * @length: length of @body
- * @location: if not %NULL, will contain the Location of the POSTed
- * object on return
- * @repl_uid: if not %NULL, will contain the Repl-UID of the POSTed
- * object on return
- *
- * PUTs data into @folder with a new name based on @object_name. This
- * is a convenience wrapper around e2k_context_put_new(), qv.
- *
- * Return value: the HTTP status
- **/
-E2kHTTPStatus
-e_folder_exchange_put_new (EFolder *folder,
- E2kOperation *op,
- const gchar *object_name,
- E2kContextTestCallback test_callback,
- gpointer user_data,
- const gchar *content_type,
- const gchar *body, gint length,
- gchar **location, gchar **repl_uid)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), E2K_HTTP_MALFORMED);
-
- return e2k_context_put_new (E_FOLDER_EXCHANGE_CONTEXT (folder), op,
- E_FOLDER_EXCHANGE_URI (folder),
- object_name, test_callback, user_data,
- content_type, body, length,
- location, repl_uid);
-}
-
-/**
- * e_folder_exchange_proppatch_new:
- * @folder: the folder to PROPPATCH a new object in
- * @op: pointer to an #E2kOperation to use for cancellation
- * @object_name: base name of the new object (not URI-encoded)
- * @test_callback: callback to use to test possible object URIs
- * @user_data: data for @test_callback
- * @props: the properties to set/remove
- * @location: if not %NULL, will contain the Location of the
- * PROPPATCHed object on return
- * @repl_uid: if not %NULL, will contain the Repl-UID of the
- * PROPPATCHed object on return
- *
- * PROPPATCHes data into @folder with a new name based on
- * @object_name. This is a convenience wrapper around
- * e2k_context_proppatch_new(), qv.
-
- * Return value: the HTTP status
- **/
-E2kHTTPStatus
-e_folder_exchange_proppatch_new (EFolder *folder, E2kOperation *op,
- const gchar *object_name,
- E2kContextTestCallback test_callback,
- gpointer user_data,
- E2kProperties *props,
- gchar **location, gchar **repl_uid)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), E2K_HTTP_MALFORMED);
-
- return e2k_context_proppatch_new (E_FOLDER_EXCHANGE_CONTEXT (folder), op,
- E_FOLDER_EXCHANGE_URI (folder),
- object_name,
- test_callback, user_data,
- props,
- location, repl_uid);
-}
-
-/**
- * e_folder_exchange_bproppatch_start:
- * @folder: the folder
- * @op: pointer to an #E2kOperation to use for cancellation
- * @hrefs: array of URIs, relative to @folder
- * @nhrefs: length of @hrefs
- * @props: the properties to set/remove
- * @create: whether or not to create the objects if they do not exist
- *
- * Begins BPROPPATCHing @hrefs under @folder. This is a convenience
- * wrapper around e2k_context_bproppatch_start(), qv.
- *
- * Return value: an iterator for getting the results of the BPROPPATCH
- **/
-E2kResultIter *
-e_folder_exchange_bproppatch_start (EFolder *folder, E2kOperation *op,
- const gchar **hrefs, gint nhrefs,
- E2kProperties *props, gboolean create)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
-
- return e2k_context_bproppatch_start (E_FOLDER_EXCHANGE_CONTEXT (folder), op,
- E_FOLDER_EXCHANGE_URI (folder),
- hrefs, nhrefs, props, create);
-}
-
-/**
- * e_folder_exchange_bdelete_start:
- * @folder: the folder
- * @op: pointer to an #E2kOperation to use for cancellation
- * @hrefs: array of URIs, relative to @folder, to delete
- * @nhrefs: length of @hrefs
- *
- * Begins a BDELETE (bulk DELETE) operation in @folder for @hrefs.
- * This is a convenience wrapper around e2k_context_bdelete_start(),
- * qv.
- *
- * Return value: an iterator for returning the results
- **/
-E2kResultIter *
-e_folder_exchange_bdelete_start (EFolder *folder, E2kOperation *op,
- const gchar **hrefs, gint nhrefs)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
-
- return e2k_context_bdelete_start (E_FOLDER_EXCHANGE_CONTEXT (folder), op,
- E_FOLDER_EXCHANGE_URI (folder),
- hrefs, nhrefs);
-}
-
-/**
- * e_folder_exchange_mkcol:
- * @folder: the folder to create
- * @op: pointer to an #E2kOperation to use for cancellation
- * @props: properties to set on the new folder, or %NULL
- * @permanent_url: if not %NULL, will contain the permanent URL of the
- * new folder on return
- *
- * Performs a MKCOL operation to create @folder, with optional
- * additional properties. This is a convenience wrapper around
- * e2k_context_mkcol(), qv.
- *
- * Return value: the HTTP status
- **/
-E2kHTTPStatus
-e_folder_exchange_mkcol (EFolder *folder, E2kOperation *op,
- E2kProperties *props,
- gchar **permanent_url)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), E2K_HTTP_MALFORMED);
-
- return e2k_context_mkcol (E_FOLDER_EXCHANGE_CONTEXT (folder), op,
- E_FOLDER_EXCHANGE_URI (folder),
- props, permanent_url);
-}
-
-/**
- * e_folder_exchange_delete:
- * @folder: the folder to delete
- * @op: pointer to an #E2kOperation to use for cancellation
- *
- * Attempts to DELETE @folder. This is a convenience wrapper around
- * e2k_context_delete(), qv.
- *
- * Return value: the HTTP status
- **/
-E2kHTTPStatus
-e_folder_exchange_delete (EFolder *folder, E2kOperation *op)
-{
- ExchangeHierarchy *hier;
- const gchar *folder_type, *physical_uri;
-
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), E2K_HTTP_MALFORMED);
- /* remove ESources */
- hier = e_folder_exchange_get_hierarchy (folder);
-
- if (hier->type == EXCHANGE_HIERARCHY_PERSONAL ||
- hier->type == EXCHANGE_HIERARCHY_FAVORITES) {
- folder_type = e_folder_get_type_string (folder);
- physical_uri = e_folder_get_physical_uri (folder);
-
- if ((strcmp (folder_type, "calendar") == 0) ||
- (strcmp (folder_type, "calendar/public") == 0)) {
- remove_folder_esource (hier->account,
- EXCHANGE_CALENDAR_FOLDER,
- physical_uri);
- }
- else if ((strcmp (folder_type, "tasks") == 0) ||
- (strcmp (folder_type, "tasks/public") == 0)) {
- remove_folder_esource (hier->account,
- EXCHANGE_TASKS_FOLDER,
- physical_uri);
- }
- else if ((strcmp (folder_type, "contacts") == 0) ||
- (strcmp (folder_type, "contacts/public") == 0)) {
- remove_folder_esource (hier->account,
- EXCHANGE_CONTACTS_FOLDER,
- physical_uri);
- }
- }
-
- return e2k_context_delete (E_FOLDER_EXCHANGE_CONTEXT (folder), op,
- E_FOLDER_EXCHANGE_URI (folder));
-}
-
-/**
- * e_folder_exchange_transfer_dir:
- * @source: source folder
- * @op: pointer to an #E2kOperation to use for cancellation
- * @dest: destination folder
- * @delete_original: whether or not to delete the original folder
- * @permanent_url: if not %NULL, will contain the permanent URL of the
- * new folder on return
- *
- * Performs a MOVE or COPY (depending on @delete_original) operation
- * on @source. This is a convenience wrapper around
- * e2k_context_transfer_dir(), qv.
- *
- * Return value: the HTTP status
- **/
-E2kHTTPStatus
-e_folder_exchange_transfer_dir (EFolder *source, E2kOperation *op,
- EFolder *dest, gboolean delete_original,
- gchar **permanent_url)
-{
- g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (source), E2K_HTTP_MALFORMED);
-
- return e2k_context_transfer_dir (E_FOLDER_EXCHANGE_CONTEXT (source), op,
- E_FOLDER_EXCHANGE_URI (source),
- E_FOLDER_EXCHANGE_URI (dest),
- delete_original, permanent_url);
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __E_FOLDER_EXCHANGE_H__
-#define __E_FOLDER_EXCHANGE_H__
-
-#include "e-folder.h"
-#include "exchange-types.h"
-#include "e2k-context.h"
-
-G_BEGIN_DECLS
-
-#define E_TYPE_FOLDER_EXCHANGE (e_folder_exchange_get_type ())
-#define E_FOLDER_EXCHANGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_FOLDER_EXCHANGE, EFolderExchange))
-#define E_FOLDER_EXCHANGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_FOLDER_EXCHANGE, EFolderExchangeClass))
-#define E_IS_FOLDER_EXCHANGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_FOLDER_EXCHANGE))
-#define E_IS_FOLDER_EXCHANGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_FOLDER_EXCHANGE))
-
-struct _EFolderExchange {
- EFolder parent;
-
- EFolderExchangePrivate *priv;
-};
-
-struct _EFolderExchangeClass {
- EFolderClass parent_class;
-
-};
-
-GType e_folder_exchange_get_type (void);
-
-EFolder *e_folder_exchange_new (ExchangeHierarchy *hier,
- const gchar *name,
- const gchar *type,
- const gchar *outlook_class,
- const gchar *phys_uri,
- const gchar *int_uri);
-
-EFolder *e_folder_exchange_new_from_file (ExchangeHierarchy *hier,
- const gchar *filename);
-gboolean e_folder_exchange_save_to_file (EFolder *folder,
- const gchar *filename);
-
-const gchar *e_folder_exchange_get_internal_uri (EFolder *folder);
-void e_folder_exchange_set_internal_uri (EFolder *folder,
- const gchar *internal_uri);
-
-const gchar *e_folder_exchange_get_path (EFolder *folder);
-
-const gchar *e_folder_exchange_get_permanent_uri (EFolder *folder);
-void e_folder_exchange_set_permanent_uri (EFolder *folder,
- const gchar *permanent_uri);
-
-gint64 e_folder_exchange_get_folder_size (EFolder *folder);
-void e_folder_exchange_set_folder_size (EFolder *folder, gint64 folder_size);
-
-gboolean e_folder_exchange_get_has_subfolders (EFolder *folder);
-void e_folder_exchange_set_has_subfolders (EFolder *folder,
- gboolean has_subfolders);
-
-gboolean e_folder_exchange_get_rescan_tree (EFolder *folder);
-void e_folder_exchange_set_rescan_tree (EFolder *folder,
- gboolean has_subfolders);
-
-const gchar *e_folder_exchange_get_outlook_class (EFolder *folder);
-
-gchar *e_folder_exchange_get_storage_file (EFolder *folder,
- const gchar *filename);
-
-ExchangeHierarchy *e_folder_exchange_get_hierarchy (EFolder *folder);
-
-/* E2kContext wrappers */
-E2kHTTPStatus e_folder_exchange_propfind (EFolder *folder,
- E2kOperation *op,
- const gchar **props,
- gint nprops,
- E2kResult **results,
- gint *nresults);
-E2kResultIter *e_folder_exchange_bpropfind_start (EFolder *folder,
- E2kOperation *op,
- const gchar **hrefs,
- gint nhrefs,
- const gchar **props,
- gint nprops);
-
-E2kResultIter *e_folder_exchange_search_start (EFolder *folder,
- E2kOperation *op,
- const gchar **props,
- gint nprops,
- E2kRestriction *rn,
- const gchar *orderby,
- gboolean ascending);
-
-void e_folder_exchange_subscribe (EFolder *folder,
- E2kContextChangeType,
- gint min_interval,
- E2kContextChangeCallback,
- gpointer user_data);
-void e_folder_exchange_unsubscribe (EFolder *folder);
-
-E2kResultIter *e_folder_exchange_transfer_start (EFolder *source,
- E2kOperation *op,
- EFolder *dest,
- GPtrArray *source_hrefs,
- gboolean delete_originals);
-
-E2kHTTPStatus e_folder_exchange_put_new (EFolder *folder,
- E2kOperation *op,
- const gchar *object_name,
- E2kContextTestCallback,
- gpointer user_data,
- const gchar *content_type,
- const gchar *body,
- gint length,
- gchar **location,
- gchar **repl_uid);
-
-E2kHTTPStatus e_folder_exchange_proppatch_new (EFolder *folder,
- E2kOperation *op,
- const gchar *object_name,
- E2kContextTestCallback,
- gpointer user_data,
- E2kProperties *props,
- gchar **location,
- gchar **repl_uid);
-
-E2kResultIter *e_folder_exchange_bproppatch_start (EFolder *folder,
- E2kOperation *op,
- const gchar **hrefs,
- gint nhrefs,
- E2kProperties *props,
- gboolean create);
-
-E2kResultIter *e_folder_exchange_bdelete_start (EFolder *folder,
- E2kOperation *op,
- const gchar **hrefs,
- gint nhrefs);
-
-E2kHTTPStatus e_folder_exchange_mkcol (EFolder *folder,
- E2kOperation *op,
- E2kProperties *props,
- gchar **permanent_url);
-E2kHTTPStatus e_folder_exchange_delete (EFolder *folder,
- E2kOperation *op);
-E2kHTTPStatus e_folder_exchange_transfer_dir (EFolder *source,
- E2kOperation *op,
- EFolder *dest,
- gboolean delete_original,
- gchar **permanent_url);
-
-G_END_DECLS
-
-#endif /* __E_FOLDER_EXCHANGE_H__ */
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-folder-set.c
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Author: Ettore Perazzoli
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e-folder-tree.h"
-
-#include <string.h>
-#include <glib.h>
-
-struct Folder {
- struct Folder *parent;
- gchar *path;
- gpointer data;
- GList *subfolders;
-};
-typedef struct Folder Folder;
-
-struct EFolderTree {
- GHashTable *path_to_folder;
- GHashTable *data_to_path;
-
- EFolderDestroyNotify folder_destroy_notify;
- gpointer folder_destroy_notify_closure;
-};
-
-/* Utility functions. */
-
-static gchar *
-get_parent_path (const gchar *path)
-{
- const gchar *last_separator;
-
- g_assert (g_path_is_absolute (path));
-
- last_separator = strrchr (path, '/');
-
- if (last_separator == path)
- return g_strdup ("/");
-
- return g_strndup (path, last_separator - path);
-}
-
-static void
-traverse_subtree (EFolderTree *tree,
- Folder *root_folder,
- EFolderTreeForeachFunc foreach_func,
- gpointer data)
-{
- GList *p;
-
- g_assert (foreach_func != NULL);
-
- (* foreach_func) (tree, root_folder->path, root_folder->data, data);
-
- for (p = root_folder->subfolders; p != NULL; p = p->next) {
- Folder *folder;
-
- folder = (Folder *) p->data;
- traverse_subtree (tree, folder, foreach_func, data);
- }
-}
-
-/* Folder handling. */
-
-static Folder *
-folder_new (const gchar *path,
- gpointer data)
-{
- Folder *folder;
-
- folder = g_new0 (Folder, 1);
- folder->path = g_strdup (path);
- folder->data = data;
-
- return folder;
-}
-
-static void
-folder_remove_subfolder (Folder *folder,
- Folder *subfolder)
-{
- folder->subfolders = g_list_remove (folder->subfolders, subfolder);
- subfolder->parent = NULL;
-}
-
-static void
-folder_add_subfolder (Folder *folder,
- Folder *subfolder)
-{
- folder->subfolders = g_list_prepend (folder->subfolders, subfolder);
- subfolder->parent = folder;
-}
-
-static void
-folder_destroy (Folder *folder)
-{
- g_assert (folder->subfolders == NULL);
-
- if (folder->parent != NULL)
- folder_remove_subfolder (folder->parent, folder);
-
- g_free (folder->path);
-
- g_free (folder);
-}
-
-static void
-remove_folder (EFolderTree *folder_tree,
- Folder *folder)
-{
- if (folder->subfolders != NULL) {
- GList *p;
-
- for (p = folder->subfolders; p != NULL; p = p->next) {
- Folder *subfolder;
-
- subfolder = (Folder *) p->data;
- subfolder->parent = NULL;
- remove_folder (folder_tree, subfolder);
- }
-
- g_list_free (folder->subfolders);
- folder->subfolders = NULL;
- }
-
- g_hash_table_remove (folder_tree->path_to_folder, folder->path);
- g_hash_table_remove (folder_tree->data_to_path, folder->data);
-
- if (folder_tree->folder_destroy_notify != NULL)
- (* folder_tree->folder_destroy_notify) (folder_tree,
- folder->path,
- folder->data,
- folder_tree->folder_destroy_notify_closure);
-
- folder_destroy (folder);
-}
-
-/**
- * e_folder_tree_new:
- * @folder_destroy_notify: Function to be called when a folder gets removed from the tree
- * @closure: Additional data to pass to @folder_destroy_notify
- *
- * Create a new EFolderTree.
- *
- * Return value: A pointer to the newly created EFolderTree.
- **/
-EFolderTree *
-e_folder_tree_new (EFolderDestroyNotify folder_destroy_notify,
- gpointer closure)
-{
- EFolderTree *new;
-
- new = g_new0 (EFolderTree, 1);
-
- new->folder_destroy_notify = folder_destroy_notify;
- new->folder_destroy_notify_closure = closure;
-
- new->path_to_folder = g_hash_table_new (g_str_hash, g_str_equal);
- new->data_to_path = g_hash_table_new (g_direct_hash, g_direct_equal);
-
- e_folder_tree_add (new, "/", NULL);
-
- return new;
-}
-
-/**
- * e_folder_tree_destroy:
- * @folder_tree: A pointer to an EFolderTree
- *
- * Destroy @folder_tree.
- **/
-void
-e_folder_tree_destroy (EFolderTree *folder_tree)
-{
- Folder *root_folder;
-
- g_return_if_fail (folder_tree != NULL);
-
- root_folder = g_hash_table_lookup (folder_tree->path_to_folder, "/");
- remove_folder (folder_tree, root_folder);
-
- g_hash_table_destroy (folder_tree->path_to_folder);
- g_hash_table_destroy (folder_tree->data_to_path);
-
- g_free (folder_tree);
-}
-
-/**
- * e_folder_tree_add:
- * @folder_tree: A pointer to an EFolderTree
- * @path: Path at which the new folder must be added
- * @data: Data associated with the new folder
- *
- * Insert a new folder at @path, with the specified @data.
- *
- * Return value: %TRUE if successful, %FALSE if failed.
- **/
-gboolean
-e_folder_tree_add (EFolderTree *folder_tree,
- const gchar *path,
- gpointer data)
-{
- Folder *parent_folder;
- Folder *folder;
- const gchar *existing_path;
- gchar *parent_path;
-
- g_return_val_if_fail (folder_tree != NULL, FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
- g_return_val_if_fail (g_path_is_absolute (path), FALSE);
-
- /* Can only "add" a new root folder if the tree is empty */
- if (! strcmp (path, "/")) {
- folder = g_hash_table_lookup (folder_tree->path_to_folder, path);
- if (folder) {
- if (folder->subfolders) {
- g_warning ("e_folder_tree_add() -- Trying to change root folder after adding children");
- return FALSE;
- }
- remove_folder (folder_tree, folder);
- }
-
- folder = folder_new (path, data);
- g_hash_table_insert (folder_tree->path_to_folder, folder->path, folder);
- g_hash_table_insert (folder_tree->data_to_path, data, folder->path);
- return TRUE;
- }
-
- parent_path = get_parent_path (path);
-
- parent_folder = g_hash_table_lookup (folder_tree->path_to_folder, parent_path);
- if (parent_folder == NULL) {
- g_warning ("e_folder_tree_add() -- Trying to add a subfolder to a path that does not exist yet -- %s",
- parent_path);
- g_free (parent_path);
- return FALSE;
- }
- g_free (parent_path);
-
- folder = g_hash_table_lookup (folder_tree->path_to_folder, path);
- if (folder != NULL) {
- g_warning ("e_folder_tree_add() -- Trying to add a subfolder for a path that already exists -- %s",
- path);
- return FALSE;
- }
-
- existing_path = g_hash_table_lookup (folder_tree->data_to_path, data);
- if (existing_path != NULL) {
- g_warning ("e_folder_tree_add() -- Trying to add a folder with duplicate data -- %s",
- path);
- return FALSE;
- }
-
- folder = folder_new (path, data);
- folder_add_subfolder (parent_folder, folder);
-
- g_hash_table_insert (folder_tree->path_to_folder, folder->path, folder);
- g_hash_table_insert (folder_tree->data_to_path, data, folder->path);
-
- return TRUE;
-}
-
-/**
- * e_folder_tree_remove:
- * @folder_tree: A pointer to an EFolderTree
- * @path: Path of the folder to remove
- *
- * Remove the folder at @path from @folder_tree.
- *
- * Return value: %TRUE if successful, %FALSE if failed.
- **/
-gboolean
-e_folder_tree_remove (EFolderTree *folder_tree,
- const gchar *path)
-{
- Folder *folder;
-
- g_return_val_if_fail (folder_tree != NULL, FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
- g_return_val_if_fail (g_path_is_absolute (path), FALSE);
-
- folder = g_hash_table_lookup (folder_tree->path_to_folder, path);
- if (folder == NULL)
- return FALSE;
-
- remove_folder (folder_tree, folder);
- return TRUE;
-}
-
-static void
-count_nodes (EFolderTree *tree,
- const gchar *path,
- gpointer data,
- gpointer closure)
-{
- gint *count = closure;
-
- (*count)++;
-}
-
-/**
- * e_folder_tree_get_count:
- * @folder_tree: A pointer to an EFolderTree
- *
- * Gets the number of folders in the tree
- *
- * Return value: The number of folders in the tree
- **/
-gint
-e_folder_tree_get_count (EFolderTree *folder_tree)
-{
- gint count = 0;
-
- e_folder_tree_foreach (folder_tree, count_nodes, &count);
-
- return count;
-}
-
-/**
- * e_folder_tree_get_folder:
- * @folder_tree: A pointer to an EFolderTree
- * @path: Path of the folder for which we want to get the data
- *
- * Get the data for the folder at @path.
- *
- * Return value: The pointer to the data for the folder at @path.
- **/
-gpointer
-e_folder_tree_get_folder (EFolderTree *folder_tree,
- const gchar *path)
-{
- Folder *folder;
-
- g_return_val_if_fail (folder_tree != NULL, NULL);
- g_return_val_if_fail (path != NULL, NULL);
- g_return_val_if_fail (g_path_is_absolute (path), NULL);
-
- folder = g_hash_table_lookup (folder_tree->path_to_folder, path);
- if (folder == NULL)
- return NULL;
-
- return folder->data;
-}
-
-/**
- * e_folder_tree_get_subfolders:
- * @folder_tree: A pointer to an EFolderTree
- * @path: A path in @folder_tree
- *
- * Get a list of the paths of the subfolders of @path.
- *
- * Return value: A list of pointers to the paths of the subfolders. The list
- * and the strings must be freed by the caller.
- **/
-GList *
-e_folder_tree_get_subfolders (EFolderTree *folder_tree,
- const gchar *path)
-{
- Folder *folder;
- GList *list;
- GList *p;
-
- g_return_val_if_fail (folder_tree != NULL, NULL);
- g_return_val_if_fail (path != NULL, NULL);
- g_return_val_if_fail (g_path_is_absolute (path), NULL);
-
- folder = g_hash_table_lookup (folder_tree->path_to_folder, path);
- if (folder == NULL)
- return NULL;
-
- list = NULL;
- for (p = folder->subfolders; p != NULL; p = p->next) {
- const Folder *folder;
-
- folder = (const Folder *) p->data;
- list = g_list_prepend (list, g_strdup (folder->path));
- }
-
- return list;
-}
-
-/**
- * e_folder_tree_foreach:
- * @folder_tree:
- * @foreach_func:
- * @data:
- *
- * Call @foreach_func with the specified @data for all the folders
- * in @folder_tree, starting at the root node.
- **/
-void
-e_folder_tree_foreach (EFolderTree *folder_tree,
- EFolderTreeForeachFunc foreach_func,
- gpointer data)
-{
- Folder *root_node;
-
- g_return_if_fail (folder_tree != NULL);
- g_return_if_fail (foreach_func != NULL);
-
- root_node = g_hash_table_lookup (folder_tree->path_to_folder, "/");
- if (root_node == NULL) {
- g_warning ("e_folder_tree_foreach -- What?! No root node!?");
- return;
- }
-
- traverse_subtree (folder_tree, root_node, foreach_func, data);
-}
-
-/**
- * e_folder_tree_get_path_for_data:
- * @folder_tree: A pointer to an EFolderTree
- * @data: The data for the folder for which the path is needed
- *
- * Look up the path for the specified @data.
- *
- * Return value: The path for the folder that holds that @data.
- **/
-const gchar *
-e_folder_tree_get_path_for_data (EFolderTree *folder_tree,
- gconstpointer data)
-{
- g_return_val_if_fail (folder_tree != NULL, NULL);
- g_return_val_if_fail (data != NULL, NULL);
-
- return (const gchar *) g_hash_table_lookup (folder_tree->data_to_path, data);
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-folder-tree.h
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Author: Ettore Perazzoli
- */
-
-#ifndef _E_FOLDER_TREE_H_
-#define _E_FOLDER_TREE_H_
-
-#include <glib.h>
-
-typedef struct EFolderTree EFolderTree;
-
-typedef void (* EFolderDestroyNotify) (EFolderTree *tree, const gchar *path, gpointer data, gpointer closure);
-typedef void (* EFolderTreeForeachFunc) (EFolderTree *tree, const gchar *path, gpointer data, gpointer closure);
-
-EFolderTree *e_folder_tree_new (EFolderDestroyNotify folder_destroy_notify,
- void *closure);
-
-void e_folder_tree_destroy (EFolderTree *folder_tree);
-
-gboolean e_folder_tree_add (EFolderTree *folder_tree,
- const gchar *path,
- void *data);
-gboolean e_folder_tree_remove (EFolderTree *folder_tree,
- const gchar *path);
-
-gint e_folder_tree_get_count (EFolderTree *folder_tree);
-
-void *e_folder_tree_get_folder (EFolderTree *folder_tree,
- const gchar *path);
-GList *e_folder_tree_get_subfolders (EFolderTree *folder_tree,
- const gchar *path);
-
-void e_folder_tree_foreach (EFolderTree *folder_tree,
- EFolderTreeForeachFunc foreach_func,
- void *data);
-
-const gchar *e_folder_tree_get_path_for_data (EFolderTree *folder_tree,
- const void *data);
-
-#endif /* _E_FOLDER_TREE_H_ */
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-folder-type-registry.c
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Author: Ettore Perazzoli
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e-folder-type-registry.h"
-
-#define PARENT_TYPE G_TYPE_OBJECT
-static GObjectClass *parent_class = NULL;
-
-G_DEFINE_TYPE (EFolderTypeRegistry, e_folder_type_registry, G_TYPE_OBJECT)
-
-typedef struct {
- gchar *name;
- gchar *icon_name;
-
- gchar *display_name;
- gchar *description;
-
- gboolean user_creatable;
-
- GList *accepted_dnd_types; /* gchar * */
-
- GObject *handler;
-
-} FolderType;
-
-struct EFolderTypeRegistryPrivate {
- GHashTable *name_to_type;
-};
-
-/* FolderType handling. */
-
-static FolderType *
-folder_type_new (const gchar *name,
- const gchar *icon_name,
- const gchar *display_name,
- const gchar *description,
- gboolean user_creatable,
- gint num_accepted_dnd_types,
- const gchar **accepted_dnd_types)
-{
- FolderType *new;
- gint i;
-
- new = g_new0 (FolderType, 1);
-
- new->name = g_strdup (name);
- new->icon_name = g_strdup (icon_name);
- new->display_name = g_strdup (display_name);
- new->description = g_strdup (description);
-
- new->user_creatable = user_creatable;
-
- new->accepted_dnd_types = NULL;
- for (i = 0; i < num_accepted_dnd_types; i++)
- new->accepted_dnd_types = g_list_prepend (new->accepted_dnd_types,
- g_strdup (accepted_dnd_types[i]));
- new->accepted_dnd_types = g_list_reverse (new->accepted_dnd_types);
-
- new->handler = NULL;
-
- return new;
-}
-
-static void
-folder_type_free (FolderType *folder_type)
-{
- g_free (folder_type->name);
- g_free (folder_type->icon_name);
- g_free (folder_type->display_name);
- g_free (folder_type->description);
-
- if (folder_type->handler != NULL)
- g_object_unref (folder_type->handler);
-
- g_free (folder_type);
-}
-
-static FolderType *
-get_folder_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name)
-{
- EFolderTypeRegistryPrivate *priv;
-
- priv = folder_type_registry->priv;
-
- return g_hash_table_lookup (priv->name_to_type, type_name);
-}
-
-static gboolean
-register_folder_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *name,
- const gchar *icon_name,
- const gchar *display_name,
- const gchar *description,
- gboolean user_creatable,
- gint num_accepted_dnd_types,
- const gchar **accepted_dnd_types)
-{
- EFolderTypeRegistryPrivate *priv;
- FolderType *folder_type;
-
- priv = folder_type_registry->priv;
-
- /* Make sure we don't add the same type twice. */
- if (get_folder_type (folder_type_registry, name) != NULL)
- return FALSE;
-
- folder_type = folder_type_new (name, icon_name,
- display_name, description,
- user_creatable,
- num_accepted_dnd_types, accepted_dnd_types);
- g_hash_table_insert (priv->name_to_type, folder_type->name, folder_type);
-
- return TRUE;
-}
-
-static gboolean
-set_handler (EFolderTypeRegistry *folder_type_registry,
- const gchar *name,
- GObject *handler)
-{
- EFolderTypeRegistryPrivate *priv;
- FolderType *folder_type;
-
- priv = folder_type_registry->priv;
-
- folder_type = get_folder_type (folder_type_registry, name);
- if (folder_type == NULL)
- return FALSE;
- if (folder_type->handler != NULL)
- return FALSE;
-
- g_object_ref (handler);
- folder_type->handler = handler;
-
- return TRUE;
-}
-
-/* GObject methods. */
-
-static void
-hash_forall_free_folder_type (gpointer key,
- gpointer value,
- gpointer data)
-{
- FolderType *folder_type;
-
- folder_type = (FolderType *) value;
- folder_type_free (folder_type);
-}
-
-static void
-impl_finalize (GObject *object)
-{
- EFolderTypeRegistry *folder_type_registry;
- EFolderTypeRegistryPrivate *priv;
-
- folder_type_registry = E_FOLDER_TYPE_REGISTRY (object);
- priv = folder_type_registry->priv;
-
- g_hash_table_foreach (priv->name_to_type, hash_forall_free_folder_type, NULL);
- g_hash_table_destroy (priv->name_to_type);
-
- g_free (priv);
-
- (* G_OBJECT_CLASS (parent_class)->finalize) (object);
-}
-
-static void
-e_folder_type_registry_class_init (EFolderTypeRegistryClass *class)
-{
- GObjectClass *object_class;
-
- object_class = G_OBJECT_CLASS (class);
- object_class->finalize = impl_finalize;
-
- parent_class = g_type_class_ref (PARENT_TYPE);
-}
-
-static void
-e_folder_type_registry_init (EFolderTypeRegistry *folder_type_registry)
-{
- EFolderTypeRegistryPrivate *priv;
-
- priv = g_new0 (EFolderTypeRegistryPrivate, 1);
- priv->name_to_type = g_hash_table_new (g_str_hash, g_str_equal);
-
- folder_type_registry->priv = priv;
-}
-
-EFolderTypeRegistry *
-e_folder_type_registry_new (void)
-{
- return g_object_new (E_TYPE_FOLDER_TYPE_REGISTRY, NULL);
-}
-
-gboolean
-e_folder_type_registry_register_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name,
- const gchar *icon_name,
- const gchar *display_name,
- const gchar *description,
- gboolean user_creatable,
- gint num_accepted_dnd_types,
- const gchar **accepted_dnd_types)
-{
- g_return_val_if_fail (E_IS_FOLDER_TYPE_REGISTRY (folder_type_registry), FALSE);
- g_return_val_if_fail (type_name != NULL, FALSE);
- g_return_val_if_fail (icon_name != NULL, FALSE);
-
- return register_folder_type (folder_type_registry, type_name, icon_name,
- display_name, description, user_creatable,
- num_accepted_dnd_types, accepted_dnd_types);
-}
-
-gboolean
-e_folder_type_registry_set_handler_for_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name,
- GObject *handler)
-{
- g_return_val_if_fail (E_IS_FOLDER_TYPE_REGISTRY (folder_type_registry), FALSE);
- /* g_return_val_if_fail (EVOLUTION_IS_SHELL_COMPONENT_CLIENT (handler), FALSE); */
-
- return set_handler (folder_type_registry, type_name, handler);
-}
-
-gboolean
-e_folder_type_registry_type_registered (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name)
-{
- EFolderTypeRegistryPrivate *priv;
-
- g_return_val_if_fail (E_IS_FOLDER_TYPE_REGISTRY (folder_type_registry), FALSE);
- g_return_val_if_fail (type_name != NULL, FALSE);
-
- priv = folder_type_registry->priv;
-
- if (get_folder_type (folder_type_registry, type_name) == NULL)
- return FALSE;
-
- return TRUE;
-}
-
-void
-e_folder_type_registry_unregister_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name)
-{
- EFolderTypeRegistryPrivate *priv;
- FolderType *folder_type;
-
- g_return_if_fail (E_IS_FOLDER_TYPE_REGISTRY (folder_type_registry));
- g_return_if_fail (type_name != NULL);
-
- priv = folder_type_registry->priv;
-
- folder_type = get_folder_type (folder_type_registry, type_name);
- if (folder_type == NULL)
- return;
-
- g_hash_table_remove (priv->name_to_type, folder_type->name);
- folder_type_free (folder_type);
-}
-
-static void
-get_type_names_hash_forall (gpointer key,
- gpointer value,
- gpointer data)
-{
- GList **type_name_list;
-
- type_name_list = (GList **) data;
-
- *type_name_list = g_list_prepend (*type_name_list, g_strdup ((const gchar *) key));
-}
-
-GList *
-e_folder_type_registry_get_type_names (EFolderTypeRegistry *folder_type_registry)
-{
- GList *type_name_list;
- EFolderTypeRegistryPrivate *priv;
-
- g_return_val_if_fail (E_IS_FOLDER_TYPE_REGISTRY (folder_type_registry), NULL);
-
- priv = folder_type_registry->priv;
-
- type_name_list = NULL;
- g_hash_table_foreach (priv->name_to_type, get_type_names_hash_forall, &type_name_list);
-
- return type_name_list;
-}
-
-const gchar *
-e_folder_type_registry_get_icon_name_for_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name)
-{
- const FolderType *folder_type;
-
- g_return_val_if_fail (E_IS_FOLDER_TYPE_REGISTRY (folder_type_registry), NULL);
- g_return_val_if_fail (type_name != NULL, NULL);
-
- folder_type = get_folder_type (folder_type_registry, type_name);
- if (folder_type == NULL)
- return NULL;
-
- return folder_type->icon_name;
-}
-
-GObject *
-e_folder_type_registry_get_handler_for_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name)
-{
- const FolderType *folder_type;
-
- g_return_val_if_fail (E_IS_FOLDER_TYPE_REGISTRY (folder_type_registry), NULL);
- g_return_val_if_fail (type_name != NULL, NULL);
-
- folder_type = get_folder_type (folder_type_registry, type_name);
- if (folder_type == NULL)
- return NULL;
-
- return folder_type->handler;
-}
-
-gboolean
-e_folder_type_registry_type_is_user_creatable (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name)
-{
- const FolderType *folder_type;
-
- g_return_val_if_fail (E_IS_FOLDER_TYPE_REGISTRY (folder_type_registry), FALSE);
- g_return_val_if_fail (type_name != NULL, FALSE);
-
- folder_type = get_folder_type (folder_type_registry, type_name);
- if (folder_type == NULL)
- return FALSE;
-
- return folder_type->user_creatable;
-}
-
-const gchar *
-e_folder_type_registry_get_display_name_for_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name)
-{
- const FolderType *folder_type;
-
- g_return_val_if_fail (E_IS_FOLDER_TYPE_REGISTRY (folder_type_registry), NULL);
- g_return_val_if_fail (type_name != NULL, NULL);
-
- folder_type = get_folder_type (folder_type_registry, type_name);
- if (folder_type == NULL)
- return NULL;
-
- return folder_type->display_name;
-}
-
-const gchar *
-e_folder_type_registry_get_description_for_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name)
-{
- const FolderType *folder_type;
-
- g_return_val_if_fail (E_IS_FOLDER_TYPE_REGISTRY (folder_type_registry), NULL);
- g_return_val_if_fail (type_name != NULL, NULL);
-
- folder_type = get_folder_type (folder_type_registry, type_name);
- if (folder_type == NULL)
- return NULL;
-
- return folder_type->description;
-}
-
-GList *
-e_folder_type_registry_get_accepted_dnd_types_for_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name)
-{
- const FolderType *folder_type;
-
- g_return_val_if_fail (E_IS_FOLDER_TYPE_REGISTRY (folder_type_registry), NULL);
- g_return_val_if_fail (type_name != NULL, NULL);
-
- folder_type = get_folder_type (folder_type_registry, type_name);
- if (folder_type == NULL)
- return NULL;
-
- return folder_type->accepted_dnd_types;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-folder-type-registry.h
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Author: Ettore Perazzoli
- */
-
-#ifndef _E_FOLDER_TYPE_REGISTRY_H_
-#define _E_FOLDER_TYPE_REGISTRY_H_
-
-#include <glib-object.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-
-G_BEGIN_DECLS
-
-#define E_TYPE_FOLDER_TYPE_REGISTRY (e_folder_type_registry_get_type ())
-#define E_FOLDER_TYPE_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_FOLDER_TYPE_REGISTRY, EFolderTypeRegistry))
-#define E_FOLDER_TYPE_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_FOLDER_TYPE_REGISTRY, EFolderTypeRegistryClass))
-#define E_IS_FOLDER_TYPE_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_FOLDER_TYPE_REGISTRY))
-#define E_IS_FOLDER_TYPE_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_FOLDER_TYPE_REGISTRY))
-
-typedef struct EFolderTypeRegistry EFolderTypeRegistry;
-typedef struct EFolderTypeRegistryPrivate EFolderTypeRegistryPrivate;
-typedef struct EFolderTypeRegistryClass EFolderTypeRegistryClass;
-
-struct EFolderTypeRegistry {
- GObject parent;
-
- EFolderTypeRegistryPrivate *priv;
-};
-
-struct EFolderTypeRegistryClass {
- GObjectClass parent_class;
-};
-
-GType e_folder_type_registry_get_type (void);
-EFolderTypeRegistry *e_folder_type_registry_new (void);
-
-gboolean e_folder_type_registry_register_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name,
- const gchar *icon_name,
- const gchar *display_name,
- const gchar *description,
- gboolean user_creatable,
- gint num_accepted_dnd_types,
- const gchar **accepted_dnd_types);
-gboolean e_folder_type_registry_set_handler_for_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name,
- GObject *handler);
-
-GList *e_folder_type_registry_get_type_names (EFolderTypeRegistry *folder_type_registry);
-
-gboolean e_folder_type_registry_type_registered (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name);
-void e_folder_type_registry_unregister_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name);
-
-const gchar *e_folder_type_registry_get_icon_name_for_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name);
-GObject *e_folder_type_registry_get_handler_for_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name);
-gboolean e_folder_type_registry_type_is_user_creatable (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name);
-const gchar *e_folder_type_registry_get_display_name_for_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name);
-const gchar *e_folder_type_registry_get_description_for_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name);
-
-GList *e_folder_type_registry_get_accepted_dnd_types_for_type (EFolderTypeRegistry *folder_type_registry,
- const gchar *type_name);
-
-G_END_DECLS
-
-#endif /* _E_FOLDER_TYPE_REGISTRY_H_ */
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-folder.c
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Author: Ettore Perazzoli
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e-folder.h"
-
-#include <string.h>
-#include <glib.h>
-#include <libedataserver/e-data-server-util.h>
-
-#define PARENT_TYPE G_TYPE_OBJECT
-static GObjectClass *parent_class = NULL;
-
-G_DEFINE_TYPE (EFolder, e_folder, G_TYPE_OBJECT)
-
-struct EFolderPrivate {
- gchar *name;
- gchar *type;
- gchar *description;
- gchar *physical_uri;
-
- gint child_highlight;
- gint unread_count;
-
- /* Folders have a default sorting priority of zero; when deciding the
- sort order in the Evolution folder tree, folders with the same
- priority value are compared by name, while folders with a higher
- priority number always come after the folders with a lower priority
- number. */
- gint sorting_priority;
-
- guint self_highlight : 1;
- guint is_stock : 1;
- guint can_sync_offline : 1;
- guint has_subfolders : 1;
-
- /* Custom icon for this folder; if NULL the folder will just use the
- icon for its type. */
- gchar *custom_icon_name;
-};
-
-enum {
- CHANGED,
- NAME_CHANGED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-/* EFolder methods. */
-
-static gboolean
-accept_drop (EFolder *folder, GdkDragContext *context,
- const gchar *target_type,
- GtkSelectionData *selection_data)
-{
- return FALSE;
-}
-
-/* GObject methods. */
-
-static void
-impl_finalize (GObject *object)
-{
- EFolder *folder;
- EFolderPrivate *priv;
-
- folder = E_FOLDER (object);
- priv = folder->priv;
-
- g_free (priv->name);
- g_free (priv->type);
- g_free (priv->description);
- g_free (priv->physical_uri);
-
- g_free (priv->custom_icon_name);
-
- g_free (priv);
-
- (* G_OBJECT_CLASS (parent_class)->finalize) (object);
-}
-
-static void
-e_folder_class_init (EFolderClass *klass)
-{
- GObjectClass *object_class;
-
- parent_class = g_type_class_ref (PARENT_TYPE);
-
- object_class = G_OBJECT_CLASS (klass);
- object_class->finalize = impl_finalize;
-
- klass->accept_drop = accept_drop;
- signals[CHANGED] = g_signal_new ("changed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (EFolderClass, changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- signals[NAME_CHANGED] = g_signal_new ("name_changed",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (EFolderClass, name_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-}
-
-static void
-e_folder_init (EFolder *folder)
-{
- EFolderPrivate *priv;
-
- priv = g_new0 (EFolderPrivate, 1);
- folder->priv = priv;
-}
-
-void
-e_folder_construct (EFolder *folder,
- const gchar *name,
- const gchar *type,
- const gchar *description)
-{
- EFolderPrivate *priv;
-
- g_return_if_fail (E_IS_FOLDER (folder));
- g_return_if_fail (name != NULL);
- g_return_if_fail (type != NULL);
-
- priv = folder->priv;
-
- priv->name = g_strdup (name);
- priv->type = g_strdup (type);
- priv->description = g_strdup (description);
-}
-
-EFolder *
-e_folder_new (const gchar *name,
- const gchar *type,
- const gchar *description)
-{
- EFolder *folder;
-
- g_return_val_if_fail (name != NULL, NULL);
- g_return_val_if_fail (type != NULL, NULL);
- g_return_val_if_fail (description != NULL, NULL);
-
- folder = g_object_new (E_TYPE_FOLDER, NULL);
-
- e_folder_construct (folder, name, type, description);
-
- return folder;
-}
-
-const gchar *
-e_folder_get_name (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER (folder), NULL);
-
- return folder->priv->name;
-}
-
-const gchar *
-e_folder_get_type_string (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER (folder), NULL);
-
- return folder->priv->type;
-}
-
-const gchar *
-e_folder_get_description (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER (folder), NULL);
-
- return folder->priv->description;
-}
-
-const gchar *
-e_folder_get_physical_uri (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER (folder), NULL);
-
- return folder->priv->physical_uri;
-}
-
-gint
-e_folder_get_unread_count (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER (folder), FALSE);
-
- return folder->priv->unread_count;
-}
-
-gboolean
-e_folder_get_highlighted (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER (folder), FALSE);
-
- return folder->priv->child_highlight || folder->priv->unread_count;
-}
-
-gboolean
-e_folder_get_is_stock (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER (folder), FALSE);
-
- return folder->priv->is_stock;
-}
-
-gboolean
-e_folder_get_can_sync_offline (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER (folder), FALSE);
-
- return folder->priv->can_sync_offline;
-}
-
-gboolean
-e_folder_get_has_subfolders (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER (folder), FALSE);
-
- return folder->priv->has_subfolders;
-}
-
-/**
- * e_folder_get_custom_icon:
- * @folder: An EFolder
- *
- * Get the name of the custom icon for @folder, or NULL if no custom icon is
- * associated with it.
- **/
-const gchar *
-e_folder_get_custom_icon_name (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER (folder), NULL);
-
- return folder->priv->custom_icon_name;
-}
-
-/**
- * e_folder_get_sorting_priority:
- * @folder: An EFolder
- *
- * Get the sorting priority for @folder.
- *
- * Return value: Sorting priority value for @folder.
- **/
-gint
-e_folder_get_sorting_priority (EFolder *folder)
-{
- g_return_val_if_fail (E_IS_FOLDER (folder), 0);
-
- return folder->priv->sorting_priority;
-}
-
-void
-e_folder_set_name (EFolder *folder,
- const gchar *name)
-{
- g_return_if_fail (E_IS_FOLDER (folder));
- g_return_if_fail (name != NULL);
-
- if (folder->priv->name == name)
- return;
-
- g_free (folder->priv->name);
- folder->priv->name = g_strdup (name);
-
- g_signal_emit (folder, signals[NAME_CHANGED], 0);
- g_signal_emit (folder, signals[CHANGED], 0);
-}
-
-void
-e_folder_set_type_string (EFolder *folder,
- const gchar *type)
-{
- g_return_if_fail (E_IS_FOLDER (folder));
- g_return_if_fail (type != NULL);
-
- g_free (folder->priv->type);
- folder->priv->type = g_strdup (type);
-
- g_signal_emit (folder, signals[CHANGED], 0);
-}
-
-void
-e_folder_set_description (EFolder *folder,
- const gchar *description)
-{
- g_return_if_fail (E_IS_FOLDER (folder));
- g_return_if_fail (description != NULL);
-
- g_free (folder->priv->description);
- folder->priv->description = g_strdup (description);
-
- g_signal_emit (folder, signals[CHANGED], 0);
-}
-
-void
-e_folder_set_physical_uri (EFolder *folder,
- const gchar *physical_uri)
-{
- g_return_if_fail (E_IS_FOLDER (folder));
- g_return_if_fail (physical_uri != NULL);
-
- if (folder->priv->physical_uri == physical_uri)
- return;
-
- g_free (folder->priv->physical_uri);
- folder->priv->physical_uri = g_strdup (physical_uri);
-
- g_signal_emit (folder, signals[CHANGED], 0);
-}
-
-void
-e_folder_set_unread_count (EFolder *folder,
- gint unread_count)
-{
- g_return_if_fail (E_IS_FOLDER (folder));
-
- folder->priv->unread_count = unread_count;
-
- g_signal_emit (folder, signals[CHANGED], 0);
-}
-
-void
-e_folder_set_child_highlight (EFolder *folder,
- gboolean highlighted)
-{
- g_return_if_fail (E_IS_FOLDER (folder));
-
- if (highlighted)
- folder->priv->child_highlight++;
- else
- folder->priv->child_highlight--;
-
- g_signal_emit (folder, signals[CHANGED], 0);
-}
-
-void
-e_folder_set_is_stock (EFolder *folder,
- gboolean is_stock)
-{
- g_return_if_fail (E_IS_FOLDER (folder));
-
- folder->priv->is_stock = !! is_stock;
-
- g_signal_emit (folder, signals[CHANGED], 0);
-}
-
-void
-e_folder_set_can_sync_offline (EFolder *folder,
- gboolean can_sync_offline)
-{
- g_return_if_fail (E_IS_FOLDER (folder));
-
- folder->priv->can_sync_offline = !! can_sync_offline;
-
- g_signal_emit (folder, signals[CHANGED], 0);
-}
-
-void
-e_folder_set_has_subfolders (EFolder *folder,
- gboolean has_subfolders)
-{
- g_return_if_fail (E_IS_FOLDER (folder));
-
- folder->priv->has_subfolders = !! has_subfolders;
-
- g_signal_emit (folder, signals[CHANGED], 0);
-}
-
-/**
- * e_folder_set_custom_icon_name:
- * @folder: An EFolder
- * @icon_name: Name of the icon to be set (to be found in the standard
- * Evolution icon dir)
- *
- * Set a custom icon for @folder (thus overriding the default icon, which is
- * the one associated to the type of the folder).
- **/
-void
-e_folder_set_custom_icon (EFolder *folder,
- const gchar *icon_name)
-{
- g_return_if_fail (E_IS_FOLDER (folder));
-
- if (icon_name == folder->priv->custom_icon_name)
- return;
-
- if (folder->priv->custom_icon_name == NULL
- || (icon_name != NULL && strcmp (icon_name, folder->priv->custom_icon_name) != 0)) {
- g_free (folder->priv->custom_icon_name);
- folder->priv->custom_icon_name = g_strdup (icon_name);
-
- g_signal_emit (folder, signals[CHANGED], 0);
- }
-}
-
-/**
- * e_folder_set_sorting_priority:
- * @folder: An EFolder
- * @sorting_priority: A sorting priority number
- *
- * Set the sorting priority for @folder. Folders have a default sorting
- * priority of zero; when deciding the sort order in the Evolution folder tree,
- * folders with the same priority value are compared by name, while folders
- * with a higher priority number always come after the folders with a lower
- * priority number.
- **/
-void
-e_folder_set_sorting_priority (EFolder *folder,
- gint sorting_priority)
-{
- g_return_if_fail (E_IS_FOLDER (folder));
-
- if (folder->priv->sorting_priority == sorting_priority)
- return;
-
- folder->priv->sorting_priority = sorting_priority;
-
- g_signal_emit (folder, signals[CHANGED], 0);
-}
-
-gboolean
-e_folder_accept_drop (EFolder *folder, GdkDragContext *context,
- const gchar *target_type,
- GtkSelectionData *selection_data)
-{
- g_return_val_if_fail (E_IS_FOLDER (folder), FALSE);
- g_return_val_if_fail (context != NULL, FALSE);
-
- return E_FOLDER_GET_CLASS (folder)->accept_drop (folder, context,
- target_type,
- selection_data);
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-folder.h
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Author: Ettore Perazzoli
- */
-
-#ifndef _E_FOLDER_H_
-#define _E_FOLDER_H_
-
-#include <glib-object.h>
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define E_TYPE_FOLDER (e_folder_get_type ())
-#define E_FOLDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_FOLDER, EFolder))
-#define E_FOLDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_FOLDER, EFolderClass))
-#define E_IS_FOLDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_FOLDER))
-#define E_IS_FOLDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_FOLDER))
-#define E_FOLDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_FOLDER, EFolderClass))
-
-typedef struct EFolder EFolder;
-typedef struct EFolderPrivate EFolderPrivate;
-typedef struct EFolderClass EFolderClass;
-
-struct EFolder {
- GObject parent;
-
- EFolderPrivate *priv;
-};
-
-struct EFolderClass {
- GObjectClass parent_class;
-
- /* Methods. */
- gboolean (* accept_drop) (EFolder *folder,
- GdkDragContext *context,
- const gchar *target_type,
- GtkSelectionData *selection_data);
-
- /* Signals. */
- void (* changed) (EFolder *folder);
- void (* name_changed) (EFolder *folder);
-};
-
-GType e_folder_get_type (void);
-void e_folder_construct (EFolder *folder,
- const gchar *name,
- const gchar *type,
- const gchar *description);
-EFolder *e_folder_new (const gchar *name,
- const gchar *type,
- const gchar *description);
-
-const gchar *e_folder_get_name (EFolder *folder);
-const gchar *e_folder_get_type_string (EFolder *folder);
-const gchar *e_folder_get_description (EFolder *folder);
-const gchar *e_folder_get_physical_uri (EFolder *folder);
-gint e_folder_get_unread_count (EFolder *folder);
-gboolean e_folder_get_highlighted (EFolder *folder);
-gboolean e_folder_get_is_stock (EFolder *folder);
-gboolean e_folder_get_can_sync_offline (EFolder *folder);
-gboolean e_folder_get_has_subfolders (EFolder *folder);
-const gchar *e_folder_get_custom_icon_name (EFolder *folder);
-gint e_folder_get_sorting_priority (EFolder *folder);
-
-void e_folder_set_name (EFolder *folder, const gchar *name);
-void e_folder_set_type_string (EFolder *folder, const gchar *type);
-void e_folder_set_description (EFolder *folder, const gchar *description);
-void e_folder_set_physical_uri (EFolder *folder, const gchar *physical_uri);
-void e_folder_set_unread_count (EFolder *folder, gint unread_count);
-void e_folder_set_child_highlight (EFolder *folder, gboolean highlighted);
-void e_folder_set_is_stock (EFolder *folder, gboolean is_stock);
-void e_folder_set_can_sync_offline (EFolder *folder, gboolean can_sync_offline);
-void e_folder_set_has_subfolders (EFolder *folder, gboolean has_subfolders);
-void e_folder_set_custom_icon (EFolder *folder, const gchar *icon_name);
-void e_folder_set_sorting_priority (EFolder *folder, gint sorting_priority);
-
-gboolean e_folder_accept_drop (EFolder *folder, GdkDragContext *context,
- const gchar *target_type,
- GtkSelectionData *selection_data);
-G_END_DECLS
-
-#endif /* _E_FOLDER_H_ */
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-storage.c
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Author: Ettore Perazzoli
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "e-storage.h"
-
-#include "e-folder-tree.h"
-
-#include <glib/gi18n-lib.h>
-#include <libedataserver/e-data-server-util.h>
-
-#include <string.h>
-
-#define PARENT_TYPE G_TYPE_OBJECT
-static GObjectClass *parent_class = NULL;
-
-G_DEFINE_TYPE (EStorage, e_storage, G_TYPE_OBJECT)
-
-struct EStoragePrivate {
- /* The set of folders we have in this storage. */
- EFolderTree *folder_tree;
-
- /* Internal name of the storage */
- gchar *name;
-};
-
-enum {
- NEW_FOLDER,
- UPDATED_FOLDER,
- REMOVED_FOLDER,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-/* Destroy notification function for the folders in the tree. */
-
-static void
-folder_destroy_notify (EFolderTree *tree,
- const gchar *path,
- gpointer data,
- gpointer closure)
-{
- EFolder *e_folder;
-
- if (data == NULL) {
- /* The root folder has no EFolder associated to it. */
- return;
- }
-
- e_folder = E_FOLDER (data);
- g_object_unref (e_folder);
-}
-
-/* Signal callbacks for the EFolders. */
-
-static void
-folder_changed_cb (EFolder *folder,
- gpointer data)
-{
- EStorage *storage;
- EStoragePrivate *priv;
- const gchar *path, *p;
- gboolean highlight;
-
- g_assert (E_IS_STORAGE (data));
-
- storage = E_STORAGE (data);
- priv = storage->priv;
-
- path = e_folder_tree_get_path_for_data (priv->folder_tree, folder);
- g_assert (path != NULL);
-
- g_signal_emit (storage, signals[UPDATED_FOLDER], 0, path);
-
- highlight = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (folder), "last_highlight"));
- if (highlight != e_folder_get_highlighted (folder)) {
- highlight = !highlight;
- g_object_set_data (G_OBJECT (folder), "last_highlight", GINT_TO_POINTER (highlight));
- p = strrchr (path, '/');
- if (p && p != path) {
- gchar *name;
-
- name = g_strndup (path, p - path);
- folder = e_folder_tree_get_folder (priv->folder_tree, name);
- g_free (name);
- if (folder)
- e_folder_set_child_highlight (folder, highlight);
- }
- }
-}
-
-/* GObject methods. */
-
-static void
-impl_finalize (GObject *object)
-{
- EStorage *storage;
- EStoragePrivate *priv;
-
- storage = E_STORAGE (object);
- priv = storage->priv;
-
- if (priv->folder_tree != NULL)
- e_folder_tree_destroy (priv->folder_tree);
-
- g_free (priv->name);
-
- g_free (priv);
-
- (* G_OBJECT_CLASS (parent_class)->finalize) (object);
-}
-
-/* EStorage methods. */
-
-static GList *
-impl_get_subfolder_paths (EStorage *storage,
- const gchar *path)
-{
- EStoragePrivate *priv;
-
- priv = storage->priv;
-
- return e_folder_tree_get_subfolders (priv->folder_tree, path);
-}
-
-static EFolder *
-impl_get_folder (EStorage *storage,
- const gchar *path)
-{
- EStoragePrivate *priv;
- EFolder *e_folder;
-
- priv = storage->priv;
-
- e_folder = (EFolder *) e_folder_tree_get_folder (priv->folder_tree, path);
-
- return e_folder;
-}
-
-static const gchar *
-impl_get_name (EStorage *storage)
-{
- return storage->priv->name;
-}
-
-static void
-impl_async_create_folder (EStorage *storage,
- const gchar *path,
- const gchar *type,
- EStorageResultCallback callback,
- gpointer data)
-{
- (* callback) (storage, E_STORAGE_NOTIMPLEMENTED, data);
-}
-
-static void
-impl_async_remove_folder (EStorage *storage,
- const gchar *path,
- EStorageResultCallback callback,
- gpointer data)
-{
- (* callback) (storage, E_STORAGE_NOTIMPLEMENTED, data);
-}
-
-static void
-impl_async_xfer_folder (EStorage *storage,
- const gchar *source_path,
- const gchar *destination_path,
- gboolean remove_source,
- EStorageResultCallback callback,
- gpointer data)
-{
- (* callback) (storage, E_STORAGE_NOTIMPLEMENTED, data);
-}
-
-static void
-impl_async_open_folder (EStorage *storage,
- const gchar *path,
- EStorageDiscoveryCallback callback,
- gpointer data)
-{
- (* callback) (storage, E_STORAGE_NOTIMPLEMENTED, NULL, data);
-}
-
-static gboolean
-impl_will_accept_folder (EStorage *storage,
- EFolder *new_parent,
- EFolder *source)
-{
- EStoragePrivate *priv = storage->priv;
- const gchar *parent_path, *source_path;
- gint source_len;
-
- /* By default, we only disallow dragging a folder into
- * a subfolder of itself.
- */
-
- if (new_parent == source)
- return FALSE;
-
- parent_path = e_folder_tree_get_path_for_data (priv->folder_tree,
- new_parent);
- source_path = e_folder_tree_get_path_for_data (priv->folder_tree,
- source);
- if (!parent_path || !source_path)
- return FALSE;
-
- source_len = strlen (source_path);
- if (!strncmp (parent_path, source_path, source_len) &&
- parent_path[source_len] == '/')
- return FALSE;
-
- return TRUE;
-}
-
-static void
-impl_async_discover_shared_folder (EStorage *storage,
- const gchar *owner,
- const gchar *folder_name,
- EStorageDiscoveryCallback callback,
- gpointer data)
-{
- (* callback) (storage, E_STORAGE_NOTIMPLEMENTED, NULL, data);
-}
-
-static void
-impl_async_remove_shared_folder (EStorage *storage,
- const gchar *path,
- EStorageResultCallback callback,
- gpointer data)
-{
- (* callback) (storage, E_STORAGE_NOTIMPLEMENTED, data);
-}
-
-/* Initialization. */
-
-static void
-e_storage_class_init (EStorageClass *class)
-{
- GObjectClass *object_class;
-
- object_class = G_OBJECT_CLASS (class);
- parent_class = g_type_class_ref (PARENT_TYPE);
-
- object_class->finalize = impl_finalize;
-
- class->get_subfolder_paths = impl_get_subfolder_paths;
- class->get_folder = impl_get_folder;
- class->get_name = impl_get_name;
- class->async_create_folder = impl_async_create_folder;
- class->async_remove_folder = impl_async_remove_folder;
- class->async_xfer_folder = impl_async_xfer_folder;
- class->async_open_folder = impl_async_open_folder;
- class->will_accept_folder = impl_will_accept_folder;
-
- class->async_discover_shared_folder = impl_async_discover_shared_folder;
- class->async_remove_shared_folder = impl_async_remove_shared_folder;
- signals[NEW_FOLDER] =
- g_signal_new ("new_folder",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (EStorageClass, new_folder),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1,
- G_TYPE_STRING);
- signals[UPDATED_FOLDER] =
- g_signal_new ("updated_folder",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (EStorageClass, updated_folder),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1,
- G_TYPE_STRING);
- signals[REMOVED_FOLDER] =
- g_signal_new ("removed_folder",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET (EStorageClass, removed_folder),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1,
- G_TYPE_STRING);
-}
-
-static void
-e_storage_init (EStorage *storage)
-{
- EStoragePrivate *priv;
-
- priv = g_new0 (EStoragePrivate, 1);
-
- priv->folder_tree = e_folder_tree_new (folder_destroy_notify, NULL);
-
- storage->priv = priv;
-}
-
-/* Creation. */
-
-void
-e_storage_construct (EStorage *storage,
- const gchar *name,
- EFolder *root_folder)
-{
- EStoragePrivate *priv;
-
- g_return_if_fail (E_IS_STORAGE (storage));
-
- priv = storage->priv;
-
- priv->name = g_strdup (name);
-
- e_storage_new_folder (storage, "/", root_folder);
-}
-
-EStorage *
-e_storage_new (const gchar *name,
- EFolder *root_folder)
-{
- EStorage *new;
-
- new = g_object_new (e_storage_get_type (), NULL);
-
- e_storage_construct (new, name, root_folder);
-
- return new;
-}
-
-gboolean
-e_storage_path_is_absolute (const gchar *path)
-{
- g_return_val_if_fail (path != NULL, FALSE);
-
- return *path == '/';
-}
-
-gboolean
-e_storage_path_is_relative (const gchar *path)
-{
- g_return_val_if_fail (path != NULL, FALSE);
-
- return *path != '/';
-}
-
-GList *
-e_storage_get_subfolder_paths (EStorage *storage,
- const gchar *path)
-{
- g_return_val_if_fail (E_IS_STORAGE (storage), NULL);
- g_return_val_if_fail (path != NULL, NULL);
- g_return_val_if_fail (g_path_is_absolute (path), NULL);
-
- return (* E_STORAGE_GET_CLASS (storage)->get_subfolder_paths) (storage, path);
-}
-
-EFolder *
-e_storage_get_folder (EStorage *storage,
- const gchar *path)
-{
- g_return_val_if_fail (E_IS_STORAGE (storage), NULL);
- g_return_val_if_fail (path != NULL, NULL);
- g_return_val_if_fail (e_storage_path_is_absolute (path), NULL);
-
- return (* E_STORAGE_GET_CLASS (storage)->get_folder) (storage, path);
-}
-
-const gchar *
-e_storage_get_name (EStorage *storage)
-{
- g_return_val_if_fail (E_IS_STORAGE (storage), NULL);
-
- return (* E_STORAGE_GET_CLASS (storage)->get_name) (storage);
-}
-
-/* Folder operations. */
-
-void
-e_storage_async_create_folder (EStorage *storage,
- const gchar *path,
- const gchar *type,
- EStorageResultCallback callback,
- gpointer data)
-{
- g_return_if_fail (E_IS_STORAGE (storage));
- g_return_if_fail (path != NULL);
- g_return_if_fail (g_path_is_absolute (path));
- g_return_if_fail (type != NULL);
- g_return_if_fail (callback != NULL);
-
- (* E_STORAGE_GET_CLASS (storage)->async_create_folder) (storage, path, type, callback, data);
-}
-
-void
-e_storage_async_remove_folder (EStorage *storage,
- const gchar *path,
- EStorageResultCallback callback,
- void *data)
-{
- g_return_if_fail (E_IS_STORAGE (storage));
- g_return_if_fail (path != NULL);
- g_return_if_fail (g_path_is_absolute (path));
- g_return_if_fail (callback != NULL);
-
- (* E_STORAGE_GET_CLASS (storage)->async_remove_folder) (storage, path, callback, data);
-}
-
-void
-e_storage_async_xfer_folder (EStorage *storage,
- const gchar *source_path,
- const gchar *destination_path,
- const gboolean remove_source,
- EStorageResultCallback callback,
- gpointer data)
-{
- g_return_if_fail (E_IS_STORAGE (storage));
- g_return_if_fail (source_path != NULL);
- g_return_if_fail (g_path_is_absolute (source_path));
- g_return_if_fail (destination_path != NULL);
- g_return_if_fail (g_path_is_absolute (destination_path));
-
- if (strcmp (source_path, destination_path) == 0) {
- (* callback) (storage, E_STORAGE_OK, data);
- return;
- }
-
- if (remove_source) {
- gint destination_len;
- gint source_len;
-
- source_len = strlen (source_path);
- destination_len = strlen (destination_path);
-
- if (source_len < destination_len
- && destination_path[source_len] == '/'
- && strncmp (destination_path, source_path, source_len) == 0) {
- (* callback) (storage, E_STORAGE_CANTMOVETODESCENDANT, data);
- return;
- }
- }
-
- (* E_STORAGE_GET_CLASS (storage)->async_xfer_folder) (storage, source_path, destination_path, remove_source, callback, data);
-}
-
-void
-e_storage_async_open_folder (EStorage *storage,
- const gchar *path,
- EStorageDiscoveryCallback callback,
- gpointer data)
-{
- EStoragePrivate *priv;
- EFolder *folder;
-
- g_return_if_fail (E_IS_STORAGE (storage));
- g_return_if_fail (path != NULL);
- g_return_if_fail (g_path_is_absolute (path));
-
- priv = storage->priv;
-
- folder = e_folder_tree_get_folder (priv->folder_tree, path);
- if (folder == NULL) {
- (* callback) (storage, E_STORAGE_NOTFOUND, path, data);
- return;
- }
-
- if (! e_folder_get_has_subfolders (folder)) {
- (* callback) (storage, E_STORAGE_OK, path, data);
- return;
- }
-
- (* E_STORAGE_GET_CLASS (storage)->async_open_folder) (storage, path, callback, data);
-}
-
-gboolean
-e_storage_will_accept_folder (EStorage *storage,
- EFolder *new_parent, EFolder *source)
-{
- g_return_val_if_fail (E_IS_STORAGE (storage), FALSE);
- g_return_val_if_fail (E_IS_FOLDER (new_parent), FALSE);
- g_return_val_if_fail (E_IS_FOLDER (source), FALSE);
-
- return (* E_STORAGE_GET_CLASS (storage)->will_accept_folder) (storage, new_parent, source);
-}
-
-/* Shared folders. */
-
-void
-e_storage_async_discover_shared_folder (EStorage *storage,
- const gchar *owner,
- const gchar *folder_name,
- EStorageDiscoveryCallback callback,
- gpointer data)
-{
- g_return_if_fail (E_IS_STORAGE (storage));
- g_return_if_fail (owner != NULL);
- g_return_if_fail (folder_name != NULL);
-
- (* E_STORAGE_GET_CLASS (storage)->async_discover_shared_folder) (storage, owner, folder_name, callback, data);
-}
-
-void
-e_storage_cancel_discover_shared_folder (EStorage *storage,
- const gchar *owner,
- const gchar *folder_name)
-{
- g_return_if_fail (E_IS_STORAGE (storage));
- g_return_if_fail (owner != NULL);
- g_return_if_fail (folder_name != NULL);
- g_return_if_fail (E_STORAGE_GET_CLASS (storage)->cancel_discover_shared_folder != NULL);
-
- (* E_STORAGE_GET_CLASS (storage)->cancel_discover_shared_folder) (storage, owner, folder_name);
-}
-
-void
-e_storage_async_remove_shared_folder (EStorage *storage,
- const gchar *path,
- EStorageResultCallback callback,
- gpointer data)
-{
- g_return_if_fail (E_IS_STORAGE (storage));
- g_return_if_fail (path != NULL);
- g_return_if_fail (g_path_is_absolute (path));
-
- (* E_STORAGE_GET_CLASS (storage)->async_remove_shared_folder) (storage, path, callback, data);
-}
-
-const gchar *
-e_storage_result_to_string (EStorageResult result)
-{
- switch (result) {
- case E_STORAGE_OK:
- return _("No error");
- case E_STORAGE_GENERICERROR:
- return _("Generic error");
- case E_STORAGE_EXISTS:
- return _("A folder with the same name already exists");
- case E_STORAGE_INVALIDTYPE:
- return _("The specified folder type is not valid");
- case E_STORAGE_IOERROR:
- return _("I/O error");
- case E_STORAGE_NOSPACE:
- return _("Not enough space to create the folder");
- case E_STORAGE_NOTEMPTY:
- return _("The folder is not empty");
- case E_STORAGE_NOTFOUND:
- return _("The specified folder was not found");
- case E_STORAGE_NOTIMPLEMENTED:
- return _("Function not implemented in this storage");
- case E_STORAGE_PERMISSIONDENIED:
- return _("Permission denied");
- case E_STORAGE_UNSUPPORTEDOPERATION:
- return _("Operation not supported");
- case E_STORAGE_UNSUPPORTEDTYPE:
- return _("The specified type is not supported in this storage");
- case E_STORAGE_CANTCHANGESTOCKFOLDER:
- return _("The specified folder cannot be modified or removed");
- case E_STORAGE_CANTMOVETODESCENDANT:
- return _("Cannot make a folder a child of one of its descendants");
- case E_STORAGE_INVALIDNAME:
- return _("Cannot create a folder with that name");
- case E_STORAGE_NOTONLINE:
- return _("This operation cannot be performed in off-line mode");
- default:
- return _("Unknown error");
- }
-}
-
-/* Public utility functions. */
-
-typedef struct {
- const gchar *physical_uri;
- gchar *retval;
-} GetPathForPhysicalUriForeachData;
-
-static void
-get_path_for_physical_uri_foreach (EFolderTree *folder_tree,
- const gchar *path,
- gpointer path_data,
- gpointer user_data)
-{
- GetPathForPhysicalUriForeachData *foreach_data;
- const gchar *physical_uri;
- EFolder *e_folder;
-
- foreach_data = (GetPathForPhysicalUriForeachData *) user_data;
- if (foreach_data->retval != NULL)
- return;
-
- e_folder = (EFolder *) path_data;
- if (e_folder == NULL)
- return;
-
- physical_uri = e_folder_get_physical_uri (e_folder);
- if (physical_uri == NULL)
- return;
-
- if (strcmp (foreach_data->physical_uri, physical_uri) == 0)
- foreach_data->retval = g_strdup (path);
-}
-
-/**
- * e_storage_get_path_for_physical_uri:
- * @storage: A storage
- * @physical_uri: A physical URI
- *
- * Look for the folder having the specified @physical_uri.
- *
- * Return value: The path of the folder having the specified @physical_uri in
- * @storage. If such a folder does not exist, just return NULL. The return
- * value must be freed by the caller.
- **/
-gchar *
-e_storage_get_path_for_physical_uri (EStorage *storage,
- const gchar *physical_uri)
-{
- GetPathForPhysicalUriForeachData foreach_data;
- EStoragePrivate *priv;
-
- g_return_val_if_fail (E_IS_STORAGE (storage), NULL);
- g_return_val_if_fail (physical_uri != NULL, NULL);
-
- priv = storage->priv;
-
- foreach_data.physical_uri = physical_uri;
- foreach_data.retval = NULL;
-
- e_folder_tree_foreach (priv->folder_tree, get_path_for_physical_uri_foreach, &foreach_data);
-
- return foreach_data.retval;
-}
-
-/* Protected functions. */
-
-/* These functions are used by subclasses to add and remove folders from the
- state stored in the storage object. */
-
-static void
-remove_subfolders_except (EStorage *storage, const gchar *path, const gchar *except)
-{
- EStoragePrivate *priv;
- GList *subfolders, *f;
- const gchar *folder_path;
-
- priv = storage->priv;
-
- subfolders = e_folder_tree_get_subfolders (priv->folder_tree, path);
- for (f = subfolders; f; f = f->next) {
- folder_path = f->data;
- if (!except || strcmp (folder_path, except) != 0)
- e_storage_removed_folder (storage, folder_path);
- }
- for (f = subfolders; f != NULL; f = f->next)
- g_free (f->data);
-
- g_list_free (subfolders);
-}
-
-gboolean
-e_storage_new_folder (EStorage *storage,
- const gchar *path,
- EFolder *e_folder)
-{
- EStoragePrivate *priv;
- gchar *parent_path, *p;
- EFolder *parent;
-
- g_return_val_if_fail (E_IS_STORAGE (storage), FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
- g_return_val_if_fail (g_path_is_absolute (path), FALSE);
- g_return_val_if_fail (E_IS_FOLDER (e_folder), FALSE);
-
- priv = storage->priv;
-
- if (! e_folder_tree_add (priv->folder_tree, path, e_folder))
- return FALSE;
-
- /* If this is the child of a folder that has a pseudo child,
- * remove the pseudo child now.
- */
- p = strrchr (path, '/');
- if (p && p != path)
- parent_path = g_strndup (path, p - path);
- else
- parent_path = g_strdup ("/");
- parent = e_folder_tree_get_folder (priv->folder_tree, parent_path);
- if (parent && e_folder_get_has_subfolders (parent)) {
- remove_subfolders_except (storage, parent_path, path);
- e_folder_set_has_subfolders (parent, FALSE);
- }
- g_free (parent_path);
-
- g_signal_connect_object (e_folder, "changed", G_CALLBACK (folder_changed_cb), storage, 0);
-
- g_signal_emit (storage, signals[NEW_FOLDER], 0, path);
-
- folder_changed_cb (e_folder, storage);
-
- return TRUE;
-}
-
-/* This really should be called e_storage_set_has_subfolders, but then
- * it would look like it was an EStorageSet function. (Fact o' the
- * day: The word "set" has more distinct meanings than any other word
- * in the English language.) Anyway, we now return you to your
- * regularly scheduled source code, already in progress.
- */
-gboolean
-e_storage_declare_has_subfolders (EStorage *storage,
- const gchar *path,
- const gchar *message)
-{
- EStoragePrivate *priv;
- EFolder *parent, *pseudofolder;
- gchar *pseudofolder_path;
- gboolean ok;
-
- g_return_val_if_fail (E_IS_STORAGE (storage), FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
- g_return_val_if_fail (g_path_is_absolute (path), FALSE);
- g_return_val_if_fail (message != NULL, FALSE);
-
- priv = storage->priv;
-
- parent = e_folder_tree_get_folder (priv->folder_tree, path);
- if (parent == NULL)
- return FALSE;
- if (e_folder_get_has_subfolders (parent))
- return TRUE;
-
- remove_subfolders_except (storage, path, NULL);
-
- pseudofolder = e_folder_new (message, "working", "");
- if (strcmp (path, "/") == 0)
- pseudofolder_path = g_strdup_printf ("/%s", message);
- else
- pseudofolder_path = g_strdup_printf ("%s/%s", path, message);
- e_folder_set_physical_uri (pseudofolder, pseudofolder_path);
-
- ok = e_storage_new_folder (storage, pseudofolder_path, pseudofolder);
- g_free (pseudofolder_path);
- if (!ok) {
- g_object_unref (pseudofolder);
- return FALSE;
- }
-
- e_folder_set_has_subfolders (parent, TRUE);
- return TRUE;
-}
-
-gboolean
-e_storage_get_has_subfolders (EStorage *storage,
- const gchar *path)
-{
- EStoragePrivate *priv;
- EFolder *folder;
-
- g_return_val_if_fail (E_IS_STORAGE (storage), FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
- g_return_val_if_fail (g_path_is_absolute (path), FALSE);
-
- priv = storage->priv;
-
- folder = e_folder_tree_get_folder (priv->folder_tree, path);
-
- return folder && e_folder_get_has_subfolders (folder);
-}
-
-gboolean
-e_storage_removed_folder (EStorage *storage,
- const gchar *path)
-{
- EStoragePrivate *priv;
- EFolder *folder;
- const gchar *p;
-
- g_return_val_if_fail (E_IS_STORAGE (storage), FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
- g_return_val_if_fail (g_path_is_absolute (path), FALSE);
-
- priv = storage->priv;
-
- folder = e_folder_tree_get_folder (priv->folder_tree, path);
- if (folder == NULL)
- return FALSE;
-
- p = strrchr (path, '/');
- if (p != NULL && p != path) {
- EFolder *parent_folder;
- gchar *parent_path;
-
- parent_path = g_strndup (path, p - path);
- parent_folder = e_folder_tree_get_folder (priv->folder_tree, parent_path);
-
- if (e_folder_get_highlighted (folder))
- e_folder_set_child_highlight (parent_folder, FALSE);
-
- g_free (parent_path);
- }
-
- g_signal_emit (storage, signals[REMOVED_FOLDER], 0, path);
-
- e_folder_tree_remove (priv->folder_tree, path);
-
- return TRUE;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-storage.h
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Author: Ettore Perazzoli
- */
-
-#ifndef _E_STORAGE_H_
-#define _E_STORAGE_H_
-
-#include <glib-object.h>
-#include "e-folder.h"
-
-G_BEGIN_DECLS
-
-#define E_TYPE_STORAGE (e_storage_get_type ())
-#define E_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_STORAGE, EStorage))
-#define E_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_STORAGE, EStorageClass))
-#define E_IS_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_STORAGE))
-#define E_IS_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_STORAGE))
-#define E_STORAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_STORAGE, EStorageClass))
-
-typedef struct EStorage EStorage;
-typedef struct EStoragePrivate EStoragePrivate;
-typedef struct EStorageClass EStorageClass;
-
-typedef enum {
- E_STORAGE_OK,
- E_STORAGE_GENERICERROR,
- E_STORAGE_EXISTS,
- E_STORAGE_INVALIDTYPE,
- E_STORAGE_IOERROR,
- E_STORAGE_NOSPACE,
- E_STORAGE_NOTEMPTY,
- E_STORAGE_NOTFOUND,
- E_STORAGE_NOTIMPLEMENTED,
- E_STORAGE_PERMISSIONDENIED,
- E_STORAGE_UNSUPPORTEDOPERATION,
- E_STORAGE_UNSUPPORTEDTYPE,
- E_STORAGE_CANTCHANGESTOCKFOLDER,
- E_STORAGE_CANTMOVETODESCENDANT,
- E_STORAGE_NOTONLINE,
- E_STORAGE_INVALIDNAME
-} EStorageResult;
-
-typedef void (* EStorageResultCallback) (EStorage *storage, EStorageResult result, gpointer data);
-typedef void (* EStorageDiscoveryCallback) (EStorage *storage, EStorageResult result, const gchar *path, gpointer data);
-
-struct EStorage {
- GObject parent;
-
- EStoragePrivate *priv;
-};
-
-struct EStorageClass {
- GObjectClass parent_class;
-
- /* Signals. */
-
- void (* new_folder) (EStorage *storage, const gchar *path);
- void (* updated_folder) (EStorage *storage, const gchar *path);
- void (* removed_folder) (EStorage *storage, const gchar *path);
-
- /* Virtual methods. */
-
- GList * (* get_subfolder_paths) (EStorage *storage,
- const gchar *path);
- EFolder * (* get_folder) (EStorage *storage,
- const gchar *path);
- const gchar * (* get_name) (EStorage *storage);
-
- void (* async_create_folder) (EStorage *storage,
- const gchar *path,
- const gchar *type,
- EStorageResultCallback callback,
- gpointer data);
-
- void (* async_remove_folder) (EStorage *storage,
- const gchar *path,
- EStorageResultCallback callback,
- gpointer data);
-
- void (* async_xfer_folder) (EStorage *storage,
- const gchar *source_path,
- const gchar *destination_path,
- const gboolean remove_source,
- EStorageResultCallback callback,
- gpointer data);
-
- void (* async_open_folder) (EStorage *storage,
- const gchar *path,
- EStorageDiscoveryCallback callback,
- gpointer data);
-
- gboolean (* will_accept_folder) (EStorage *storage,
- EFolder *new_parent,
- EFolder *source);
-
- void (* async_discover_shared_folder) (EStorage *storage,
- const gchar *owner,
- const gchar *folder_name,
- EStorageDiscoveryCallback callback,
- gpointer data);
- void (* cancel_discover_shared_folder) (EStorage *storage,
- const gchar *owner,
- const gchar *folder_name);
- void (* async_remove_shared_folder) (EStorage *storage,
- const gchar *path,
- EStorageResultCallback callback,
- gpointer data);
-};
-
-GType e_storage_get_type (void);
-void e_storage_construct (EStorage *storage,
- const gchar *name,
- EFolder *root_folder);
-EStorage *e_storage_new (const gchar *name,
- EFolder *root_folder);
-
-gboolean e_storage_path_is_relative (const gchar *path);
-gboolean e_storage_path_is_absolute (const gchar *path);
-
-GList *e_storage_get_subfolder_paths (EStorage *storage,
- const gchar *path);
-EFolder *e_storage_get_folder (EStorage *storage,
- const gchar *path);
-
-const gchar *e_storage_get_name (EStorage *storage);
-
-/* Folder operations. */
-
-void e_storage_async_create_folder (EStorage *storage,
- const gchar *path,
- const gchar *type,
- EStorageResultCallback callback,
- void *data);
-void e_storage_async_remove_folder (EStorage *storage,
- const gchar *path,
- EStorageResultCallback callback,
- void *data);
-void e_storage_async_xfer_folder (EStorage *storage,
- const gchar *source_path,
- const gchar *destination_path,
- const gboolean remove_source,
- EStorageResultCallback callback,
- void *data);
-void e_storage_async_open_folder (EStorage *storage,
- const gchar *path,
- EStorageDiscoveryCallback callback,
- void *data);
-
-const gchar *e_storage_result_to_string (EStorageResult result);
-
-gboolean e_storage_will_accept_folder (EStorage *storage,
- EFolder *new_parent,
- EFolder *source);
-
-/* Shared folders. */
-void e_storage_async_discover_shared_folder (EStorage *storage,
- const gchar *owner,
- const gchar *folder_name,
- EStorageDiscoveryCallback callback,
- void *data);
-void e_storage_cancel_discover_shared_folder (EStorage *storage,
- const gchar *owner,
- const gchar *folder_name);
-void e_storage_async_remove_shared_folder (EStorage *storage,
- const gchar *path,
- EStorageResultCallback callback,
- void *data);
-
-/* Utility functions. */
-
-gchar *e_storage_get_path_for_physical_uri (EStorage *storage,
- const gchar *physical_uri);
-
-/* FIXME: Need to rename these. */
-
-gboolean e_storage_new_folder (EStorage *storage,
- const gchar *path,
- EFolder *folder);
-gboolean e_storage_removed_folder (EStorage *storage,
- const gchar *path);
-
-gboolean e_storage_declare_has_subfolders (EStorage *storage,
- const gchar *path,
- const gchar *message);
-gboolean e_storage_get_has_subfolders (EStorage *storage,
- const gchar *path);
-
-G_END_DECLS
-
-#endif /* _E_STORAGE_H_ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2002-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* ExchangeAccount: Handles a single configured Connector account. This
- * is strictly a model object. ExchangeStorage handles the view.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "exchange-account.h"
-#include "exchange-hierarchy-webdav.h"
-#include "exchange-hierarchy-favorites.h"
-#include "exchange-hierarchy-gal.h"
-#include "exchange-folder-size.h"
-#include "e-folder-exchange.h"
-#include "e2k-autoconfig.h"
-#include "e2k-kerberos.h"
-#include "e2k-propnames.h"
-#include "e2k-uri.h"
-#include "e2k-utils.h"
-#include "exchange-hierarchy-foreign.h"
-
-/* This is an ugly hack to avoid API break */
-/* Added for get_authtype */
-#include "exchange-esource.h"
-#include <libedataserverui/e-passwords.h>
-
-#include <gtk/gtk.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-#define d(x)
-#define ADS_UF_DONT_EXPIRE_PASSWORD 0x10000
-#define ONE_HUNDRED_NANOSECOND 0.000000100
-#define SECONDS_IN_DAY 86400
-
-struct _ExchangeAccountPrivate {
- E2kContext *ctx;
- E2kGlobalCatalog *gc;
- GHashTable *standard_uris;
- ExchangeFolderSize *fsize;
-
- GMutex *connect_lock;
- gboolean connecting, connected;
- gint account_online;
-
- GPtrArray *hierarchies;
- GHashTable *hierarchies_by_folder, *foreign_hierarchies;
- ExchangeHierarchy *favorites_hierarchy;
- GHashTable *folders;
- GStaticRecMutex folders_lock;
- gchar *uri_authority, *http_uri_schema;
- gboolean uris_use_email, offline_sync;
-
- gchar *identity_name, *identity_email, *source_uri, *password_key;
- gchar *username, *password, *windows_domain, *nt_domain, *ad_server;
- gchar *owa_url;
- E2kAutoconfigAuthPref auth_pref;
- gint ad_limit, passwd_exp_warn_period, quota_limit;
- E2kAutoconfigGalAuthPref ad_auth;
-
- EAccountList *account_list;
- EAccount *account;
-
- GMutex *discover_data_lock;
- GList *discover_datas;
-};
-
-enum {
- CONNECTED,
- NEW_FOLDER,
- REMOVED_FOLDER,
- LAST_SIGNAL
-};
-
-static guint signals [LAST_SIGNAL] = { 0 };
-
-#define PARENT_TYPE G_TYPE_OBJECT
-static GObjectClass *parent_class = NULL;
-
-static void dispose (GObject *);
-static void finalize (GObject *);
-static void remove_hierarchy (ExchangeAccount *account, ExchangeHierarchy *hier);
-
-static void
-class_init (GObjectClass *object_class)
-{
- parent_class = g_type_class_ref (PARENT_TYPE);
-
- /* virtual method override */
- object_class->dispose = dispose;
- object_class->finalize = finalize;
-
- /* signals */
- signals[CONNECTED] =
- g_signal_new ("connected",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ExchangeAccountClass, connected),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1,
- E2K_TYPE_CONTEXT);
- signals[NEW_FOLDER] =
- g_signal_new ("new_folder",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ExchangeAccountClass, new_folder),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1,
- G_TYPE_POINTER);
- signals[REMOVED_FOLDER] =
- g_signal_new ("removed_folder",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ExchangeAccountClass, removed_folder),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1,
- G_TYPE_POINTER);
-}
-
-static void
-init (GObject *object)
-{
- ExchangeAccount *account = EXCHANGE_ACCOUNT (object);
-
- account->priv = g_new0 (ExchangeAccountPrivate, 1);
- account->priv->connect_lock = g_mutex_new ();
- account->priv->hierarchies = g_ptr_array_new ();
- account->priv->hierarchies_by_folder = g_hash_table_new (NULL, NULL);
- account->priv->foreign_hierarchies = g_hash_table_new (g_str_hash, g_str_equal);
- account->priv->folders = g_hash_table_new (g_str_hash, g_str_equal);
- g_static_rec_mutex_init (&account->priv->folders_lock);
- account->priv->discover_data_lock = g_mutex_new ();
- account->priv->account_online = UNSUPPORTED_MODE;
- account->priv->nt_domain = NULL;
- account->priv->fsize = exchange_folder_size_new ();
-}
-
-static void
-free_name (gpointer name, gpointer value, gpointer data)
-{
- g_free (name);
-}
-
-static void
-free_folder (gpointer key, gpointer folder, gpointer data)
-{
- g_object_unref (folder);
-}
-
-static void
-dispose (GObject *object)
-{
- ExchangeAccount *account = EXCHANGE_ACCOUNT (object);
- gint i;
-
- if (account->priv->account) {
- g_object_unref (account->priv->account);
- account->priv->account = NULL;
- }
-
- if (account->priv->account_list) {
- g_object_unref (account->priv->account_list);
- account->priv->account_list = NULL;
- }
-
- if (account->priv->ctx) {
- g_object_unref (account->priv->ctx);
- account->priv->ctx = NULL;
- }
-
- if (account->priv->gc) {
- g_object_unref (account->priv->gc);
- account->priv->gc = NULL;
- }
-
- if (account->priv->hierarchies) {
- for (i = 0; i < account->priv->hierarchies->len; i++)
- g_object_unref (account->priv->hierarchies->pdata[i]);
- g_ptr_array_free (account->priv->hierarchies, TRUE);
- account->priv->hierarchies = NULL;
- }
-
- if (account->priv->foreign_hierarchies) {
- g_hash_table_foreach (account->priv->foreign_hierarchies, free_name, NULL);
- g_hash_table_destroy (account->priv->foreign_hierarchies);
- account->priv->foreign_hierarchies = NULL;
- }
-
- g_static_rec_mutex_lock (&account->priv->folders_lock);
-
- if (account->priv->hierarchies_by_folder) {
- g_hash_table_destroy (account->priv->hierarchies_by_folder);
- account->priv->hierarchies_by_folder = NULL;
- }
-
- if (account->priv->folders) {
- g_hash_table_foreach (account->priv->folders, free_folder, NULL);
- g_hash_table_destroy (account->priv->folders);
- account->priv->folders = NULL;
- }
-
- g_static_rec_mutex_unlock (&account->priv->folders_lock);
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-free_uri (gpointer name, gpointer uri, gpointer data)
-{
- g_free (name);
- g_free (uri);
-}
-
-static void
-finalize (GObject *object)
-{
- ExchangeAccount *account = EXCHANGE_ACCOUNT (object);
-
- if (account->account_name)
- g_free (account->account_name);
- if (account->storage_dir)
- g_free (account->storage_dir);
- if (account->exchange_server)
- g_free (account->exchange_server);
- if (account->home_uri)
- g_free (account->home_uri);
- if (account->public_uri)
- g_free (account->public_uri);
- if (account->legacy_exchange_dn)
- g_free (account->legacy_exchange_dn);
- if (account->default_timezone)
- g_free (account->default_timezone);
-
- if (account->priv->standard_uris) {
- g_hash_table_foreach (account->priv->standard_uris,
- free_uri, NULL);
- g_hash_table_destroy (account->priv->standard_uris);
- }
-
- if (account->priv->uri_authority)
- g_free (account->priv->uri_authority);
- if (account->priv->http_uri_schema)
- g_free (account->priv->http_uri_schema);
-
- if (account->priv->identity_name)
- g_free (account->priv->identity_name);
- if (account->priv->identity_email)
- g_free (account->priv->identity_email);
- if (account->priv->source_uri)
- g_free (account->priv->source_uri);
- if (account->priv->password_key)
- g_free (account->priv->password_key);
-
- if (account->priv->username)
- g_free (account->priv->username);
- if (account->priv->password) {
- memset (account->priv->password, 0,
- strlen (account->priv->password));
- g_free (account->priv->password);
- }
- if (account->priv->windows_domain)
- g_free (account->priv->windows_domain);
-
- if (account->priv->nt_domain)
- g_free (account->priv->nt_domain);
-
- if (account->priv->ad_server)
- g_free (account->priv->ad_server);
-
- if (account->priv->owa_url)
- g_free (account->priv->owa_url);
-
- if (account->priv->connect_lock)
- g_mutex_free (account->priv->connect_lock);
-
- if (account->priv->discover_data_lock)
- g_mutex_free (account->priv->discover_data_lock);
-
- g_static_rec_mutex_free (&account->priv->folders_lock);
-
- g_free (account->priv);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-E2K_MAKE_TYPE (exchange_account, ExchangeAccount, class_init, init, PARENT_TYPE)
-
-void
-exchange_account_rescan_tree (ExchangeAccount *account)
-{
- gint i;
- EFolder *toplevel;
-
- g_return_if_fail (EXCHANGE_IS_ACCOUNT (account));
-
- g_static_rec_mutex_lock (&account->priv->folders_lock);
-
- for (i = 0; i < account->priv->hierarchies->len; i++) {
- /* First include the toplevel folder of the hierarchy as well */
- toplevel = EXCHANGE_HIERARCHY (account->priv->hierarchies->pdata[i])->toplevel;
-
- exchange_hierarchy_scan_subtree (account->priv->hierarchies->pdata[i],
- toplevel, account->priv->account_online);
- exchange_hierarchy_rescan (account->priv->hierarchies->pdata[i]);
- }
- g_static_rec_mutex_unlock (&account->priv->folders_lock);
-}
-
-/*
- * ExchangeHierarchy folder creation/deletion/xfer notifications
- */
-
-static void
-hierarchy_new_folder (ExchangeHierarchy *hier, EFolder *folder,
- ExchangeAccount *account)
-{
- gint table_updated = 0;
- const gchar *permanent_uri =
- e_folder_exchange_get_permanent_uri (folder);
- gchar *key;
-
- g_static_rec_mutex_lock (&account->priv->folders_lock);
-
- /* This makes the cleanup easier. We just unref it each time
- * we find it in account->priv->folders.
- */
- key = (gchar *) e_folder_exchange_get_path (folder);
- if (!g_hash_table_lookup (account->priv->folders, key)) {
- /* Avoid dupilcations since the user could add a folder as
- favorite even though it is already marked as favorite */
- g_object_ref (folder);
- g_hash_table_insert (account->priv->folders,
- key,
- folder);
- table_updated = 1;
- }
-
- key = (gchar *) e_folder_get_physical_uri (folder);
- if (!g_hash_table_lookup (account->priv->folders, key)) {
- /* Avoid dupilcations since the user could add a folder as
- favorite even though it is already marked as favorite */
- g_object_ref (folder);
- g_hash_table_insert (account->priv->folders,
- key,
- folder);
- table_updated = 1;
- }
-
- key = (gchar *) e_folder_exchange_get_internal_uri (folder);
- if (!g_hash_table_lookup (account->priv->folders, key)) {
- /* The internal_uri for public folders and favorites folder
- is same !!! Without this check the folder value could
- overwrite the previously added folder. */
- g_object_ref (folder);
- g_hash_table_insert (account->priv->folders,
- key,
- folder);
- table_updated = 1;
- }
-
- if (permanent_uri && (!g_hash_table_lookup (account->priv->folders,
- permanent_uri))) {
- g_object_ref (folder);
- g_hash_table_insert (account->priv->folders,
- (gchar *)permanent_uri,
- folder);
- table_updated = 1;
- }
-
- if (table_updated)
- {
- g_hash_table_insert (account->priv->hierarchies_by_folder,
- folder, hier);
- g_static_rec_mutex_unlock (&account->priv->folders_lock);
-
- g_signal_emit (account, signals[NEW_FOLDER], 0, folder);
- } else {
- g_static_rec_mutex_unlock (&account->priv->folders_lock);
- }
-}
-
-static void
-hierarchy_removed_folder (ExchangeHierarchy *hier, EFolder *folder,
- ExchangeAccount *account)
-{
- gint unref_count = 0;
-
- g_static_rec_mutex_lock (&account->priv->folders_lock);
- if (!g_hash_table_lookup (account->priv->folders,
- e_folder_exchange_get_path (folder))) {
- g_static_rec_mutex_unlock (&account->priv->folders_lock);
- return;
- }
-
- if (g_hash_table_remove (account->priv->folders, e_folder_exchange_get_path (folder)))
- unref_count++;
-
- if (g_hash_table_remove (account->priv->folders, e_folder_get_physical_uri (folder)))
- unref_count++;
-
- /* Dont remove this for favorites, as the internal_uri is shared
- by the public folder as well */
- if (hier->type != EXCHANGE_HIERARCHY_FAVORITES) {
- if (g_hash_table_remove (account->priv->folders, e_folder_exchange_get_internal_uri (folder)))
- unref_count++;
- }
-
- g_hash_table_remove (account->priv->hierarchies_by_folder, folder);
-
- g_static_rec_mutex_unlock (&account->priv->folders_lock);
- g_signal_emit (account, signals[REMOVED_FOLDER], 0, folder);
-
- if (folder == hier->toplevel)
- remove_hierarchy (account, hier);
-
- /* unref only those we really removed */
- while (unref_count > 0) {
- g_object_unref (folder);
- unref_count--;
- }
-}
-
-static gboolean
-get_folder (ExchangeAccount *account, const gchar *path,
- EFolder **folder, ExchangeHierarchy **hier)
-{
- g_static_rec_mutex_lock (&account->priv->folders_lock);
- *folder = g_hash_table_lookup (account->priv->folders, path);
- if (!*folder) {
- g_static_rec_mutex_unlock (&account->priv->folders_lock);
- return FALSE;
- }
- *hier = g_hash_table_lookup (account->priv->hierarchies_by_folder,
- *folder);
- g_static_rec_mutex_unlock (&account->priv->folders_lock);
- if (!*hier)
- return FALSE;
- return TRUE;
-}
-
-static gboolean
-get_parent_and_name (ExchangeAccount *account, const gchar **path,
- EFolder **parent, ExchangeHierarchy **hier)
-{
- gchar *name, *parent_path;
-
- name = strrchr (*path + 1, '/');
- if (!name)
- return FALSE;
-
- g_static_rec_mutex_lock (&account->priv->folders_lock);
- parent_path = g_strndup (*path, name - *path);
- *parent = g_hash_table_lookup (account->priv->folders, parent_path);
- g_free (parent_path);
-
- if (!*parent) {
- g_static_rec_mutex_unlock (&account->priv->folders_lock);
- return FALSE;
- }
-
- *hier = g_hash_table_lookup (account->priv->hierarchies_by_folder,
- *parent);
- g_static_rec_mutex_unlock (&account->priv->folders_lock);
- if (!*hier)
- return FALSE;
-
- *path = name + 1;
- return TRUE;
-}
-
-ExchangeAccountFolderResult
-exchange_account_create_folder (ExchangeAccount *account,
- const gchar *path, const gchar *type)
-{
- ExchangeHierarchy *hier;
- EFolder *parent;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account),
- EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
-
- if (!get_parent_and_name (account, &path, &parent, &hier))
- return EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
-
- return exchange_hierarchy_create_folder (hier, parent, path, type);
-}
-
-static gboolean
-check_if_sf (gpointer key, gpointer value, gpointer user_data)
-{
- gchar *sf_href = (gchar *)value;
- gchar *int_uri = (gchar *)user_data;
-
- if (!strcmp (sf_href, int_uri))
- return TRUE; /* Quit calling the callback */
-
- return FALSE; /* Continue calling the callback till end of table */
-}
-
-ExchangeAccountFolderResult
-exchange_account_remove_folder (ExchangeAccount *account, const gchar *path)
-{
- ExchangeHierarchy *hier;
- EFolder *folder;
- const gchar *int_uri;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account),
- EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
-
- d(g_print ("exchange_account_remove_folder: path=[%s]\n", path));
-
- if (!get_folder (account, path, &folder, &hier))
- return EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
-
- int_uri = e_folder_exchange_get_internal_uri (folder);
-
- if (g_hash_table_find (account->priv->standard_uris,
- check_if_sf, (gchar *)int_uri)) {
- return EXCHANGE_ACCOUNT_FOLDER_UNSUPPORTED_OPERATION;
- }
-
- return exchange_hierarchy_remove_folder (hier, folder);
-}
-
-ExchangeAccountFolderResult
-exchange_account_xfer_folder (ExchangeAccount *account,
- const gchar *source_path,
- const gchar *dest_path,
- gboolean remove_source)
-{
- EFolder *source, *dest_parent;
- ExchangeHierarchy *source_hier, *dest_hier;
- const gchar *name;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account),
- EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
-
- if (!get_folder (account, source_path, &source, &source_hier) ||
- !get_parent_and_name (account, &dest_path, &dest_parent, &dest_hier)) {
- /* Source or dest seems to not exist */
- return EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
- }
- if (source_hier != dest_hier) {
- /* Can't move something between hierarchies */
- return EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR;
- }
- if (remove_source) {
- name = e_folder_get_name (source);
- if (exchange_account_get_standard_uri (account, name))
- return EXCHANGE_ACCOUNT_FOLDER_UNSUPPORTED_OPERATION;
-
- }
-
- return exchange_hierarchy_xfer_folder (source_hier, source,
- dest_parent, dest_path,
- remove_source);
-}
-
-static void
-remove_hierarchy (ExchangeAccount *account, ExchangeHierarchy *hier)
-{
- gint i;
-
- for (i = 0; i < account->priv->hierarchies->len; i++) {
- if (account->priv->hierarchies->pdata[i] == hier) {
- g_ptr_array_remove_index_fast (account->priv->hierarchies, i);
- break;
- }
- }
- g_hash_table_remove (account->priv->foreign_hierarchies,
- hier->owner_email);
- g_signal_handlers_disconnect_by_func (hier, hierarchy_new_folder, account);
- g_signal_handlers_disconnect_by_func (hier, hierarchy_removed_folder, account);
- g_object_unref (hier);
-}
-
-static void
-setup_hierarchy (ExchangeAccount *account, ExchangeHierarchy *hier)
-{
- g_ptr_array_add (account->priv->hierarchies, hier);
-
- g_signal_connect (hier, "new_folder",
- G_CALLBACK (hierarchy_new_folder), account);
- g_signal_connect (hier, "removed_folder",
- G_CALLBACK (hierarchy_removed_folder), account);
-
- exchange_hierarchy_add_to_storage (hier);
-}
-
-static void
-setup_hierarchy_foreign (ExchangeAccount *account, ExchangeHierarchy *hier)
-{
- g_hash_table_insert (account->priv->foreign_hierarchies,
- (gchar *)hier->owner_email, hier);
- setup_hierarchy (account, hier);
-}
-
-struct discover_data {
- const gchar *user, *folder_name;
- E2kOperation op;
-};
-
-static ExchangeHierarchy *
-get_hierarchy_for (ExchangeAccount *account, E2kGlobalCatalogEntry *entry)
-{
- ExchangeHierarchy *hier;
- gchar *hierarchy_name, *source;
- gchar *physical_uri_prefix, *internal_uri_prefix;
-
- hier = g_hash_table_lookup (account->priv->foreign_hierarchies,
- entry->email);
- if (hier)
- return hier;
-
- /* i18n: This is the title of an "other user's folders"
- hierarchy. Eg, "John Doe's Folders". */
- hierarchy_name = g_strdup_printf (_("%s's Folders"),
- entry->display_name);
- source = g_strdup_printf ("exchange://%s@%s/", entry->mailbox,
- account->exchange_server);
- physical_uri_prefix = g_strdup_printf ("exchange://%s/;%s",
- account->priv->uri_authority,
- entry->email);
- internal_uri_prefix = exchange_account_get_foreign_uri (account, entry,
- NULL);
-
- hier = exchange_hierarchy_foreign_new (account, hierarchy_name,
- physical_uri_prefix,
- internal_uri_prefix,
- entry->display_name,
- entry->email, source);
- g_free (hierarchy_name);
- g_free (physical_uri_prefix);
- g_free (internal_uri_prefix);
- g_free (source);
-
- setup_hierarchy_foreign (account, hier);
- return hier;
-}
-
-ExchangeAccountFolderResult
-exchange_account_discover_shared_folder (ExchangeAccount *account,
- const gchar *user,
- const gchar *folder_name,
- EFolder **folder)
-{
- struct discover_data dd;
- ExchangeHierarchy *hier;
- gchar *email;
- E2kGlobalCatalogStatus status;
- E2kGlobalCatalogEntry *entry;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account),
- EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
-
- if (!account->priv->gc)
- return EXCHANGE_ACCOUNT_FOLDER_GC_NOTREACHABLE;
-
- email = strchr (user, '<');
- if (email)
- email = g_strndup (email + 1, strcspn (email + 1, ">"));
- else
- email = g_strdup (user);
- hier = g_hash_table_lookup (account->priv->foreign_hierarchies, email);
- if (hier) {
- g_free (email);
- return exchange_hierarchy_foreign_add_folder (hier, folder_name, folder);
- }
-
- dd.user = user;
- dd.folder_name = folder_name;
- e2k_operation_init (&dd.op);
-
- g_mutex_lock (account->priv->discover_data_lock);
- account->priv->discover_datas =
- g_list_prepend (account->priv->discover_datas, &dd);
- g_mutex_unlock (account->priv->discover_data_lock);
-
- status = e2k_global_catalog_lookup (account->priv->gc, &dd.op,
- E2K_GLOBAL_CATALOG_LOOKUP_BY_EMAIL,
- email,
- E2K_GLOBAL_CATALOG_LOOKUP_EMAIL |
- E2K_GLOBAL_CATALOG_LOOKUP_MAILBOX,
- &entry);
- g_free (email);
- e2k_operation_free (&dd.op);
-
- g_mutex_lock (account->priv->discover_data_lock);
- account->priv->discover_datas =
- g_list_remove (account->priv->discover_datas, &dd);
- g_mutex_unlock (account->priv->discover_data_lock);
-
- if (status != E2K_GLOBAL_CATALOG_OK) {
- if (status == E2K_GLOBAL_CATALOG_ERROR)
- return EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR;
- if (status == E2K_GLOBAL_CATALOG_NO_SUCH_USER)
- return EXCHANGE_ACCOUNT_FOLDER_NO_SUCH_USER;
- else
- return EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
- }
-
- hier = get_hierarchy_for (account, entry);
- return exchange_hierarchy_foreign_add_folder (hier, folder_name, folder);
-}
-
-void
-exchange_account_cancel_discover_shared_folder (ExchangeAccount *account,
- const gchar *user,
- const gchar *folder_name)
-{
- struct discover_data *dd;
- GList *dds;
-
- g_return_if_fail (EXCHANGE_IS_ACCOUNT (account));
-
- g_mutex_lock (account->priv->discover_data_lock);
- for (dds = account->priv->discover_datas; dds; dds = dds->next) {
- dd = dds->data;
- if (!strcmp (dd->user, user) &&
- !strcmp (dd->folder_name, folder_name))
- break;
- }
- if (!dds) {
- g_mutex_unlock (account->priv->discover_data_lock);
- return;
- }
-
- e2k_operation_cancel (&dd->op);
- g_mutex_unlock (account->priv->discover_data_lock);
-
-#ifdef FIXME
- /* We can't actually cancel the hierarchy's attempt to get
- * the folder, but we can remove the hierarchy if appropriate.
- */
- if (dd->hier && exchange_hierarchy_is_empty (dd->hier))
- hierarchy_removed_folder (dd->hier, dd->hier->toplevel, account);
-#endif
-}
-
-ExchangeAccountFolderResult
-exchange_account_remove_shared_folder (ExchangeAccount *account,
- const gchar *path)
-{
- ExchangeHierarchy *hier;
- EFolder *folder;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account),
- EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
-
- if (!get_folder (account, path, &folder, &hier))
- return EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
- if (!EXCHANGE_IS_HIERARCHY_FOREIGN (hier))
- return EXCHANGE_ACCOUNT_FOLDER_UNSUPPORTED_OPERATION;
-
- return exchange_hierarchy_remove_folder (hier, folder);
-}
-
-ExchangeAccountFolderResult
-exchange_account_open_folder (ExchangeAccount *account, const gchar *path)
-{
- ExchangeHierarchy *hier;
- EFolder *folder;
- gint mode;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account),
- EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
-
- d(g_print ("exchange_account_remove_folder: path=[%s]\n", path));
-
- if (!get_folder (account, path, &folder, &hier))
- return EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
-
- exchange_account_is_offline (account, &mode);
- if (mode == ONLINE_MODE && !account->priv->connected &&
- hier == (ExchangeHierarchy *)account->priv->hierarchies->pdata[0] &&
- folder == hier->toplevel) {
- /* The shell is asking us to open the personal folders
- * hierarchy, but we're already planning to do that
- * anyway. So just ignore the request for now.
- */
- return EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
- }
-
- return exchange_hierarchy_scan_subtree (hier, folder, mode);
-}
-
-ExchangeAccountFolderResult
-exchange_account_add_favorite (ExchangeAccount *account,
- EFolder *folder)
-{
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
- g_return_val_if_fail (E_IS_FOLDER (folder), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
-
- return exchange_hierarchy_favorites_add_folder (
- account->priv->favorites_hierarchy,
- folder);
-}
-
-ExchangeAccountFolderResult
-exchange_account_remove_favorite (ExchangeAccount *account,
- EFolder *folder)
-{
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
- g_return_val_if_fail (E_IS_FOLDER (folder), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
-
- return exchange_hierarchy_remove_folder (
- EXCHANGE_HIERARCHY (account->priv->favorites_hierarchy),
- folder);
-}
-
-gboolean
-exchange_account_is_favorite_folder (ExchangeAccount *account,
- EFolder *folder)
-{
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
- g_return_val_if_fail (E_IS_FOLDER (folder), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
-
- return exchange_hierarchy_favorites_is_added (
- EXCHANGE_HIERARCHY (account->priv->favorites_hierarchy),
- folder);
-}
-
-static void
-context_redirect (E2kContext *ctx, E2kHTTPStatus status,
- const gchar *old_uri, const gchar *new_uri,
- ExchangeAccount *account)
-{
- EFolder *folder;
-
- g_static_rec_mutex_lock (&account->priv->folders_lock);
- folder = g_hash_table_lookup (account->priv->folders, old_uri);
- if (!folder) {
- g_static_rec_mutex_unlock (&account->priv->folders_lock);
- return;
- }
-
- g_hash_table_remove (account->priv->folders, old_uri);
- e_folder_exchange_set_internal_uri (folder, new_uri);
- g_hash_table_insert (account->priv->folders,
- (gchar *)e_folder_exchange_get_internal_uri (folder),
- folder);
-
- g_static_rec_mutex_unlock (&account->priv->folders_lock);
-}
-
-static void
-set_sf_prop (const gchar *propname, E2kPropType type,
- gpointer phref, gpointer user_data)
-{
- ExchangeAccount *account = user_data;
- const gchar *href = (const gchar *)phref;
- gchar *tmp;
-
- propname = strrchr (propname, ':');
- if (!propname++ || !href || !*href)
- return;
-
- tmp = e2k_strdup_with_trailing_slash (href);
- if (!tmp) {
- g_warning ("Failed to add propname '%s' for href '%s'\n", propname, href);
- return;
- }
-
- g_hash_table_insert (account->priv->standard_uris,
- g_strdup (propname),
- tmp);
-}
-
-static const gchar *mailbox_info_props[] = {
- E2K_PR_STD_FOLDER_CALENDAR,
- E2K_PR_STD_FOLDER_CONTACTS,
- E2K_PR_STD_FOLDER_DELETED_ITEMS,
- E2K_PR_STD_FOLDER_DRAFTS,
- E2K_PR_STD_FOLDER_INBOX,
- E2K_PR_STD_FOLDER_JOURNAL,
- E2K_PR_STD_FOLDER_NOTES,
- E2K_PR_STD_FOLDER_OUTBOX,
- E2K_PR_STD_FOLDER_SENT_ITEMS,
- E2K_PR_STD_FOLDER_TASKS,
- E2K_PR_STD_FOLDER_ROOT,
- E2K_PR_STD_FOLDER_SENDMSG,
-
- PR_STORE_ENTRYID,
- E2K_PR_EXCHANGE_TIMEZONE
-};
-static const gint n_mailbox_info_props = G_N_ELEMENTS (mailbox_info_props);
-
-static gboolean
-account_moved (ExchangeAccount *account, E2kAutoconfig *ac)
-{
- E2kAutoconfigResult result;
- EAccount *eaccount;
-
- result = e2k_autoconfig_check_exchange (ac, NULL);
- if (result != E2K_AUTOCONFIG_OK)
- return FALSE;
- result = e2k_autoconfig_check_global_catalog (ac, NULL);
- if (result != E2K_AUTOCONFIG_OK)
- return FALSE;
-
- eaccount = account->priv->account;
-
- if (eaccount->source->url && eaccount->transport->url &&
- !strcmp (eaccount->source->url, eaccount->transport->url)) {
- g_free (eaccount->transport->url);
- eaccount->transport->url = g_strdup (ac->account_uri);
- }
- g_free (eaccount->source->url);
- eaccount->source->url = g_strdup (ac->account_uri);
-
- e_account_list_change (account->priv->account_list, eaccount);
- e_account_list_save (account->priv->account_list);
- return TRUE;
-}
-
-#if 0
-static gboolean
-get_password (ExchangeAccount *account, E2kAutoconfig *ac, ExchangeAccountResult error)
-{
- gchar *password;
-
- if (error != EXCHANGE_ACCOUNT_CONNECT_SUCCESS)
- e_passwords_forget_password ("Exchange", account->priv->password_key);
-
- password = e_passwords_get_password ("Exchange", account->priv->password_key);
-#if 0
- if (exchange_component_is_interactive (global_exchange_component)) {
- gboolean remember, oldremember;
- if (!password) {
- gchar *prompt;
-
- prompt = g_strdup_printf (_("Enter password for %s"),
- account->account_name);
- oldremember = remember =
- account->priv->account->source->save_passwd;
- password = e_passwords_ask_password (
- _("Enter password"),
- "Exchange",
- account->priv->password_key,
- prompt,
- E_PASSWORDS_REMEMBER_FOREVER|E_PASSWORDS_SECRET,
- &remember,
- NULL);
- if (remember != oldremember) {
- account->priv->account->source->save_passwd = remember;
- }
- g_free (prompt);
- }
- else if (!account->priv->account->source->save_passwd) {
- /* 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()
- */
- e_passwords_forget_password ("Exchange", account->priv->password_key);
- }
- }
-#endif
- if (!password) {
- }
- else if (!account->priv->account->source->save_passwd) {
- /* 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()
- */
- e_passwords_forget_password ("Exchange", account->priv->password_key);
- }
-
- if (password) {
- e2k_autoconfig_set_password (ac, password);
- memset (password, 0, strlen (password));
- g_free (password);
- return TRUE;
- } else
- return FALSE;
-}
-#endif
-
-/* This uses the kerberos calls to check if the authentication failure
- * was due to the password getting expired. If the password has expired
- * this returns TRUE, else it returns FALSE.
- */
-#ifdef HAVE_KRB5
-static gboolean
-is_password_expired (ExchangeAccount *account, E2kAutoconfig *ac)
-{
- gchar *domain;
- E2kKerberosResult result;
-
- if (!ac->password)
- return FALSE;
-
- domain = ac->w2k_domain;
- if (!domain) {
- domain = strchr (account->priv->identity_email, '@');
- if (domain)
- domain++;
- }
- if (!domain)
- return FALSE;
-
- result = e2k_kerberos_check_password (ac->username, domain,
- ac->password);
- if (result != E2K_KERBEROS_OK &&
- result != E2K_KERBEROS_PASSWORD_EXPIRED) {
- /* try again with nt domain */
- domain = ac->nt_domain;
- if (domain)
- result = e2k_kerberos_check_password (ac->username,
- domain,
- ac->password);
- }
-
- return (result == E2K_KERBEROS_PASSWORD_EXPIRED);
-}
-#endif
-
-static gint
-find_passwd_exp_period (ExchangeAccount *account, E2kGlobalCatalogEntry *entry)
-{
- gdouble max_pwd_age = 0;
- gint max_pwd_age_days;
- E2kOperation gcop;
- E2kGlobalCatalogStatus gcstatus;
-
- /* If user has not selected password expiry warning option, return */
- if (account->priv->passwd_exp_warn_period == -1)
- return -1;
-
- /* Check for password expiry period */
- /* This needs to be invoked after is_password_expired(), i.e.,
- only if password is not expired */
-
- /* Check for account control value for a user */
-
- e2k_operation_init (&gcop);
- gcstatus = e2k_global_catalog_lookup (account->priv->gc,
- &gcop,
- E2K_GLOBAL_CATALOG_LOOKUP_BY_EMAIL,
- account->priv->identity_email,
- E2K_GLOBAL_CATALOG_LOOKUP_ACCOUNT_CONTROL,
- &entry);
- e2k_operation_free (&gcop);
- if (gcstatus != E2K_GLOBAL_CATALOG_OK)
- return -1;
-
- if (entry->user_account_control & ADS_UF_DONT_EXPIRE_PASSWORD) {
- return -1; /* Password is not set to expire */
- }
-
- /* Here we don't check not setting the password and expired password */
- /* Check for the maximum password age set */
-
- e2k_operation_init (&gcop);
- max_pwd_age = lookup_passwd_max_age (account->priv->gc, &gcop);
- e2k_operation_free (&gcop);
-
- if (max_pwd_age > 0) {
- /* Calculate password expiry period */
- max_pwd_age_days =
- ( max_pwd_age * ONE_HUNDRED_NANOSECOND ) / SECONDS_IN_DAY;
-
- if (max_pwd_age_days <= account->priv->passwd_exp_warn_period) {
- return max_pwd_age_days;
- }
- }
- return -1;
-}
-
-gchar *
-exchange_account_get_password (ExchangeAccount *account)
-{
- return e_passwords_get_password ("Exchange", account->priv->password_key);
-}
-
-void
-exchange_account_forget_password (ExchangeAccount *account)
-{
- e_passwords_forget_password ("Exchange", account->priv->password_key);
-}
-
-ExchangeAccountResult
-exchange_account_set_password (ExchangeAccount *account, gchar *old_pass, gchar *new_pass)
-{
-#ifdef HAVE_KRB5
- E2kKerberosResult result;
- gchar *domain;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), EXCHANGE_ACCOUNT_PASSWORD_CHANGE_FAILED);
- g_return_val_if_fail (old_pass != NULL, EXCHANGE_ACCOUNT_PASSWORD_CHANGE_FAILED);
- g_return_val_if_fail (new_pass != NULL, EXCHANGE_ACCOUNT_PASSWORD_CHANGE_FAILED);
-
- domain = account->priv->gc ? account->priv->gc->domain : NULL;
- if (!domain) {
- domain = strchr (account->priv->identity_email, '@');
- if (domain)
- domain++;
- }
- if (!domain) {
- /* email id is not proper, we return instead of trying nt_domain */
- return EXCHANGE_ACCOUNT_CONFIG_ERROR;
- }
-
- result = e2k_kerberos_change_password (account->priv->username, domain,
- old_pass, new_pass);
- if (result != E2K_KERBEROS_OK && result != E2K_KERBEROS_PASSWORD_TOO_WEAK) {
- /* try with nt_domain */
- domain = account->priv->nt_domain;
- if (domain)
- result = e2k_kerberos_change_password (account->priv->username,
- domain, old_pass,
- new_pass);
- }
- switch (result) {
- case E2K_KERBEROS_OK:
- e_passwords_forget_password ("Exchange", account->priv->password_key);
- e_passwords_add_password (account->priv->password_key, new_pass);
- if (account->priv->account->source->save_passwd)
- e_passwords_remember_password ("Exchange", account->priv->password_key);
- break;
-
- case E2K_KERBEROS_PASSWORD_TOO_WEAK:
- return EXCHANGE_ACCOUNT_PASSWORD_WEAK_ERROR;
-
- case E2K_KERBEROS_FAILED:
- default:
- return EXCHANGE_ACCOUNT_PASSWORD_CHANGE_FAILED;
- }
-
- return EXCHANGE_ACCOUNT_PASSWORD_CHANGE_SUCCESS;
-#else
- g_warning ("exchange_account_set_password: Not implemented (no KRB5)");
- return EXCHANGE_ACCOUNT_PASSWORD_CHANGE_FAILED;
-#endif
-}
-
-void
-exchange_account_set_save_password (ExchangeAccount *account, gboolean save_password)
-{
- account->priv->account->source->save_passwd = save_password;
-}
-
-gboolean
-exchange_account_is_save_password (ExchangeAccount *account)
-{
- return account->priv->account->source->save_passwd;
-}
-
-/**
- * exchange_account_set_offline:
- * @account: an #ExchangeAccount
- *
- * This nullifies the connection and sets the account as offline.
- * The caller should take care that the required data is fetched
- * before calling this method.
- *
- * Return value: Returns TRUE is successfully sets the account to
- * offline or FALSE if failed
- **/
-gboolean
-exchange_account_set_offline (ExchangeAccount *account)
-{
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), FALSE);
-
- g_mutex_lock (account->priv->connect_lock);
- if (account->priv->ctx) {
- g_object_unref (account->priv->ctx);
- account->priv->ctx = NULL;
- }
-
- account->priv->account_online = OFFLINE_MODE;
- g_mutex_unlock (account->priv->connect_lock);
- return TRUE;
-}
-
-/**
- * exchange_account_set_online:
- * @account: an #ExchangeAccount
- *
- * This nullifies the connection and sets the account as offline.
- * The caller should take care that the required data is fetched
- * before calling this method.
- *
- * Return value: Returns TRUE is successfully sets the account to
- * offline or FALSE if failed
- **/
-gboolean
-exchange_account_set_online (ExchangeAccount *account)
-{
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), FALSE);
-
- g_mutex_lock (account->priv->connect_lock);
- account->priv->account_online = ONLINE_MODE;
- g_mutex_unlock (account->priv->connect_lock);
-
- return TRUE;
-}
-
-/**
- * exchange_account_is_offline:
- * @account: an #ExchangeAccount
- *
- * Return value: Returns TRUE if account is offline
- **/
-void
-exchange_account_is_offline (ExchangeAccount *account, gint *state)
-{
- g_return_if_fail (EXCHANGE_IS_ACCOUNT (account));
-
- *state = account->priv->account_online;
-}
-
-static gboolean
-setup_account_hierarchies (ExchangeAccount *account)
-{
- ExchangeHierarchy *hier, *personal_hier;
- ExchangeAccountFolderResult fresult;
- gchar *phys_uri_prefix, *dir;
- GDir *d;
- const gchar *dent;
- gint mode;
-
- exchange_account_is_offline (account, &mode);
-
- if (mode == UNSUPPORTED_MODE)
- return FALSE;
-
- /* Check if folder hierarchies are already setup. */
- if (account->priv->hierarchies->len > 0)
- goto hierarchies_created;
-
- /* Set up Personal Folders hierarchy */
- phys_uri_prefix = g_strdup_printf ("exchange://%s/;personal",
- account->priv->uri_authority);
- hier = exchange_hierarchy_webdav_new (account,
- EXCHANGE_HIERARCHY_PERSONAL,
- _("Personal Folders"),
- phys_uri_prefix,
- account->home_uri,
- account->priv->identity_name,
- account->priv->identity_email,
- account->priv->source_uri,
- TRUE);
-
- setup_hierarchy (account, hier);
- g_free (phys_uri_prefix);
-
- /* Favorite Public Folders */
- phys_uri_prefix = g_strdup_printf ("exchange://%s/;favorites",
- account->priv->uri_authority);
- hier = exchange_hierarchy_favorites_new (account,
- _("Favorite Public Folders"),
- phys_uri_prefix,
- account->home_uri,
- account->public_uri,
- account->priv->identity_name,
- account->priv->identity_email,
- account->priv->source_uri);
- setup_hierarchy (account, hier);
- g_free (phys_uri_prefix);
- account->priv->favorites_hierarchy = hier;
-
- /* Public Folders */
- phys_uri_prefix = g_strdup_printf ("exchange://%s/;public",
- account->priv->uri_authority);
- hier = exchange_hierarchy_webdav_new (account,
- EXCHANGE_HIERARCHY_PUBLIC,
- /* i18n: Outlookism */
- _("All Public Folders"),
- phys_uri_prefix,
- account->public_uri,
- account->priv->identity_name,
- account->priv->identity_email,
- account->priv->source_uri,
- FALSE);
- setup_hierarchy (account, hier);
- g_free (phys_uri_prefix);
-
- /* Global Address List */
- phys_uri_prefix = g_strdup_printf ("gal://%s/gal",
- account->priv->uri_authority);
- /* i18n: Outlookism */
- hier = exchange_hierarchy_gal_new (account, _("Global Address List"),
- phys_uri_prefix);
- setup_hierarchy (account, hier);
- g_free (phys_uri_prefix);
-
- /* Other users' folders */
- d = g_dir_open (account->storage_dir, 0, NULL);
- if (d) {
- while ((dent = g_dir_read_name (d))) {
- if (!strchr (dent, '@'))
- continue;
- dir = g_strdup_printf ("%s/%s", account->storage_dir, dent);
- hier = exchange_hierarchy_foreign_new_from_dir (account, dir);
- g_free (dir);
- if (!hier)
- continue;
-
- setup_hierarchy_foreign (account, hier);
- }
- g_dir_close (d);
- }
-
-hierarchies_created:
-
- /* Scan the personal and favorite folders so we can resolve references
- * to the Calendar, Contacts, etc even if the tree isn't
- * opened.
- */
-
- /* Assuming the first element being personal hierarchy. */
- personal_hier = account->priv->hierarchies->pdata[0];
-
- fresult = exchange_hierarchy_scan_subtree (personal_hier,
- personal_hier->toplevel,
- mode);
- if (fresult != EXCHANGE_ACCOUNT_FOLDER_OK) {
- account->priv->connecting = FALSE;
- return FALSE;
- }
-
- account->mbox_size = exchange_hierarchy_webdav_get_total_folder_size (
- EXCHANGE_HIERARCHY_WEBDAV (personal_hier));
-
- fresult = exchange_hierarchy_scan_subtree (
- account->priv->favorites_hierarchy,
- account->priv->favorites_hierarchy->toplevel,
- mode);
- if (fresult != EXCHANGE_ACCOUNT_FOLDER_OK &&
- fresult != EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST) {
- account->priv->connecting = FALSE;
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * exchange_account_connect:
- * @account: an #ExchangeAccount
- *
- * This attempts to connect to @account. If the shell has enabled user
- * interaction, then it will prompt for a password if needed, and put
- * up an error message if the connection attempt failed.
- *
- * Return value: an #E2kContext, or %NULL if the connection attempt
- * failed.
- **/
-E2kContext *
-exchange_account_connect (ExchangeAccount *account, const gchar *pword,
- ExchangeAccountResult *info_result)
-{
- E2kAutoconfig *ac;
- E2kAutoconfigResult result;
- E2kHTTPStatus status;
- gboolean redirected = FALSE;
- E2kResult *results;
- gint nresults = 0, mode;
- GByteArray *entryid;
- const gchar *tz;
- E2kGlobalCatalogStatus gcstatus;
- E2kGlobalCatalogEntry *entry;
- E2kOperation gcop;
- gchar *user_name = NULL;
-
- *info_result = EXCHANGE_ACCOUNT_UNKNOWN_ERROR;
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- *info_result = EXCHANGE_ACCOUNT_CONNECT_SUCCESS;
- exchange_account_is_offline (account, &mode);
-
- g_mutex_lock (account->priv->connect_lock);
-
- if (mode == UNSUPPORTED_MODE) {
- *info_result = EXCHANGE_ACCOUNT_CONNECT_ERROR;
- account->priv->connecting = FALSE;
- g_mutex_unlock (account->priv->connect_lock);
- return NULL;
- }
-
- if (account->priv->connecting || mode == OFFLINE_MODE) {
- g_mutex_unlock (account->priv->connect_lock);
- if (mode == OFFLINE_MODE) {
- setup_account_hierarchies (account);
- *info_result = EXCHANGE_ACCOUNT_OFFLINE;
- }
- else {
- *info_result = EXCHANGE_ACCOUNT_CONNECT_ERROR;
- }
- return NULL;
- } else if (account->priv->ctx) {
- g_mutex_unlock (account->priv->connect_lock);
- return account->priv->ctx;
- }
-
- account->priv->connecting = TRUE;
-
- if (account->priv->windows_domain)
- user_name = g_strdup_printf ("%s\\%s", account->priv->windows_domain, account->priv->username);
- else
- user_name = g_strdup (account->priv->username);
-
- ac = e2k_autoconfig_new (account->home_uri,
- user_name,
- NULL,
- account->priv->auth_pref);
- g_free (user_name);
-
- e2k_autoconfig_set_gc_server (ac, account->priv->ad_server,
- account->priv->ad_limit, account->priv->ad_auth);
-
- if (!pword) {
- account->priv->connecting = FALSE;
- g_mutex_unlock (account->priv->connect_lock);
- *info_result = EXCHANGE_ACCOUNT_PASSWORD_INCORRECT;
- e2k_autoconfig_free (ac);
- return NULL;
- }
-
- e2k_autoconfig_set_password (ac, pword);
-
- try_connect_again:
- account->priv->ctx = e2k_autoconfig_get_context (ac, NULL, &result);
-
- if (!account->priv->nt_domain && ac->nt_domain)
- account->priv->nt_domain = g_strdup (ac->nt_domain);
- else
- account->priv->nt_domain = NULL;
-
- if (result != E2K_AUTOCONFIG_OK) {
-#ifdef HAVE_KRB5
- if ( is_password_expired (account, ac)) {
- *info_result = EXCHANGE_ACCOUNT_PASSWORD_EXPIRED;
- account->priv->connecting = FALSE;
- g_mutex_unlock (account->priv->connect_lock);
- e2k_autoconfig_free (ac);
- return NULL;
- }
-#endif
- switch (result) {
-
- case E2K_AUTOCONFIG_AUTH_ERROR:
- *info_result = EXCHANGE_ACCOUNT_PASSWORD_INCORRECT;
- e2k_autoconfig_free (ac);
- account->priv->connecting = FALSE;
- g_mutex_unlock (account->priv->connect_lock);
- return NULL;
-
- case E2K_AUTOCONFIG_AUTH_ERROR_TRY_DOMAIN:
- *info_result = EXCHANGE_ACCOUNT_DOMAIN_ERROR;
- e2k_autoconfig_free (ac);
- account->priv->connecting = FALSE;
- g_mutex_unlock (account->priv->connect_lock);
- return NULL;
-
- case E2K_AUTOCONFIG_AUTH_ERROR_TRY_NTLM:
- ac->use_ntlm = 1;
- goto try_connect_again;
-
- case E2K_AUTOCONFIG_AUTH_ERROR_TRY_BASIC:
- ac->use_ntlm = 0;
- goto try_connect_again;
-
- case E2K_AUTOCONFIG_REDIRECT:
- if (!redirected && account_moved (account, ac))
- goto try_connect_again;
- break;
-
- case E2K_AUTOCONFIG_TRY_SSL:
- if (account_moved (account, ac))
- goto try_connect_again;
- break;
-
- default:
- break;
- }
-
- e2k_autoconfig_free (ac);
- account->priv->connecting = FALSE;
- account->priv->account_online = OFFLINE_MODE; /* correct? */
-
- switch (result) {
- case E2K_AUTOCONFIG_REDIRECT:
- case E2K_AUTOCONFIG_TRY_SSL:
- *info_result = EXCHANGE_ACCOUNT_MAILBOX_NA;
- break;
- case E2K_AUTOCONFIG_EXCHANGE_5_5:
- *info_result = EXCHANGE_ACCOUNT_VERSION_ERROR;
- break;
- case E2K_AUTOCONFIG_NOT_EXCHANGE:
- case E2K_AUTOCONFIG_NO_OWA:
- *info_result = EXCHANGE_ACCOUNT_WSS_ERROR;
- break;
- case E2K_AUTOCONFIG_NO_MAILBOX:
- *info_result = EXCHANGE_ACCOUNT_NO_MAILBOX;
- break;
- case E2K_AUTOCONFIG_CANT_RESOLVE:
- *info_result = EXCHANGE_ACCOUNT_RESOLVE_ERROR;
- break;
- case E2K_AUTOCONFIG_CANT_CONNECT:
- *info_result = EXCHANGE_ACCOUNT_CONNECT_ERROR;
- break;
- case E2K_AUTOCONFIG_CANCELLED:
- break;
- default:
- *info_result = EXCHANGE_ACCOUNT_UNKNOWN_ERROR;
- break;
- }
-
- g_mutex_unlock (account->priv->connect_lock);
- return NULL;
- }
-
- account->priv->gc = e2k_autoconfig_get_global_catalog (ac, NULL);
- e2k_autoconfig_free (ac);
-
- status = e2k_context_propfind (account->priv->ctx, NULL,
- account->home_uri,
- mailbox_info_props,
- n_mailbox_info_props,
- &results, &nresults);
-
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
- account->priv->connecting = FALSE;
- *info_result = EXCHANGE_ACCOUNT_UNKNOWN_ERROR;
- g_mutex_unlock (account->priv->connect_lock);
- return NULL; /* FIXME: what error has happened? */
- }
-
- if (nresults) {
- account->priv->standard_uris =
- g_hash_table_new (e2k_ascii_strcase_hash,
- e2k_ascii_strcase_equal);
- e2k_properties_foreach (results[0].props, set_sf_prop, account);
-
- /* FIXME: we should get these from the autoconfig */
- entryid = e2k_properties_get_prop (results[0].props, PR_STORE_ENTRYID);
- if (entryid)
- account->legacy_exchange_dn = g_strdup (e2k_entryid_to_dn (entryid));
-
- tz = e2k_properties_get_prop (results[0].props, E2K_PR_EXCHANGE_TIMEZONE);
- if (tz)
- account->default_timezone = g_strdup (tz);
- }
-
- if (!setup_account_hierarchies (account)) {
- *info_result = EXCHANGE_ACCOUNT_UNKNOWN_ERROR;
- g_mutex_unlock (account->priv->connect_lock);
- if (nresults)
- e2k_results_free (results, nresults);
- return NULL; /* FIXME: what error has happened? */
- }
-
- account->priv->account_online = ONLINE_MODE;
- account->priv->connecting = FALSE;
- account->priv->connected = TRUE;
-
- if (!account->priv->gc)
- goto skip_quota;
- /* Check for quota usage */
- e2k_operation_init (&gcop);
- gcstatus = e2k_global_catalog_lookup (account->priv->gc, &gcop,
- E2K_GLOBAL_CATALOG_LOOKUP_BY_EMAIL,
- account->priv->identity_email,
- E2K_GLOBAL_CATALOG_LOOKUP_QUOTA,
- &entry);
- e2k_operation_free (&gcop);
-
- /* FIXME: warning message should have quota limit value
- */
- if (gcstatus == E2K_GLOBAL_CATALOG_OK) {
-
- if (entry->quota_norecv &&
- account->mbox_size >= entry->quota_norecv) {
- *info_result = EXCHANGE_ACCOUNT_QUOTA_RECIEVE_ERROR;
- account->priv->quota_limit = entry->quota_norecv;
- } else if (entry->quota_nosend &&
- account->mbox_size >= entry->quota_nosend) {
- *info_result = EXCHANGE_ACCOUNT_QUOTA_SEND_ERROR;
- account->priv->quota_limit = entry->quota_nosend;
- } else if (entry->quota_warn &&
- account->mbox_size >= entry->quota_warn) {
- *info_result = EXCHANGE_ACCOUNT_QUOTA_WARN;
- account->priv->quota_limit = entry->quota_warn;
- }
- }
-
-skip_quota:
- g_signal_connect (account->priv->ctx, "redirect",
- G_CALLBACK (context_redirect), account);
-
- g_signal_emit (account, signals[CONNECTED], 0, account->priv->ctx);
- g_mutex_unlock (account->priv->connect_lock);
- if (nresults)
- e2k_results_free (results, nresults);
- return account->priv->ctx;
-}
-
-/**
- * exchange_account_is_offline_sync_set:
- * @account: an #ExchangeAccount
- *
- * Return value: TRUE if offline_sync is set for @account and FALSE if not.
- */
-void
-exchange_account_is_offline_sync_set (ExchangeAccount *account, gint *mode)
-{
- *mode = UNSUPPORTED_MODE;
-
- g_return_if_fail (EXCHANGE_IS_ACCOUNT (account));
-
- if (account->priv->offline_sync)
- *mode = OFFLINE_MODE;
- else
- *mode = ONLINE_MODE;
-}
-
-/**
- * exchange_account_get_context:
- * @account: an #ExchangeAccount
- *
- * Return value: @account's #E2kContext, if it is connected and
- * online, or %NULL if not.
- **/
-E2kContext *
-exchange_account_get_context (ExchangeAccount *account)
-{
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- return account->priv->ctx;
-}
-
-/**
- * exchange_account_get_global_catalog:
- * @account: an #ExchangeAccount
- *
- * Return value: @account's #E2kGlobalCatalog, if it is connected and
- * online, or %NULL if not.
- **/
-E2kGlobalCatalog *
-exchange_account_get_global_catalog (ExchangeAccount *account)
-{
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- return account->priv->gc;
-}
-
-/**
- * exchange_account_fetch:
- * @acct: an #ExchangeAccount
- *
- * Return value: @account's #EAccount, if it is connected and
- * online, or %NULL if not.
- **/
-EAccount *
-exchange_account_fetch (ExchangeAccount *acct)
-{
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (acct), NULL);
-
- return acct->priv->account;
-}
-
-/**
- * exchange_account_get_account_uri_param:
- * @acct: and #ExchangeAccount
- * @param: uri param name to get
- *
- * Reads the parameter #param from the source url of the underlying EAccount.
- * Returns the value or NULL. Returned value should be freed with g_free.
- **/
-gchar *
-exchange_account_get_account_uri_param (ExchangeAccount *acct, const gchar *param)
-{
- EAccount *account;
- E2kUri *uri;
- gchar *res;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (acct), NULL);
- g_return_val_if_fail (param != NULL, NULL);
-
- account = exchange_account_fetch (acct);
- g_return_val_if_fail (account != NULL, NULL);
-
- uri = e2k_uri_new (e_account_get_string (account, E_ACCOUNT_SOURCE_URL));
- g_return_val_if_fail (uri != NULL, NULL);
-
- res = g_strdup (e2k_uri_get_param (uri, param));
-
- e2k_uri_free (uri);
-
- return res;
-}
-
-/**
- * exchange_account_get_standard_uri:
- * @account: an #ExchangeAccount
- * @item: the short name of the standard URI
- *
- * Looks up the value of one of the standard URIs on @account.
- * Supported values for @item are:
- * "calendar", "contacts", "deleteditems", "drafts", "inbox",
- * "journal", "notes", "outbox", "sentitems", "tasks", and
- * "sendmsg" (the special mail submission URI)
- *
- * Return value: the value of the standard URI, or %NULL if the
- * account is not connected or the property is invalid or not
- * defined on @account.
- **/
-const gchar *
-exchange_account_get_standard_uri (ExchangeAccount *account, const gchar *item)
-{
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- if (!account->priv->standard_uris)
- return NULL;
-
- return g_hash_table_lookup (account->priv->standard_uris, item);
-}
-
-/**
- * exchange_account_get_standard_uri_for:
- * @account: an #ExchangeAccount
- * @home_uri: the home URI of a user
- * @std_uri_prop: the %E2K_PR_STD_FOLDER property to look up
- *
- * Looks up the URI of a folder in another user's mailbox.
- *
- * Return value: the URI of the folder, or %NULL if either the folder
- * doesn't exist or the user doesn't have permission to access it.
- **/
-gchar *
-exchange_account_get_standard_uri_for (ExchangeAccount *account,
- const gchar *home_uri,
- const gchar *std_uri_prop)
-{
- gchar *foreign_uri, *prop;
- E2kHTTPStatus status;
- E2kResult *results;
- gint nresults = 0;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- foreign_uri = e2k_uri_concat (home_uri, "NON_IPM_SUBTREE");
- status = e2k_context_propfind (account->priv->ctx, NULL, foreign_uri,
- &std_uri_prop, 1,
- &results, &nresults);
- g_free (foreign_uri);
-
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status) || nresults == 0)
- return NULL;
-
- prop = e2k_properties_get_prop (results[0].props, std_uri_prop);
- if (prop)
- foreign_uri = e2k_strdup_with_trailing_slash (prop);
- else
- foreign_uri = NULL;
- e2k_results_free (results, nresults);
-
- return foreign_uri;
-}
-
-/**
- * exchange_account_get_foreign_uri:
- * @account: an #ExchangeAccount
- * @entry: an #E2kGlobalCatalogEntry with mailbox data
- * @std_uri_prop: the %E2K_PR_STD_FOLDER property to look up, or %NULL
- *
- * Looks up the URI of a folder in another user's mailbox. If
- * @std_uri_prop is %NULL, the URI for the top level of the user's
- * mailbox is returned.
- *
- * Return value: the URI of the folder, or %NULL if either the folder
- * doesn't exist or the user doesn't have permission to access it.
- **/
-gchar *
-exchange_account_get_foreign_uri (ExchangeAccount *account,
- E2kGlobalCatalogEntry *entry,
- const gchar *std_uri_prop)
-{
- gchar *home_uri, *foreign_uri;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- if (account->priv->uris_use_email) {
- gchar *mailbox;
-
- mailbox = g_strndup (entry->email, strcspn (entry->email, "@"));
- home_uri = g_strdup_printf (account->priv->http_uri_schema,
- entry->exchange_server, mailbox);
- g_free (mailbox);
- } else {
- home_uri = g_strdup_printf (account->priv->http_uri_schema,
- entry->exchange_server,
- entry->mailbox);
- }
- if (!std_uri_prop)
- return home_uri;
-
- foreign_uri = exchange_account_get_standard_uri_for (account,
- home_uri,
- std_uri_prop);
- g_free (home_uri);
-
- return foreign_uri;
-}
-
-/* Scans the subscribed users folders. */
-/*FIXME This function is not really required if the syncronization
- problem between exchange and evolution is fixed. Exchange does not get to know
- if an user's folder is subscribed from evolution */
-void
-exchange_account_scan_foreign_hierarchy (ExchangeAccount *account, const gchar *user_email)
-{
- gchar *dir;
- ExchangeHierarchy *hier;
- gint mode;
-
- hier = g_hash_table_lookup (account->priv->foreign_hierarchies, user_email);
- if (hier) {
- exchange_hierarchy_rescan (hier);
- return;
- }
-
- dir = g_strdup_printf ("%s/%s", account->storage_dir, user_email);
- if (g_file_test (dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
- hier = exchange_hierarchy_foreign_new_from_dir (account, dir);
- g_free (dir);
- if (hier) {
- exchange_account_is_offline (account, &mode);
- setup_hierarchy_foreign (account, hier);
- exchange_hierarchy_scan_subtree (hier, hier->toplevel, mode);
- }
- }
-}
-
-/**
- * exchange_account_get_hierarchy_by_email:
- * @account: an #ExchangeAccount
- * @email: email id of the foreign user
- *
- * If the hierarchy is present just return it back. Else try to get it
- * from the filesystem and return it.
- *
- * Return value: Returns the ExchangeHierarchy of the foreign user's folder.
- **/
-
-ExchangeHierarchy *
-exchange_account_get_hierarchy_by_email (ExchangeAccount *account, const gchar *email)
-{
- gchar *dir;
- ExchangeHierarchy *hier = NULL;
- gint mode;
-
- g_return_val_if_fail (email != NULL, NULL);
-
- hier = g_hash_table_lookup (account->priv->foreign_hierarchies, email);
- if (!hier) {
- dir = g_strdup_printf ("%s/%s", account->storage_dir, email);
- if (g_file_test (dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
- hier = exchange_hierarchy_foreign_new_from_dir (account, dir);
- g_free (dir);
- if (hier) {
- exchange_account_is_offline (account, &mode);
- setup_hierarchy_foreign (account, hier);
- }
- }
- }
-
- return hier;
- }
-
-/**
- * exchange_account_get_folder:
- * @account: an #ExchangeAccount
- * @path_or_uri: the shell path or URI referring to the folder
- *
- * Return value: an #EFolder corresponding to the indicated
- * folder.
- **/
-EFolder *
-exchange_account_get_folder (ExchangeAccount *account,
- const gchar *path_or_uri)
-{
- EFolder *folder;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- if (!path_or_uri)
- return NULL;
- g_static_rec_mutex_lock (&account->priv->folders_lock);
- folder = g_hash_table_lookup (account->priv->folders, path_or_uri);
- g_static_rec_mutex_unlock (&account->priv->folders_lock);
-
- return folder;
-}
-
-static gint
-folder_comparator (gconstpointer a, gconstpointer b)
-{
- EFolder **fa = (EFolder **)a;
- EFolder **fb = (EFolder **)b;
-
- return strcmp (e_folder_exchange_get_path (*fa),
- e_folder_exchange_get_path (*fb));
-}
-
-struct _folders_tree {
- gchar *path;
- GPtrArray *folders;
-};
-
-static void
-add_folder (gpointer key, gpointer value, gpointer folders)
-{
- EFolder *folder = value;
-
- d(g_print ("%s:%s: key=[%s]\t folder-path=[%s]\n", G_STRLOC, G_STRFUNC,
- key, e_folder_exchange_get_path (folder)));
-
- /* Each folder appears under three different keys, but
- * we only want to add it to the results array once. So
- * we only add when we see the "path" key.
- */
- if (!strcmp (key, e_folder_exchange_get_path (folder)))
- g_ptr_array_add (folders, folder);
-}
-
-static void
-add_folder_tree (gpointer key, gpointer value, gpointer folders)
-{
- EFolder *folder = value;
- struct _folders_tree *fld_tree = (struct _folders_tree *) folders;
-
- if (!fld_tree || !fld_tree->path)
- return;
-
- if (g_str_has_prefix (key, fld_tree->path))
- add_folder (key, folder, fld_tree->folders);
-}
-
-/**
- * exchange_account_get_folders:
- * @account: an #ExchangeAccount
- *
- * Return an array of folders (sorted such that parents will occur
- * before children). If the caller wants to keep up to date with the
- * list of folders, he should also listen to %new_folder and
- * %removed_folder signals.
- *
- * Return value: an array of folders. The array should be freed with
- * g_ptr_array_free().
- **/
-GPtrArray *
-exchange_account_get_folders (ExchangeAccount *account)
-{
- GPtrArray *folders;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- folders = g_ptr_array_new ();
- g_static_rec_mutex_lock (&account->priv->folders_lock);
- g_hash_table_foreach (account->priv->folders, add_folder, folders);
- g_static_rec_mutex_unlock (&account->priv->folders_lock);
-
- qsort (folders->pdata, folders->len,
- sizeof (EFolder *), folder_comparator);
-
- return folders;
-}
-
-/**
- * exchange_account_get_folder_tree:
- * @account: an #ExchangeAccount
- *
- * Return an array of folders (sorted such that parents will occur
- * before children). If the caller wants to keep up to date with the
- * list of folders, he should also listen to %new_folder and
- * %removed_folder signals.
- *
- * Return value: an array of folders. The array should be freed with
- * g_ptr_array_free().
- **/
-GPtrArray *
-exchange_account_get_folder_tree (ExchangeAccount *account, gchar * path)
-{
- GPtrArray *folders = NULL;
- EFolder *folder = NULL;
- ExchangeHierarchy *hier = NULL;
-
- struct _folders_tree *fld_tree = NULL;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- if (!get_folder (account, path, &folder, &hier))
- return folders;
-
- exchange_hierarchy_scan_subtree (hier, folder, account->priv->account_online);
-
- folders = g_ptr_array_new ();
- fld_tree = g_new0 (struct _folders_tree, 1);
- fld_tree->path = path;
- fld_tree->folders = folders;
-
- g_static_rec_mutex_lock (&account->priv->folders_lock);
- g_hash_table_foreach (account->priv->folders, add_folder_tree, fld_tree);
- g_static_rec_mutex_unlock (&account->priv->folders_lock);
-
- qsort (folders->pdata, folders->len,
- sizeof (EFolder *), folder_comparator);
-
- g_free (fld_tree);
-
- return folders;
-}
-
-/**
- * exchange_account_get_quota_limit:
- * @account: an #ExchangeAccount
- *
- * Return the value of the quota limit reached.
- *
- * Return value: an gint
- **/
-gint
-exchange_account_get_quota_limit (ExchangeAccount *account)
-{
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), 0);
-
- return account->priv->quota_limit;
-}
-
-gint
-exchange_account_check_password_expiry (ExchangeAccount *account)
-{
- E2kGlobalCatalogEntry *entry=NULL; /* This is never set before it's used! */
- gint max_pwd_age_days = -1;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), 0);
-
- max_pwd_age_days = find_passwd_exp_period (account, entry);
- return max_pwd_age_days;
-}
-
-gchar *
-exchange_account_get_username (ExchangeAccount *account)
-{
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- return account->priv->username;
-}
-
-/**
- * exchange_account_get_windows_domain :
- * @account : #ExchangeAccount
- *
- * Returns the Windows domain
- *
- * Return value : Windows domain
- **/
-gchar *
-exchange_account_get_windows_domain (ExchangeAccount *account)
-{
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- return account->priv->windows_domain;
-}
-
-/**
- * exchange_account_get_email_id :
- * @account : #ExchangeAccount
- *
- * Retunrs user's e-mail id.
- *
- * Return value : e-mail id string.
- **/
-gchar *
-exchange_account_get_email_id (ExchangeAccount *account)
-{
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- return account->priv->identity_email;
-}
-
-/**
- * exchange_account_folder_size_add :
- * @account : #ExchangeAccount
- * @folder_name :
- * @size : Size of @folder_name
- *
- * Updates the #ExchangeFolderSize object with the @size of @folder_name
- *
- * Return value : void
- **/
-void
-exchange_account_folder_size_add (ExchangeAccount *account,
- const gchar *folder_name,
- gdouble size)
-{
- g_return_if_fail (EXCHANGE_IS_ACCOUNT (account));
-
- exchange_folder_size_update (account->priv->fsize, folder_name, size);
-}
-
-/**
- * exchange_account_folder_size_remove :
- * @account : #ExchangeAccount
- * @folder_name :
- *
- * Removes the entry for @folder_name in #ExchangeFolderSize object
- *
- * Return value : void
- **/
-void
-exchange_account_folder_size_remove (ExchangeAccount *account,
- const gchar *folder_name)
-{
- g_return_if_fail (EXCHANGE_IS_ACCOUNT (account));
-
- exchange_folder_size_remove (account->priv->fsize, folder_name);
-}
-
-/**
- * exchange_account_folder_size_rename :
- * @account : #ExchangeAccount
- * @old_name : Old name of the folder
- * @new_name : New name of the folder
- *
- * Removes the entry for @old_name in #ExchangeFolderSize object and adds
- * a new entry for @new_name with the same folder size
- *
- * Return value : void
- **/
-void
-exchange_account_folder_size_rename (ExchangeAccount *account,
- const gchar *old_name,
- const gchar *new_name)
-{
- gdouble cached_size;
-
- g_return_if_fail (EXCHANGE_IS_ACCOUNT (account));
-
- cached_size = exchange_folder_size_get (account->priv->fsize,
- old_name);
- if (cached_size >= 0) {
- exchange_folder_size_remove (account->priv->fsize, old_name);
- exchange_folder_size_update (account->priv->fsize,
- new_name, cached_size);
- }
-
-}
-
-/**
- * exchange_account_folder_size_get_model :
- * @account : #ExchangeAccount
- *
- * Returns the model store of #ExchangeFolderSize object
- *
- * Return value : The model store. A GtkListStore
- **/
-GtkListStore *
-exchange_account_folder_size_get_model (ExchangeAccount *account)
-{
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- return exchange_folder_size_get_model (account->priv->fsize);
-}
-
-gchar *
-exchange_account_get_authtype (ExchangeAccount *account)
-{
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- if (account->priv->auth_pref == E2K_AUTOCONFIG_USE_BASIC)
- return g_strdup ("Basic");
- else if (account->priv->auth_pref == E2K_AUTOCONFIG_USE_NTLM)
- return g_strdup ("NTLM");
-
- return NULL;
-}
-
-/**
- * exchange_account_new:
- * @adata: an #EAccount
- *
- * An #ExchangeAccount is essentially an #E2kContext with
- * associated configuration.
- *
- * Return value: a new #ExchangeAccount corresponding to @adata
- **/
-ExchangeAccount *
-exchange_account_new (EAccountList *account_list, EAccount *adata)
-{
- ExchangeAccount *account;
- gchar *enc_user, *mailbox;
- const gchar *param, *proto="http", *owa_path, *pf_server, *owa_url;
- const gchar *passwd_exp_warn_period, *offline_sync;
- E2kUri *uri;
-
- uri = e2k_uri_new (adata->source->url);
- if (!uri) {
- g_warning ("Could not parse exchange uri '%s'",
- adata->source->url);
- return NULL;
- }
-
- account = g_object_new (EXCHANGE_TYPE_ACCOUNT, NULL);
- if (!account)
- return NULL;
- account->priv->account_list = account_list;
- g_object_ref (account_list);
- account->priv->account = adata;
- g_object_ref (adata);
-
- account->account_name = g_strdup (adata->name);
-
- account->storage_dir = g_strdup_printf ("%s/.evolution/exchange/%s@%s",
- g_get_home_dir (),
- uri->user, uri->host);
- /*account->account_filename = strrchr (account->storage_dir, '/') + 1;
- e_filename_make_safe (account->account_filename); */
-
- /* Identity info */
- account->priv->identity_name = g_strdup (adata->id->name);
- account->priv->identity_email = g_strdup (adata->id->address);
-
- /* URI, etc, info */
- enc_user = e2k_uri_encode (uri->user, FALSE, "@/;:");
-
- if (uri->authmech)
- account->priv->uri_authority = g_strdup_printf ("%s;auth=%s@%s", enc_user,
- uri->authmech, uri->host);
- else
- account->priv->uri_authority = g_strdup_printf ("%s@%s", enc_user,
- uri->host);
- g_free (enc_user);
-
- account->account_filename = account->priv->uri_authority;
-
- account->priv->source_uri = g_strdup_printf ("exchange://%s/", account->priv->uri_authority);
-
- /* Backword compatibility; FIXME, we should just migrate the
- * password from this to source_uri.
- * old_uri_authority = g_strdup_printf ("%s@%s", enc_user,
- * uri->host);
- * old_uri_authority needs to be used in the key for migrating
- * passwords remembered.
- */
- account->priv->password_key = g_strdup_printf ("exchange://%s/",
- account->priv->uri_authority);
-
- account->priv->username = g_strdup (uri->user);
- if (uri->domain)
- account->priv->windows_domain = g_strdup (uri->domain);
- else
- account->priv->windows_domain = NULL;
- account->exchange_server = g_strdup (uri->host);
- if (uri->authmech && !strcmp (uri->authmech, "Basic"))
- account->priv->auth_pref = E2K_AUTOCONFIG_USE_BASIC;
- else
- account->priv->auth_pref = E2K_AUTOCONFIG_USE_NTLM;
- param = e2k_uri_get_param (uri, "ad_server");
- if (param && *param) {
- account->priv->ad_server = g_strdup (param);
- param = e2k_uri_get_param (uri, "ad_limit");
- if (param)
- account->priv->ad_limit = atoi (param);
- param = e2k_uri_get_param (uri, "ad_auth");
- if (!param || g_ascii_strcasecmp (param, "default") == 0)
- account->priv->ad_auth = E2K_AUTOCONFIG_USE_GAL_DEFAULT;
- else if (g_ascii_strcasecmp (param, "basic") == 0)
- account->priv->ad_auth = E2K_AUTOCONFIG_USE_GAL_BASIC;
- else if (g_ascii_strcasecmp (param, "ntlm") == 0)
- account->priv->ad_auth = E2K_AUTOCONFIG_USE_GAL_NTLM;
- else
- account->priv->ad_auth = E2K_AUTOCONFIG_USE_GAL_DEFAULT;
- }
-
- passwd_exp_warn_period = e2k_uri_get_param (uri, "passwd_exp_warn_period");
- if (!passwd_exp_warn_period || !*passwd_exp_warn_period)
- account->priv->passwd_exp_warn_period = -1;
- else
- account->priv->passwd_exp_warn_period = atoi (passwd_exp_warn_period);
-
- offline_sync = e2k_uri_get_param (uri, "offline_sync");
- if (!offline_sync)
- account->priv->offline_sync = FALSE;
- else
- account->priv->offline_sync = TRUE;
-
- owa_path = e2k_uri_get_param (uri, "owa_path");
- if (!owa_path || !*owa_path)
- owa_path = "exchange";
- else if (*owa_path == '/')
- owa_path++;
-
- pf_server = e2k_uri_get_param (uri, "pf_server");
- if (!pf_server || !*pf_server)
- pf_server = uri->host;
-
- /* We set protocol reading owa_url, instead of having use_ssl parameter
- * because we don't have SSL section anymore in the account creation
- * druid and account editor
- */
- /* proto = e2k_uri_get_param (uri, "use_ssl") ? "https" : "http"; */
-
- owa_url = e2k_uri_get_param (uri, "owa_url");
- if (owa_url) {
- account->priv->owa_url = g_strdup (owa_url);
- if (!strncmp (owa_url, "https:", 6))
- proto = "https";
- }
-
- if (uri->port != 0) {
- account->priv->http_uri_schema =
- g_strdup_printf ("%s://%%s:%d/%s/%%s/",
- proto, uri->port, owa_path);
- account->public_uri =
- g_strdup_printf ("%s://%s:%d/public",
- proto, pf_server, uri->port);
- } else {
- account->priv->http_uri_schema =
- g_strdup_printf ("%s://%%s/%s/%%s/", proto, owa_path);
- account->public_uri =
- g_strdup_printf ("%s://%s/public", proto, pf_server);
- }
-
- param = e2k_uri_get_param (uri, "mailbox");
- if (!param || !*param)
- param = uri->user;
- else if (!g_ascii_strncasecmp (param, account->priv->identity_email, strlen (param)))
- account->priv->uris_use_email = TRUE;
- mailbox = e2k_uri_encode (param, TRUE, "/");
- account->home_uri = g_strdup_printf (account->priv->http_uri_schema,
- uri->host, mailbox);
- g_free (mailbox);
-
- param = e2k_uri_get_param (uri, "filter");
- if (param)
- account->filter_inbox = TRUE;
- param = e2k_uri_get_param (uri, "filter_junk");
- if (param)
- account->filter_junk = TRUE;
- param = e2k_uri_get_param (uri, "filter_junk_inbox");
- if (param)
- account->filter_junk_inbox_only = TRUE;
-
- e2k_uri_free (uri);
-
- return account;
-}
-
-/**
- * exchange_account_get_hierarchy_by_type:
- * @account: an #ExchangeAccount
- * @type: Hierarchy type
- *
- * Returns the non-foreign hierarchy pointer for the requested type
- *
- * Return value: Returns the hierarchy pointer for the requested type
- **/
-
-ExchangeHierarchy*
-exchange_account_get_hierarchy_by_type (ExchangeAccount* acct,
- ExchangeHierarchyType type)
-{
- gint i;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (acct), NULL);
- g_return_val_if_fail (type != EXCHANGE_HIERARCHY_FOREIGN, NULL);
-
- for (i = 0; i < acct->priv->hierarchies->len; i++) {
- if (EXCHANGE_HIERARCHY (acct->priv->hierarchies->pdata[i])->type == type)
- return EXCHANGE_HIERARCHY (acct->priv->hierarchies->pdata[i]);
- }
- return NULL;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __EXCHANGE_ACCOUNT_H__
-#define __EXCHANGE_ACCOUNT_H__
-
-#include <exchange-types.h>
-#include <exchange-constants.h>
-#include "e2k-autoconfig.h"
-#include "e2k-context.h"
-#include "e2k-global-catalog.h"
-#include "e2k-security-descriptor.h"
-#include "e-folder.h"
-#include <libedataserver/e-account-list.h>
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define EXCHANGE_TYPE_ACCOUNT (exchange_account_get_type ())
-#define EXCHANGE_ACCOUNT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXCHANGE_TYPE_ACCOUNT, ExchangeAccount))
-#define EXCHANGE_ACCOUNT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EXCHANGE_TYPE_ACCOUNT, ExchangeAccountClass))
-#define EXCHANGE_IS_ACCOUNT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXCHANGE_TYPE_ACCOUNT))
-#define EXCHANGE_IS_ACCOUNT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EXCHANGE_TYPE_ACCOUNT))
-
-struct _ExchangeAccount {
- GObject parent;
-
- ExchangeAccountPrivate *priv;
-
- /* account_name is the user-specified UTF8 display name.
- * account_filename is "username@hostname" run through
- * e_filename_make_safe.
- */
- gchar *account_name, *account_filename, *storage_dir;
- gchar *exchange_server, *home_uri, *public_uri;
- gchar *legacy_exchange_dn, *default_timezone;
-
- gboolean filter_inbox, filter_junk, filter_junk_inbox_only;
- gdouble mbox_size;
-};
-
-struct _ExchangeAccountClass {
- GObjectClass parent_class;
-
- /* signals */
- void (*connected) (ExchangeAccount *, E2kContext *);
-
- void (*new_folder) (ExchangeAccount *, EFolder *);
- void (*removed_folder) (ExchangeAccount *, EFolder *);
-};
-
-typedef enum {
- EXCHANGE_ACCOUNT_CONFIG_ERROR,
- EXCHANGE_ACCOUNT_PASSWORD_WEAK_ERROR,
- EXCHANGE_ACCOUNT_PASSWORD_CHANGE_FAILED,
- EXCHANGE_ACCOUNT_PASSWORD_CHANGE_SUCCESS,
- EXCHANGE_ACCOUNT_OFFLINE,
- EXCHANGE_ACCOUNT_PASSWORD_INCORRECT,
- EXCHANGE_ACCOUNT_DOMAIN_ERROR,
- EXCHANGE_ACCOUNT_MAILBOX_NA,
- EXCHANGE_ACCOUNT_VERSION_ERROR,
- EXCHANGE_ACCOUNT_WSS_ERROR,
- EXCHANGE_ACCOUNT_NO_MAILBOX,
- EXCHANGE_ACCOUNT_RESOLVE_ERROR,
- EXCHANGE_ACCOUNT_CONNECT_ERROR,
- EXCHANGE_ACCOUNT_PASSWORD_EXPIRED,
- EXCHANGE_ACCOUNT_UNKNOWN_ERROR,
- EXCHANGE_ACCOUNT_QUOTA_RECIEVE_ERROR,
- EXCHANGE_ACCOUNT_QUOTA_SEND_ERROR,
- EXCHANGE_ACCOUNT_QUOTA_WARN,
- EXCHANGE_ACCOUNT_CONNECT_SUCCESS
-} ExchangeAccountResult;
-
-GType exchange_account_get_type (void);
-ExchangeAccount *exchange_account_new (EAccountList *account_list,
- EAccount *adata);
-E2kContext *exchange_account_get_context (ExchangeAccount *acct);
-E2kGlobalCatalog *exchange_account_get_global_catalog (ExchangeAccount *acct);
-
-EAccount *exchange_account_fetch (ExchangeAccount *acct);
-gchar *exchange_account_get_account_uri_param (ExchangeAccount *acct, const gchar *param);
-
-const gchar *exchange_account_get_standard_uri (ExchangeAccount *acct,
- const gchar *item);
-
-gchar *exchange_account_get_standard_uri_for (ExchangeAccount *acct,
- const gchar *home_uri,
- const gchar *std_uri_prop);
-gchar *exchange_account_get_foreign_uri (ExchangeAccount *acct,
- E2kGlobalCatalogEntry *entry,
- const gchar *std_uri_prop);
-ExchangeHierarchy *exchange_account_get_hierarchy_by_email (ExchangeAccount *account, const gchar *email);
-
-gchar *exchange_account_get_authtype (ExchangeAccount *account);
-
-E2kContext *exchange_account_connect (ExchangeAccount *acct,
- const gchar *pword,
- ExchangeAccountResult *result);
-
-EFolder *exchange_account_get_folder (ExchangeAccount *acct,
- const gchar *path_or_uri);
-GPtrArray *exchange_account_get_folders (ExchangeAccount *acct);
-
-GPtrArray *exchange_account_get_folder_tree (ExchangeAccount *account, gchar * path);
-
-ExchangeHierarchy *exchange_account_get_hierarchy_by_type (ExchangeAccount *acct,
- ExchangeHierarchyType type);
-
-void exchange_account_rescan_tree (ExchangeAccount *acct);
-
-gchar *exchange_account_get_password (ExchangeAccount *acct);
-
-ExchangeAccountResult exchange_account_set_password (ExchangeAccount *acct,
- gchar *old_password,
- gchar *new_password);
-
-void exchange_account_forget_password (ExchangeAccount *acct);
-
-void exchange_account_set_save_password (ExchangeAccount *account,
- gboolean save_password);
-
-gboolean exchange_account_is_save_password (ExchangeAccount *account);
-
-gboolean exchange_account_set_offline (ExchangeAccount *account);
-
-gboolean exchange_account_set_online (ExchangeAccount *account);
-
-void exchange_account_is_offline (ExchangeAccount *account,
- gint *mode);
-
-void exchange_account_is_offline_sync_set (ExchangeAccount *account,
- gint *mode);
-
-typedef enum {
- EXCHANGE_ACCOUNT_FOLDER_OK,
- EXCHANGE_ACCOUNT_FOLDER_ALREADY_EXISTS,
- EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST,
- EXCHANGE_ACCOUNT_FOLDER_UNKNOWN_TYPE,
- EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED,
- EXCHANGE_ACCOUNT_FOLDER_OFFLINE,
- EXCHANGE_ACCOUNT_FOLDER_UNSUPPORTED_OPERATION,
- EXCHANGE_ACCOUNT_FOLDER_GC_NOTREACHABLE,
- EXCHANGE_ACCOUNT_FOLDER_NO_SUCH_USER,
- EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR
-} ExchangeAccountFolderResult;
-
-ExchangeAccountFolderResult exchange_account_create_folder (ExchangeAccount *account,
- const gchar *path,
- const gchar *type);
-ExchangeAccountFolderResult exchange_account_remove_folder (ExchangeAccount *account,
- const gchar *path);
-ExchangeAccountFolderResult exchange_account_xfer_folder (ExchangeAccount *account,
- const gchar *source_path,
- const gchar *dest_path,
- gboolean remove_source);
-ExchangeAccountFolderResult exchange_account_open_folder (ExchangeAccount *account,
- const gchar *path);
-
-ExchangeAccountFolderResult exchange_account_discover_shared_folder (ExchangeAccount *account,
- const gchar *user,
- const gchar *folder_name,
- EFolder **folder);
-void exchange_account_cancel_discover_shared_folder (ExchangeAccount *account,
- const gchar *user,
- const gchar *folder);
-ExchangeAccountFolderResult exchange_account_remove_shared_folder (ExchangeAccount *account,
- const gchar *path);
-
-ExchangeAccountFolderResult exchange_account_add_favorite (ExchangeAccount *account,
- EFolder *folder);
-ExchangeAccountFolderResult exchange_account_remove_favorite (ExchangeAccount *account,
- EFolder *folder);
-
-gboolean exchange_account_is_favorite_folder (ExchangeAccount *account,
- EFolder *folder);
-
-gchar * exchange_account_get_username (ExchangeAccount *account);
-
-gchar * exchange_account_get_windows_domain (ExchangeAccount *account);
-
-gchar * exchange_account_get_email_id (ExchangeAccount *account);
-
-gint exchange_account_get_quota_limit (ExchangeAccount *account);
-
-gint exchange_account_check_password_expiry (ExchangeAccount *account);
-
-/* Folder Size methods */
-void exchange_account_folder_size_add (ExchangeAccount *account,
- const gchar *folder_name,
- gdouble size);
-void exchange_account_folder_size_remove (ExchangeAccount *account,
- const gchar *folder_name);
-void exchange_account_folder_size_rename (ExchangeAccount *account,
- const gchar *old_name,
- const gchar *new_name);
-GtkListStore *exchange_account_folder_size_get_model (ExchangeAccount *account);
-void exchange_account_scan_foreign_hierarchy (ExchangeAccount *account,
- const gchar *user_email);
-
-G_END_DECLS
-
-#endif /* __EXCHANGE_ACCOUNT_H__ */
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __EXCHANGE_CONSTANTS_H__
-#define __EXCHANGE_CONSTANTS_H__
-
-enum {
- UNSUPPORTED_MODE = 0,
- OFFLINE_MODE,
- ONLINE_MODE
-};
-
-typedef enum {
- EXCHANGE_CALENDAR_FOLDER,
- EXCHANGE_TASKS_FOLDER,
- EXCHANGE_CONTACTS_FOLDER
-}FolderType;
-
-/* This flag indicates that its other user's folder. We encode this flag
- with the FolderType to identify the same. We are doing this to
- avoid ABI/API break. */
-#define FORIEGN_FOLDER_FLAG 0x0100
-
-#define EXCHANGE_COMPONENT_FACTORY_IID "OAFIID:GNOME_Evolution_Exchange_Component_Factory:" BASE_VERSION
-#define EXCHANGE_COMPONENT_IID "OAFIID:GNOME_Evolution_Exchange_Component:" BASE_VERSION
-#define EXCHANGE_CALENDAR_FACTORY_ID "OAFIID:GNOME_Evolution_Exchange_Connector_CalFactory:" API_VERSION
-#define EXCHANGE_ADDRESSBOOK_FACTORY_ID "OAFIID:GNOME_Evolution_Exchange_Connector_BookFactory:" API_VERSION
-#define EXCHANGE_AUTOCONFIG_WIZARD_ID "OAFIID:GNOME_Evolution_Exchange_Connector_Startup_Wizard:" BASE_VERSION
-
-#endif
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2001-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "exchange-esource.h"
-
-#include <libedataserver/e-source.h>
-#include <libedataserver/e-source-list.h>
-#include <libedataserver/e-source-group.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-static gboolean is_offline (void);
-
-static ESourceGroup *
-find_account_group (ESourceList *source_list, ExchangeAccount *exa)
-{
- ESourceGroup *group;
- EAccount *account;
-
- g_return_val_if_fail (exa != NULL, NULL);
- g_return_val_if_fail (exa->account_name != NULL, NULL);
- g_return_val_if_fail (source_list != NULL, NULL);
-
- account = exchange_account_fetch (exa);
- g_return_val_if_fail (account != NULL, NULL);
- g_return_val_if_fail (account->uid != NULL, NULL);
-
- group = e_source_list_peek_group_by_properties (source_list, "account-uid", account->uid, NULL);
- if (!group) {
- /* check whether is stored only with an account name - the old style */
- GSList *g;
-
- for (g = e_source_list_peek_groups (source_list); g != NULL; g = g->next) {
- group = E_SOURCE_GROUP (g->data);
-
- if (strcmp (e_source_group_peek_name (group), exa->account_name) == 0)
- break;
-
- group = NULL;
- }
-
- if (group)
- e_source_group_set_property (group, "account-uid", account->uid);
- }
-
- return group;
-}
-
-void
-add_folder_esource (ExchangeAccount *account,
- FolderType folder_type,
- const gchar *folder_name,
- const gchar *physical_uri)
-{
- ESource *source = NULL;
- ESourceGroup *source_group = NULL;
- gchar *relative_uri = NULL;
- GSList *ids;
- GConfClient *client;
- gboolean is_contacts_folder = TRUE, group_new = FALSE, source_new = FALSE;
- const gchar *offline = NULL;
- gchar *username, *windows_domain, *useremail, *authtype = NULL;
- gint mode;
- ESourceList *source_list = NULL;
- gboolean offline_flag, update_selection = TRUE, foriegn_folder;
-
- client = gconf_client_get_default ();
-
- /* decode the flag */
- foriegn_folder = folder_type & FORIEGN_FOLDER_FLAG;
-
- /* Unset the flag */
- folder_type = folder_type & ~FORIEGN_FOLDER_FLAG;
-
- if (folder_type == EXCHANGE_CONTACTS_FOLDER) {
- source_list = e_source_list_new_for_gconf ( client,
- CONF_KEY_CONTACTS);
- /* Modify the URI handling of Contacts to the same way as calendar and tasks */
- if (!g_str_has_prefix (physical_uri, "gal://")) {
- relative_uri = g_strdup (physical_uri + strlen (EXCHANGE_URI_PREFIX));
- }
- }
- else if (folder_type == EXCHANGE_CALENDAR_FOLDER) {
- source_list = e_source_list_new_for_gconf ( client,
- CONF_KEY_CAL);
- relative_uri = g_strdup (physical_uri + strlen (EXCHANGE_URI_PREFIX));
- is_contacts_folder = FALSE;
- }
- else if (folder_type == EXCHANGE_TASKS_FOLDER) {
- source_list = e_source_list_new_for_gconf ( client,
- CONF_KEY_TASKS);
- relative_uri = g_strdup (physical_uri + strlen (EXCHANGE_URI_PREFIX));
- is_contacts_folder = FALSE;
- }
-
- exchange_account_is_offline_sync_set (account, &mode);
-
- 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));
-
- useremail = exchange_account_get_email_id (account);
- authtype = exchange_account_get_authtype (account);
-
- if ((source_group = find_account_group (source_list, account)) == NULL) {
- source_group = e_source_group_new (account->account_name,
- EXCHANGE_URI_PREFIX);
- if (!e_source_list_add_group (source_list, source_group, -1)) {
- g_object_unref (source_list);
- g_object_unref (source_group);
- g_object_unref (client);
- g_free (relative_uri);
- g_free (username);
- if (authtype)
- g_free (authtype);
- return;
- }
- e_source_group_set_property (source_group, "account-uid", exchange_account_fetch (account)->uid);
-
- if (is_contacts_folder && g_str_has_prefix (physical_uri, "gal://")) {
- gchar *browse = exchange_account_get_account_uri_param (account, "ad_browse");
-
- source = e_source_new_with_absolute_uri (folder_name,
- physical_uri);
- e_source_set_property (source, "completion", "true");
- e_source_set_property (source, "can-browse", browse ? "1" : NULL);
- g_free (browse);
- }
- else {
- source = e_source_new (folder_name, relative_uri);
- }
-
- if (mode == OFFLINE_MODE) {
- /* If account is marked for offline sync during account
- * creation, mark all the folders for offline sync
- */
- e_source_set_property (source, "offline_sync", "1");
- }
-
- if (foriegn_folder && (folder_type != EXCHANGE_CONTACTS_FOLDER)) {
- e_source_set_property (source, "alarm", "false");
- e_source_set_property (source, "foreign", "1");
- e_source_set_property (source, "subscriber", useremail);
- }
-
- 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);
- if (is_contacts_folder)
- e_source_set_property (source, "auth", "plain/password");
- else
- e_source_set_property (source, "auth", "1");
- e_source_group_add_source (source_group, source, -1);
- e_source_list_sync (source_list, NULL);
- group_new = source_new = TRUE;
- }
- else {
- /* source group already exists*/
- if ((source = e_source_group_peek_source_by_name (source_group,
- folder_name)) == NULL) {
- if (is_contacts_folder && g_str_has_prefix (physical_uri, "gal://")) {
- gchar *browse = exchange_account_get_account_uri_param (account, "ad_browse");
-
- source = e_source_new_with_absolute_uri (
- folder_name, physical_uri);
- e_source_set_property (source, "completion", "true");
- e_source_set_property (source, "can-browse", browse ? "1" : NULL);
- g_free (browse);
- }
- else {
- source = e_source_new (folder_name, relative_uri);
- }
-
- if (mode == OFFLINE_MODE)
- e_source_set_property (source, "offline_sync", "1");
-
- 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);
- if (is_contacts_folder)
- e_source_set_property (source, "auth", "plain/password");
- else
- e_source_set_property (source, "auth", "1");
-
- if (foriegn_folder && (folder_type != EXCHANGE_CONTACTS_FOLDER)) {
- e_source_set_property (source, "alarm", "false");
- e_source_set_property (source, "foreign", "1");
- e_source_set_property (source, "subscriber", useremail);
- }
-
- e_source_group_add_source (source_group, source, -1);
- source_new = TRUE;
- e_source_list_sync (source_list, NULL);
- } else {
- update_selection = FALSE;
- /* source group and source both already exist */
- offline = e_source_get_property (source, "offline_sync");
- if (!offline) {
- /* Folder doesn't have any offline property set */
- if (mode == OFFLINE_MODE) {
- e_source_set_property (source, "offline_sync", "1");
- e_source_list_sync (source_list, NULL);
- }
- }
-
- if (is_contacts_folder && g_str_has_prefix (physical_uri, "gal://")) {
- gchar *browse = exchange_account_get_account_uri_param (account, "ad_browse");
- const gchar *old_browse = e_source_get_property (source, "can-browse");
-
- if ((old_browse || browse) && (!old_browse || !browse)) {
- e_source_set_property (source, "can-browse", browse ? "1" : NULL);
- }
-
- g_free (browse);
- }
- }
- }
-
- offline_flag = is_offline ();
- if (source && !is_contacts_folder && update_selection) {
-
- /* Select the folder created */
- if (folder_type == EXCHANGE_CALENDAR_FOLDER && !offline_flag) {
- ids = gconf_client_get_list (client,
- CONF_KEY_SELECTED_CAL_SOURCES,
- GCONF_VALUE_STRING, NULL);
- ids = g_slist_append (ids,
- g_strdup (e_source_peek_uid (source)));
- gconf_client_set_list (client,
- CONF_KEY_SELECTED_CAL_SOURCES,
- GCONF_VALUE_STRING, ids, NULL);
- g_slist_foreach (ids, (GFunc) g_free, NULL);
- g_slist_free (ids);
- }
- else if (folder_type == EXCHANGE_TASKS_FOLDER && !offline_flag) {
- ids = gconf_client_get_list (client,
- CONF_KEY_SELECTED_TASKS_SOURCES,
- GCONF_VALUE_STRING, NULL);
-
- ids = g_slist_append (ids,
- g_strdup (e_source_peek_uid (source)));
- gconf_client_set_list (client,
- CONF_KEY_SELECTED_TASKS_SOURCES,
- GCONF_VALUE_STRING, ids, NULL);
- g_slist_foreach (ids, (GFunc) g_free, NULL);
- g_slist_free (ids);
- }
- }
-
- g_free (relative_uri);
- g_free (username);
- if (authtype)
- g_free (authtype);
-
- if (source_new)
- g_object_unref (source);
- if (group_new)
- g_object_unref (source_group);
- g_object_unref (source_list);
- g_object_unref (client);
-}
-
-void
-remove_folder_esource (ExchangeAccount *account,
- FolderType folder_type,
- const gchar *physical_uri)
-{
- ESourceGroup *group;
- ESource *source;
- GSList *groups;
- GSList *sources;
- gboolean found_group, is_contacts_folder = TRUE;
- gchar *read_uri = NULL;
- const gchar *source_uid;
- GSList *ids, *temp_ids, *node_to_be_deleted;
- GConfClient *client;
- ESourceList *source_list = NULL;
-
- client = gconf_client_get_default ();
-
- /* Remove ESource for a given folder */
- if (folder_type == EXCHANGE_CONTACTS_FOLDER) {
- source_list = e_source_list_new_for_gconf ( client,
- CONF_KEY_CONTACTS);
- }
- else if (folder_type == EXCHANGE_CALENDAR_FOLDER) {
- source_list = e_source_list_new_for_gconf ( client,
- CONF_KEY_CAL);
- is_contacts_folder = FALSE;
- }
- else if (folder_type == EXCHANGE_TASKS_FOLDER) {
- source_list = e_source_list_new_for_gconf ( client,
- CONF_KEY_TASKS);
- is_contacts_folder = FALSE;
- }
-
- groups = e_source_list_peek_groups (source_list);
- found_group = FALSE;
-
- for (; groups != NULL && !found_group; groups = g_slist_next (groups)) {
- group = E_SOURCE_GROUP (groups->data);
-
- if (strcmp (e_source_group_peek_name (group), account->account_name) == 0
- &&
- strcmp (e_source_group_peek_base_uri (group), EXCHANGE_URI_PREFIX) == 0) {
-
- sources = e_source_group_peek_sources (group);
-
- for (; sources != NULL; sources = g_slist_next (sources)) {
-
- source = E_SOURCE (sources->data);
- read_uri = e_source_get_uri (source);
-
- if (strcmp (read_uri, physical_uri) == 0) {
-
- source_uid = e_source_peek_uid (source);
- /* Folder Deleted - Remove only the source */
- /*
- e_source_group_remove_source_by_uid (
- group,
- source_uid);
- */
- e_source_group_remove_source (
- group,
- source);
- e_source_list_sync (source_list, NULL);
- if (!is_contacts_folder) {
- /* Remove from the selected folders */
- if (folder_type == EXCHANGE_CALENDAR_FOLDER) {
- ids = gconf_client_get_list (
- client,
- CONF_KEY_SELECTED_CAL_SOURCES,
- GCONF_VALUE_STRING, NULL);
- if (ids) {
- node_to_be_deleted = g_slist_find_custom (ids,
- source_uid,
- (GCompareFunc) strcmp);
- if (node_to_be_deleted) {
- g_free (node_to_be_deleted->data);
- ids = g_slist_delete_link (ids,
- node_to_be_deleted);
- }
- }
- temp_ids = ids;
- for (; temp_ids != NULL; temp_ids = g_slist_next (temp_ids))
- g_free (temp_ids->data);
- g_slist_free (ids);
- }
- else if (folder_type == EXCHANGE_TASKS_FOLDER) {
- ids = gconf_client_get_list (client,
- CONF_KEY_SELECTED_TASKS_SOURCES,
- GCONF_VALUE_STRING, NULL);
- if (ids) {
- node_to_be_deleted = g_slist_find_custom (ids,
- source_uid,
- (GCompareFunc) strcmp);
- if (node_to_be_deleted) {
- g_free (node_to_be_deleted->data);
- ids = g_slist_delete_link (ids,
- node_to_be_deleted);
- }
- }
- temp_ids = ids;
- for (; temp_ids != NULL; temp_ids = g_slist_next (temp_ids))
- g_free (temp_ids->data);
- g_slist_free (ids);
- }
- }
- found_group = TRUE;
- break;
- }
- g_free (read_uri);
- }
- }
- }
- g_object_unref (source_list);
- g_object_unref (client);
-}
-
-static gboolean
-is_offline (void)
-{
- GConfClient *client;
- GConfValue *value;
- gboolean offline = FALSE;
-
- client = gconf_client_get_default ();
- value = gconf_client_get (client,
- "/apps/evolution/shell/start_offline", NULL);
- if (value)
- offline = gconf_value_get_bool (value);
-
- g_object_unref (client);
- gconf_value_free (value);
- return offline;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __EXCHANGE_ESOURCE_H__
-#define __EXCHANGE_ESOURCE_H__
-
-#include "exchange-constants.h"
-#include "exchange-account.h"
-
-G_BEGIN_DECLS
-
-#define CONF_KEY_SELECTED_CAL_SOURCES "/apps/evolution/calendar/display/selected_calendars"
-#define CONF_KEY_SELECTED_TASKS_SOURCES "/apps/evolution/calendar/tasks/selected_tasks"
-#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://"
-
-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);
-
-G_END_DECLS
-
-#endif /* __EXCHANGE_ESOURCE_H__ */
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-
-/* Copyright (C) 2002-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* ExchangeFolderSize: Display the folder tree with the folder sizes */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include <gtk/gtk.h>
-
-#include "exchange-hierarchy-webdav.h"
-#include "e-folder-exchange.h"
-#include "exchange-folder-size.h"
-
-#define PARENT_TYPE G_TYPE_OBJECT
-static GObjectClass *parent_class = NULL;
-
-G_DEFINE_TYPE (ExchangeFolderSize, exchange_folder_size, G_TYPE_OBJECT)
-
-typedef struct {
- gchar *folder_name;
- gdouble folder_size;
-} folder_info;
-
-struct _ExchangeFolderSizePrivate {
-
- GHashTable *table;
- GtkListStore *model;
- GHashTable *row_refs;
-};
-
-enum {
- COLUMN_NAME,
- COLUMN_SIZE,
- NUM_COLUMNS
-};
-
-static gboolean
-free_fgsizeable (gpointer key, gpointer value, gpointer data)
-{
- folder_info *f_info = (folder_info *) value;
-
- g_free (key);
- g_free (f_info->folder_name);
- g_free (f_info);
- return TRUE;
-}
-
-static gboolean
-free_row_refs (gpointer key, gpointer value, gpointer user_data)
-{
- g_free (key);
- gtk_tree_row_reference_free (value);
- return TRUE;
-}
-
-static void
-finalize (GObject *object)
-{
- ExchangeFolderSize *fsize = EXCHANGE_FOLDER_SIZE (object);
-
- g_hash_table_foreach_remove (fsize->priv->table, free_fgsizeable, NULL);
- g_hash_table_destroy (fsize->priv->table);
- g_hash_table_foreach_remove (fsize->priv->row_refs, free_row_refs, NULL);
- g_hash_table_destroy (fsize->priv->row_refs);
- if (fsize->priv->model)
- g_object_unref (fsize->priv->model);
- g_free (fsize->priv);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-dispose (GObject *object)
-{
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-exchange_folder_size_class_init (ExchangeFolderSizeClass *class)
-{
- GObjectClass *object_class;
- parent_class = g_type_class_ref (PARENT_TYPE);
-
- object_class = G_OBJECT_CLASS (class);
-
- /* override virtual methods */
- object_class->dispose = dispose;
- object_class->finalize = finalize;
-
-}
-
-static void
-exchange_folder_size_init (ExchangeFolderSize *fsize)
-{
- fsize->priv = g_new0 (ExchangeFolderSizePrivate, 1);
- fsize->priv->table = g_hash_table_new (g_str_hash, g_str_equal);
- fsize->priv->model = gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING, G_TYPE_DOUBLE);
- fsize->priv->row_refs = g_hash_table_new (g_str_hash, g_str_equal);
-}
-
-/**
- * exchange_folder_size_new:
- *
- * Return value: a foldersize object with the table initialized
- **/
-ExchangeFolderSize *
-exchange_folder_size_new (void)
-{
- ExchangeFolderSize *fsize;
-
- fsize = g_object_new (EXCHANGE_TYPE_FOLDER_SIZE, NULL);
-
- return fsize;
-}
-
-void
-exchange_folder_size_update (ExchangeFolderSize *fsize,
- const gchar *folder_name,
- gdouble folder_size)
-{
- folder_info *f_info, *cached_info;
- ExchangeFolderSizePrivate *priv;
- GHashTable *folder_gsizeable;
- GtkTreeRowReference *row;
- GtkTreeIter iter;
- GtkTreePath *path;
-
- g_return_if_fail (EXCHANGE_IS_FOLDER_SIZE (fsize));
-
- priv = fsize->priv;
- folder_gsizeable = priv->table;
-
- cached_info = g_hash_table_lookup (folder_gsizeable, folder_name);
- if (cached_info) {
- if (cached_info->folder_size == folder_size) {
- return;
- } else {
- cached_info->folder_size = folder_size;
- row = g_hash_table_lookup (priv->row_refs, folder_name);
- path = gtk_tree_row_reference_get_path (row);
- if (gtk_tree_model_get_iter (GTK_TREE_MODEL (fsize->priv->model), &iter, path)) {
- gtk_list_store_set (fsize->priv->model, &iter,
- COLUMN_NAME, cached_info->folder_name,
- COLUMN_SIZE, cached_info->folder_size,
- -1);
- }
- gtk_tree_path_free (path);
- return;
- }
- } else {
- f_info = g_new0(folder_info, 1);
- f_info->folder_name = g_strdup (folder_name);
- f_info->folder_size = folder_size;
- g_hash_table_insert (folder_gsizeable, f_info->folder_name, f_info);
-
- gtk_list_store_append (fsize->priv->model, &iter);
- gtk_list_store_set (fsize->priv->model, &iter,
- COLUMN_NAME, f_info->folder_name,
- COLUMN_SIZE, f_info->folder_size,
- -1);
-
- path = gtk_tree_model_get_path (GTK_TREE_MODEL (fsize->priv->model), &iter);
- row = gtk_tree_row_reference_new (GTK_TREE_MODEL (fsize->priv->model), path);
- gtk_tree_path_free (path);
-
- g_hash_table_insert (fsize->priv->row_refs, g_strdup (folder_name), row);
- }
-}
-
-void
-exchange_folder_size_remove (ExchangeFolderSize *fsize,
- const gchar *folder_name)
-{
- ExchangeFolderSizePrivate *priv;
- GHashTable *folder_gsizeable;
- folder_info *cached_info;
- GtkTreeRowReference *row;
- GtkTreeIter iter;
- GtkTreePath *path;
-
- g_return_if_fail (EXCHANGE_IS_FOLDER_SIZE (fsize));
- g_return_if_fail (folder_name != NULL);
-
- priv = fsize->priv;
- folder_gsizeable = priv->table;
-
- cached_info = g_hash_table_lookup (folder_gsizeable, folder_name);
- if (cached_info) {
- row = g_hash_table_lookup (priv->row_refs, folder_name);
- path = gtk_tree_row_reference_get_path (row);
- g_hash_table_remove (folder_gsizeable, folder_name);
- if (gtk_tree_model_get_iter (GTK_TREE_MODEL (fsize->priv->model), &iter, path)) {
- gtk_list_store_remove (fsize->priv->model, &iter);
- }
- g_hash_table_remove (priv->row_refs, row);
- gtk_tree_path_free (path);
- }
-}
-
-gdouble
-exchange_folder_size_get (ExchangeFolderSize *fsize,
- const gchar *folder_name)
-{
- ExchangeFolderSizePrivate *priv;
- GHashTable *folder_gsizeable;
- folder_info *cached_info;
-
- g_return_val_if_fail (EXCHANGE_IS_FOLDER_SIZE (fsize), -1);
-
- priv = fsize->priv;
- folder_gsizeable = priv->table;
-
- cached_info = g_hash_table_lookup (folder_gsizeable, folder_name);
- if (cached_info) {
- return cached_info->folder_size;
- }
- return -1;
-}
-
-GtkListStore *
-exchange_folder_size_get_model (ExchangeFolderSize *fsize)
-{
- ExchangeFolderSizePrivate *priv;
-
- priv = fsize->priv;
-
- if (!g_hash_table_size (priv->table))
- return NULL;
-
- return priv->model;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2002-2004 Novell, Inc. */
-
-#ifndef __EXCHANGE_FOLDER_SIZE_H__
-#define __EXCHANGE_FOLDER_SIZE_H__
-
-#include "exchange-types.h"
-#include "e2k-security-descriptor.h"
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define EXCHANGE_TYPE_FOLDER_SIZE (exchange_folder_size_get_type ())
-#define EXCHANGE_FOLDER_SIZE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXCHANGE_TYPE_FOLDER_SIZE, ExchangeFolderSize))
-#define EXCHANGE_FOLDER_SIZE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EXCHANGE_TYPE_FOLDER_SIZE, ExchangeFolderSizeClass))
-#define EXCHANGE_IS_FOLDER_SIZE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXCHANGE_TYPE_FOLDER_SIZE))
-#define EXCHANGE_IS_FOLDER_SIZE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EXCHANGE_TYPE_FOLDER_SIZE))
-
-typedef struct _ExchangeFolderSize ExchangeFolderSize;
-typedef struct _ExchangeFolderSizePrivate ExchangeFolderSizePrivate;
-typedef struct _ExchangeFolderSizeClass ExchangeFolderSizeClass;
-
-struct _ExchangeFolderSize {
- GObject parent;
-
- ExchangeFolderSizePrivate *priv;
-};
-
-struct _ExchangeFolderSizeClass {
- GObjectClass parent_class;
-
-};
-
-GType exchange_folder_size_get_type (void);
-
-ExchangeFolderSize *exchange_folder_size_new (void);
-
-void exchange_folder_size_update (ExchangeFolderSize *fsize,
- const gchar *folder_name,
- gdouble folder_size);
-void exchange_folder_size_remove (ExchangeFolderSize *fsize, const gchar *folder_name);
-
-gdouble exchange_folder_size_get (ExchangeFolderSize *fsize, const gchar *folder_name);
-
-GtkListStore *exchange_folder_size_get_model (ExchangeFolderSize *fsize);
-
-G_END_DECLS
-
-#endif /* __EXCHANGE_FOLDER_SIZE_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2002-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* ExchangeHierarchyFavorites: class for the "Favorites" Public Folders
- * hierarchy (and favorites-handling code).
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "exchange-hierarchy-favorites.h"
-#include "exchange-account.h"
-#include "e-folder-exchange.h"
-#include "e2k-propnames.h"
-#include "e2k-uri.h"
-#include "e2k-utils.h"
-#include "exchange-esource.h"
-
-#include <libedataserver/e-source-list.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-struct _ExchangeHierarchyFavoritesPrivate {
- gchar *public_uri, *shortcuts_uri;
- GHashTable *shortcuts;
-};
-
-#define PARENT_TYPE EXCHANGE_TYPE_HIERARCHY_SOMEDAV
-static ExchangeHierarchySomeDAVClass *parent_class = NULL;
-
-static GPtrArray *get_hrefs (ExchangeHierarchySomeDAV *hsd);
-static ExchangeAccountFolderResult remove_folder (ExchangeHierarchy *hier,
- EFolder *folder);
-static void finalize (GObject *object);
-
-static void
-class_init (GObjectClass *object_class)
-{
- ExchangeHierarchySomeDAVClass *somedav_class =
- EXCHANGE_HIERARCHY_SOMEDAV_CLASS (object_class);
- ExchangeHierarchyClass *hier_class =
- EXCHANGE_HIERARCHY_CLASS (object_class);
-
- parent_class = g_type_class_ref (PARENT_TYPE);
-
- /* virtual method override */
- object_class->finalize = finalize;
- hier_class->remove_folder = remove_folder;
- somedav_class->get_hrefs = get_hrefs;
-}
-
-static void
-init (GObject *object)
-{
- ExchangeHierarchyFavorites *hfav = EXCHANGE_HIERARCHY_FAVORITES (object);
-
- hfav->priv = g_new0 (ExchangeHierarchyFavoritesPrivate, 1);
- hfav->priv->shortcuts = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_free);
-}
-
-static void
-finalize (GObject *object)
-{
- ExchangeHierarchyFavorites *hfav = EXCHANGE_HIERARCHY_FAVORITES (object);
-
- g_hash_table_destroy (hfav->priv->shortcuts);
- g_free (hfav->priv->public_uri);
- g_free (hfav->priv->shortcuts_uri);
- g_free (hfav->priv);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-E2K_MAKE_TYPE (exchange_hierarchy_favorites, ExchangeHierarchyFavorites, class_init, init, PARENT_TYPE)
-
-static void
-add_hrefs (ExchangeHierarchy *hier, EFolder *folder, gpointer hrefs)
-{
- g_ptr_array_add (hrefs, (gchar *)e2k_uri_path (e_folder_exchange_get_internal_uri (folder)));
-}
-
-static const gchar *shortcuts_props[] = {
- PR_FAV_DISPLAY_NAME, /* PR_DISPLAY_NAME of referent */
- PR_FAV_DISPLAY_ALIAS, /* if set, user-chosen display name */
- PR_FAV_PUBLIC_SOURCE_KEY, /* PR_SOURCE_KEY of referent */
- PR_FAV_PARENT_SOURCE_KEY, /* PR_FAV_PUBLIC_SOURCE_KEY of parent */
- PR_FAV_LEVEL_MASK /* depth in hierarchy (first level is 1) */
-};
-static const gint n_shortcuts_props = G_N_ELEMENTS (shortcuts_props);
-
-static GPtrArray *
-get_hrefs (ExchangeHierarchySomeDAV *hsd)
-{
- ExchangeHierarchy *hier = EXCHANGE_HIERARCHY (hsd);
- ExchangeHierarchyFavorites *hfav = EXCHANGE_HIERARCHY_FAVORITES (hsd);
- E2kContext *ctx = exchange_account_get_context (hier->account);
- GPtrArray *hrefs;
- E2kResultIter *iter;
- E2kResult *result, *results;
- E2kHTTPStatus status;
- GByteArray *source_key;
- const gchar *prop = E2K_PR_DAV_HREF, *shortcut_uri;
- gchar *perm_url, *folder_uri;
- gint i, nresults = 0, mode;
-
- hrefs = g_ptr_array_new ();
-
- exchange_account_is_offline (hier->account, &mode);
- if (mode != ONLINE_MODE) {
- exchange_hierarchy_webdav_offline_scan_subtree (EXCHANGE_HIERARCHY (hfav), add_hrefs, hrefs);
- return hrefs;
- }
- /* Scan the shortcut links and use PROPFIND to resolve the
- * permanent_urls. Unfortunately it doesn't seem to be possible
- * to BPROPFIND a group of permanent_urls.
- */
- iter = e2k_context_search_start (ctx, NULL, hfav->priv->shortcuts_uri,
- shortcuts_props, n_shortcuts_props,
- NULL, NULL, TRUE);
- while ((result = e2k_result_iter_next (iter))) {
- shortcut_uri = result->href;
- source_key = e2k_properties_get_prop (result->props, PR_FAV_PUBLIC_SOURCE_KEY);
- if (!source_key)
- continue;
-
- perm_url = e2k_entryid_to_permanenturl (source_key, hfav->priv->public_uri);
-
- status = e2k_context_propfind (ctx, NULL, perm_url,
- &prop, 1, &results, &nresults);
- if (E2K_HTTP_STATUS_IS_SUCCESSFUL (status) && nresults) {
- folder_uri = g_strdup (results[0].href);
- g_ptr_array_add (hrefs, folder_uri);
- g_hash_table_insert (hfav->priv->shortcuts,
- g_strdup (folder_uri),
- g_strdup (shortcut_uri));
- e2k_results_free (results, nresults);
- }
-
- g_free (perm_url);
- }
-
- status = e2k_result_iter_free (iter);
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
- /* FIXME: need to be able to return an error */
- for (i = 0; i < hrefs->len; i++)
- g_free (hrefs->pdata[i]);
- g_ptr_array_free (hrefs, TRUE);
- hrefs = NULL;
- }
-
- return hrefs;
-}
-/**
- * exchange_hierarchy_favorites_is_added:
- * @hier: the hierarchy
- * @folder: the Public Folder to check in the favorites tree
- *
- * Checks if @folder is present in the favorites hierarchy
- *
- * Return value: TRUE if @folder is already added as a favorite.
- **/
-
-gboolean
-exchange_hierarchy_favorites_is_added (ExchangeHierarchy *hier, EFolder *folder)
-{
- ExchangeHierarchyFavorites *hfav =
- EXCHANGE_HIERARCHY_FAVORITES (hier);
- const gchar *folder_uri, *shortcut_uri;
-
- folder_uri = e_folder_exchange_get_internal_uri (folder);
- shortcut_uri = g_hash_table_lookup (hfav->priv->shortcuts, folder_uri);
-
- return shortcut_uri ? TRUE : FALSE;
-}
-
-static ExchangeAccountFolderResult
-remove_folder (ExchangeHierarchy *hier, EFolder *folder)
-{
- ExchangeHierarchyFavorites *hfav =
- EXCHANGE_HIERARCHY_FAVORITES (hier);
- const gchar *folder_uri, *shortcut_uri;
- E2kHTTPStatus status;
- const gchar *folder_type, *physical_uri;
-
- folder_uri = e_folder_exchange_get_internal_uri (folder);
- shortcut_uri = g_hash_table_lookup (hfav->priv->shortcuts, folder_uri);
- if (!shortcut_uri)
- return EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
-
- status = e2k_context_delete (
- exchange_account_get_context (hier->account), NULL,
- shortcut_uri);
-
- if (E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
- g_hash_table_remove (hfav->priv->shortcuts, folder_uri);
- exchange_hierarchy_removed_folder (hier, folder);
-
- /* Temp Fix for remove fav folders. see #59168 */
- /* remove ESources */
- folder_type = e_folder_get_type_string (folder);
- physical_uri = e_folder_get_physical_uri (folder);
-
- if (strcmp (folder_type, "calendar") == 0) {
- remove_folder_esource (hier->account,
- EXCHANGE_CALENDAR_FOLDER,
- physical_uri);
- }
- else if (strcmp (folder_type, "tasks") == 0) {
- remove_folder_esource (hier->account,
- EXCHANGE_TASKS_FOLDER,
- physical_uri);
- }
- else if (strcmp (folder_type, "contacts") == 0) {
- remove_folder_esource (hier->account,
- EXCHANGE_CONTACTS_FOLDER,
- physical_uri);
- }
- }
-
- return exchange_hierarchy_webdav_status_to_folder_result (status);
-}
-
-/**
- * exchange_hierarchy_favorites_add_folder:
- * @hier: the hierarchy
- * @folder: the Public Folder to add to the favorites tree
- *
- * Adds a new folder to @hier.
- *
- * Return value: the folder result.
- **/
-ExchangeAccountFolderResult
-exchange_hierarchy_favorites_add_folder (ExchangeHierarchy *hier,
- EFolder *folder)
-{
- ExchangeHierarchyFavorites *hfav;
- E2kProperties *props;
- E2kHTTPStatus status;
- const gchar *folder_uri, *permanent_uri;
- gchar *shortcut_uri;
-
- g_return_val_if_fail (EXCHANGE_IS_HIERARCHY (hier), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
- g_return_val_if_fail (E_IS_FOLDER (folder), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
- g_return_val_if_fail (e_folder_exchange_get_hierarchy (folder)->type == EXCHANGE_HIERARCHY_PUBLIC, EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
-
- hfav = EXCHANGE_HIERARCHY_FAVORITES (hier);
- permanent_uri = e_folder_exchange_get_permanent_uri (folder);
-
- props = e2k_properties_new ();
- e2k_properties_set_string (props, PR_FAV_DISPLAY_NAME,
- g_strdup (e_folder_get_name (folder)));
- if (permanent_uri)
- e2k_properties_set_binary (props, PR_FAV_PUBLIC_SOURCE_KEY,
- e2k_permanenturl_to_entryid (permanent_uri));
- e2k_properties_set_int (props, PR_FAV_LEVEL_MASK, 1);
-
- status = e2k_context_proppatch_new (
- exchange_account_get_context (hier->account), NULL,
- hfav->priv->shortcuts_uri,
- e_folder_get_name (folder), NULL, NULL,
- props, &shortcut_uri, NULL);
- e2k_properties_free (props);
-
- if (E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
- folder_uri = e_folder_exchange_get_internal_uri (folder);
-
- g_hash_table_insert (hfav->priv->shortcuts,
- g_strdup (folder_uri), shortcut_uri);
- return exchange_hierarchy_somedav_add_folder (EXCHANGE_HIERARCHY_SOMEDAV (hier),
- folder_uri);
- } else
- return exchange_hierarchy_webdav_status_to_folder_result (status);
-}
-
-/**
- * exchange_hierarchy_favorites_new:
- * @account: an #ExchangeAccount
- * @hierarchy_name: the name of the hierarchy
- * @physical_uri_prefix: prefix for physical URIs in this hierarchy
- * @home_uri: the home URI of the owner's mailbox
- * @public_uri: the URI of the public folder tree
- * @owner_name: display name of the owner of the hierarchy
- * @owner_email: email address of the owner of the hierarchy
- * @source_uri: account source URI for folders in this hierarchy
- *
- * Creates a new Favorites hierarchy
- *
- * Return value: the new hierarchy.
- **/
-ExchangeHierarchy *
-exchange_hierarchy_favorites_new (ExchangeAccount *account,
- const gchar *hierarchy_name,
- const gchar *physical_uri_prefix,
- const gchar *home_uri,
- const gchar *public_uri,
- const gchar *owner_name,
- const gchar *owner_email,
- const gchar *source_uri)
-{
- ExchangeHierarchy *hier;
- ExchangeHierarchyFavorites *hfav;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- hier = g_object_new (EXCHANGE_TYPE_HIERARCHY_FAVORITES, NULL);
-
- hfav = (ExchangeHierarchyFavorites *)hier;
- hfav->priv->public_uri = g_strdup (public_uri);
- hfav->priv->shortcuts_uri = e2k_uri_concat (home_uri, "NON_IPM_SUBTREE/Shortcuts");
-
- exchange_hierarchy_webdav_construct (EXCHANGE_HIERARCHY_WEBDAV (hier),
- account,
- EXCHANGE_HIERARCHY_FAVORITES,
- hierarchy_name,
- physical_uri_prefix,
- public_uri,
- owner_name, owner_email,
- source_uri,
- TRUE);
- return hier;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __EXCHANGE_HIERARCHY_FAVORITES_H__
-#define __EXCHANGE_HIERARCHY_FAVORITES_H__
-
-#include "exchange-hierarchy-somedav.h"
-
-G_BEGIN_DECLS
-
-#define EXCHANGE_TYPE_HIERARCHY_FAVORITES (exchange_hierarchy_favorites_get_type ())
-#define EXCHANGE_HIERARCHY_FAVORITES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXCHANGE_TYPE_HIERARCHY_FAVORITES, ExchangeHierarchyFavorites))
-#define EXCHANGE_HIERARCHY_FAVORITES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EXCHANGE_TYPE_HIERARCHY_FAVORITES, ExchangeHierarchyFavoritesClass))
-#define EXCHANGE_IS_HIERARCHY_FAVORITES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXCHANGE_TYPE_HIERARCHY_FAVORITES))
-#define EXCHANGE_IS_HIERARCHY_FAVORITES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EXCHANGE_TYPE_HIERARCHY_FAVORITES))
-
-struct _ExchangeHierarchyFavorites {
- ExchangeHierarchySomeDAV parent;
-
- ExchangeHierarchyFavoritesPrivate *priv;
-};
-
-struct _ExchangeHierarchyFavoritesClass {
- ExchangeHierarchySomeDAVClass parent_class;
-
-};
-
-GType exchange_hierarchy_favorites_get_type (void);
-
-ExchangeHierarchy *exchange_hierarchy_favorites_new (ExchangeAccount *account,
- const gchar *hierarchy_name,
- const gchar *physical_uri_prefix,
- const gchar *home_uri,
- const gchar *public_uri,
- const gchar *owner_name,
- const gchar *owner_email,
- const gchar *source_uri);
-
-ExchangeAccountFolderResult exchange_hierarchy_favorites_add_folder (ExchangeHierarchy *hier,
- EFolder *folder);
-
-gboolean exchange_hierarchy_favorites_is_added (ExchangeHierarchy *hier,
- EFolder *folder);
-
-G_END_DECLS
-
-#endif /* __EXCHANGE_HIERARCHY_FAVORITES_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2002-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* ExchangeHierarchyForeign: class for a hierarchy consisting of a
- * selected subset of folders from another user's mailbox.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-
-#include "libedataserver/e-source-list.h"
-#include "libedataserver/e-xml-hash-utils.h"
-#include "libedataserver/e-xml-utils.h"
-
-#include "e-folder-exchange.h"
-#include "e2k-propnames.h"
-#include "e2k-types.h"
-#include "e2k-uri.h"
-#include "e2k-utils.h"
-#include "exchange-account.h"
-#include "exchange-esource.h"
-#include "exchange-hierarchy-foreign.h"
-#include "exchange-types.h"
-
-struct _ExchangeHierarchyForeignPrivate {
- GMutex *hide_private_lock;
- gboolean checked_hide_private;
-};
-
-extern const gchar *exchange_localfreebusy_path;
-
-#define PARENT_TYPE EXCHANGE_TYPE_HIERARCHY_SOMEDAV
-static ExchangeHierarchySomeDAVClass *parent_class = NULL;
-
-static GPtrArray *get_hrefs (ExchangeHierarchySomeDAV *hsd);
-static ExchangeAccountFolderResult create_folder (ExchangeHierarchy *hier,
- EFolder *parent,
- const gchar *name,
- const gchar *type);
-static ExchangeAccountFolderResult remove_folder (ExchangeHierarchy *hier,
- EFolder *folder);
-static ExchangeAccountFolderResult scan_subtree (ExchangeHierarchy *hier,
- EFolder *folder,
- gint mode);
-static void finalize (GObject *object);
-
-static void
-class_init (GObjectClass *object_class)
-{
- ExchangeHierarchyClass *hierarchy_class =
- EXCHANGE_HIERARCHY_CLASS (object_class);
- ExchangeHierarchySomeDAVClass *somedav_class =
- EXCHANGE_HIERARCHY_SOMEDAV_CLASS (object_class);
-
- parent_class = g_type_class_ref (PARENT_TYPE);
-
- /* virtual method override */
- object_class->finalize = finalize;
-
- hierarchy_class->create_folder = create_folder;
- hierarchy_class->remove_folder = remove_folder;
- hierarchy_class->scan_subtree = scan_subtree;
-
- somedav_class->get_hrefs = get_hrefs;
-}
-
-static void
-init (GObject *object)
-{
- ExchangeHierarchyForeign *hfor = EXCHANGE_HIERARCHY_FOREIGN (object);
- ExchangeHierarchy *hier = EXCHANGE_HIERARCHY (object);
-
- hfor->priv = g_new0 (ExchangeHierarchyForeignPrivate, 1);
- hfor->priv->hide_private_lock = g_mutex_new ();
- hier->hide_private_items = TRUE;
-}
-
-static void
-finalize (GObject *object)
-{
- ExchangeHierarchyForeign *hfor = EXCHANGE_HIERARCHY_FOREIGN (object);
-
- g_mutex_free (hfor->priv->hide_private_lock);
- g_free (hfor->priv);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-E2K_MAKE_TYPE (exchange_hierarchy_foreign, ExchangeHierarchyForeign, class_init, init, PARENT_TYPE)
-
-static const gchar *privacy_props[] = {
- PR_DELEGATES_ENTRYIDS,
- PR_DELEGATES_SEE_PRIVATE,
-};
-static const gint n_privacy_props = sizeof (privacy_props) / sizeof (privacy_props[0]);
-
-static void
-check_hide_private (ExchangeHierarchy *hier)
-{
- ExchangeHierarchyForeign *hfor = EXCHANGE_HIERARCHY_FOREIGN (hier);
- E2kContext *ctx;
- E2kHTTPStatus status;
- E2kResult *results;
- gint nresults = 0, i;
- GPtrArray *entryids, *privflags;
- GByteArray *entryid;
- const gchar *my_dn, *delegate_dn;
- gchar *uri;
-
- g_mutex_lock (hfor->priv->hide_private_lock);
-
- if (hfor->priv->checked_hide_private) {
- g_mutex_unlock (hfor->priv->hide_private_lock);
- return;
- }
-
- uri = e2k_uri_concat (hier->account->home_uri,
- "NON_IPM_SUBTREE/Freebusy%20Data/LocalFreebusy.EML");
- ctx = exchange_account_get_context (hier->account);
-
- status = e2k_context_propfind (ctx, NULL, uri,
- privacy_props, n_privacy_props,
- &results, &nresults);
- g_free (uri);
-
- hfor->priv->checked_hide_private = TRUE;
-
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status) || nresults == 0) {
- g_mutex_unlock (hfor->priv->hide_private_lock);
- return;
- }
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (results[0].status) ||
- !results[0].props || nresults > 1) {
- e2k_results_free (results, nresults);
- g_mutex_unlock (hfor->priv->hide_private_lock);
- return;
- }
-
- entryids = e2k_properties_get_prop (results[0].props,
- PR_DELEGATES_ENTRYIDS);
- privflags = e2k_properties_get_prop (results[0].props,
- PR_DELEGATES_SEE_PRIVATE);
- if (entryids && privflags) {
- my_dn = hier->account->legacy_exchange_dn;
- for (i = 0; i < entryids->len && i < privflags->len; i++) {
- entryid = entryids->pdata[i];
- delegate_dn = e2k_entryid_to_dn (entryid);
-
- if (delegate_dn &&
- !g_ascii_strcasecmp (delegate_dn, my_dn) &&
- privflags->pdata[i] &&
- atoi (privflags->pdata[i]))
- hier->hide_private_items = FALSE;
- break;
- }
- }
-
- e2k_results_free (results, nresults);
- g_mutex_unlock (hfor->priv->hide_private_lock);
-}
-
-static void
-remove_all_cb (ExchangeHierarchy *hier, EFolder *folder, gpointer user_data)
-{
- exchange_hierarchy_removed_folder (hier, folder);
-}
-
-static void
-hierarchy_foreign_cleanup (ExchangeHierarchy *hier)
-{
- gchar *mf_path;
-
- exchange_hierarchy_webdav_offline_scan_subtree (hier, remove_all_cb,
- NULL);
-
- mf_path = e_folder_exchange_get_storage_file (hier->toplevel, "hierarchy.xml");
- g_unlink (mf_path);
- g_free (mf_path);
-
- exchange_hierarchy_removed_folder (hier, hier->toplevel);
-}
-
-static const gchar *folder_props[] = {
- E2K_PR_EXCHANGE_FOLDER_CLASS,
- E2K_PR_HTTPMAIL_UNREAD_COUNT,
- E2K_PR_DAV_DISPLAY_NAME,
- PR_ACCESS
-};
-static const gint n_folder_props = sizeof (folder_props) / sizeof (folder_props[0]);
-
-static ExchangeAccountFolderResult
-find_folder (ExchangeHierarchy *hier, const gchar *uri, EFolder **folder_out)
-{
- ExchangeHierarchyWebDAV *hwd = EXCHANGE_HIERARCHY_WEBDAV (hier);
- E2kContext *ctx = exchange_account_get_context (hier->account);
- E2kHTTPStatus status;
- E2kResult *results;
- gint nresults = 0;
- EFolder *folder;
- const gchar *access;
-
- status = e2k_context_propfind (ctx, NULL, uri,
- folder_props, n_folder_props,
- &results, &nresults);
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status))
- return exchange_hierarchy_webdav_status_to_folder_result (status);
-
- if (nresults == 0)
- return EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
-
- access = e2k_properties_get_prop (results[0].props, PR_ACCESS);
- if (!access || !atoi (access)) {
- e2k_results_free (results, nresults);
- return EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED;
- }
-
- folder = exchange_hierarchy_webdav_parse_folder (hwd, hier->toplevel,
- &results[0]);
- e2k_results_free (results, nresults);
-
- if (!folder)
- return EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
-
- exchange_hierarchy_new_folder (hier, folder);
-
- if (folder_out)
- *folder_out = folder;
- else
- g_object_unref (folder);
- return EXCHANGE_ACCOUNT_FOLDER_OK;
-}
-
-static struct {
- const gchar *name, *prop;
-} std_folders[] = {
- { N_("Calendar"), E2K_PR_STD_FOLDER_CALENDAR },
- { N_("Contacts"), E2K_PR_STD_FOLDER_CONTACTS },
- { N_("Deleted Items"), E2K_PR_STD_FOLDER_DELETED_ITEMS },
- { N_("Drafts"), E2K_PR_STD_FOLDER_DRAFTS },
- { N_("Inbox"), E2K_PR_STD_FOLDER_INBOX },
- { N_("Journal"), E2K_PR_STD_FOLDER_JOURNAL },
- { N_("Notes"), E2K_PR_STD_FOLDER_NOTES },
- { N_("Outbox"), E2K_PR_STD_FOLDER_OUTBOX },
- { N_("Sent Items"), E2K_PR_STD_FOLDER_SENT_ITEMS },
- { N_("Tasks"), E2K_PR_STD_FOLDER_TASKS }
-};
-static ExchangeAccountFolderResult
-create_internal (ExchangeHierarchy *hier, EFolder *parent,
- const gchar *name, const gchar *type, EFolder **folder_out)
-{
- ExchangeAccountFolderResult result;
- gchar *literal_uri = NULL, *standard_uri = NULL;
- const gchar *home_uri;
- gint i;
-
- /* For now, no nesting */
- if (parent != hier->toplevel || strchr (name + 1, '/'))
- return EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR;
-
- check_hide_private (hier);
-
- home_uri = e_folder_exchange_get_internal_uri (hier->toplevel);
- literal_uri = e2k_uri_concat (home_uri, name);
- if (exchange_account_get_folder (hier->account, literal_uri)) {
- g_free (literal_uri);
- if (exchange_hierarchy_is_empty (hier))
- hierarchy_foreign_cleanup (hier);
- return EXCHANGE_ACCOUNT_FOLDER_ALREADY_EXISTS;
- }
-
- for (i = 0; i < G_N_ELEMENTS (std_folders); i++) {
- if (g_ascii_strcasecmp (std_folders[i].name, name) != 0 &&
- g_utf8_collate (_(std_folders[i].name), name) != 0)
- continue;
-
- standard_uri = exchange_account_get_standard_uri_for (
- hier->account, home_uri, std_folders[i].prop);
- if (!standard_uri)
- break;
- if (!strcmp (literal_uri, standard_uri)) {
- g_free (standard_uri);
- standard_uri = NULL;
- break;
- }
-
- if (exchange_account_get_folder (hier->account, standard_uri)) {
- g_free (standard_uri);
- g_free (literal_uri);
- if (exchange_hierarchy_is_empty (hier))
- hierarchy_foreign_cleanup (hier);
- return EXCHANGE_ACCOUNT_FOLDER_ALREADY_EXISTS;
- }
-
- break;
- }
-
- result = find_folder (hier, literal_uri, folder_out);
- if (result == EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST && standard_uri)
- result = find_folder (hier, standard_uri, folder_out);
-
- g_free (literal_uri);
- g_free (standard_uri);
-
- /* If the hierarchy is now empty, then we must have just been
- * created but then the add failed. So remove it again.
- */
- if (exchange_hierarchy_is_empty (hier))
- hierarchy_foreign_cleanup (hier);
-
- return result;
-}
-
-static ExchangeAccountFolderResult
-create_folder (ExchangeHierarchy *hier, EFolder *parent,
- const gchar *name, const gchar *type)
-{
- return create_internal (hier, parent, name, type, NULL);
-}
-
-static ExchangeAccountFolderResult
-remove_folder (ExchangeHierarchy *hier, EFolder *folder)
-{
- const gchar *folder_type, *physical_uri;
-
- /* Temp Fix for remove fav folders. see #59168 */
- /* remove ESources */
- folder_type = e_folder_get_type_string (folder);
- physical_uri = e_folder_get_physical_uri (folder);
-
- if (strcmp (folder_type, "calendar") == 0) {
- remove_folder_esource (hier->account,
- EXCHANGE_CALENDAR_FOLDER,
- physical_uri);
- }
- else if (strcmp (folder_type, "tasks") == 0) {
- remove_folder_esource (hier->account,
- EXCHANGE_TASKS_FOLDER,
- physical_uri);
- }
- else if (strcmp (folder_type, "contacts") == 0) {
- remove_folder_esource (hier->account,
- EXCHANGE_CONTACTS_FOLDER,
- physical_uri);
- }
- if (folder != hier->toplevel)
- exchange_hierarchy_removed_folder (hier, folder);
-
- if (folder == hier->toplevel || exchange_hierarchy_is_empty (hier))
- hierarchy_foreign_cleanup (hier);
-
- return EXCHANGE_ACCOUNT_FOLDER_OK;
-}
-
-static ExchangeAccountFolderResult
-scan_subtree (ExchangeHierarchy *hier, EFolder *folder, gint mode)
-{
- ExchangeAccountFolderResult folder_result;
-
- check_hide_private (hier);
-
- folder_result = EXCHANGE_HIERARCHY_CLASS (parent_class)->scan_subtree (hier, folder, mode);
-
- if (exchange_hierarchy_is_empty (hier))
- hierarchy_foreign_cleanup (hier);
-
- return folder_result;
-}
-
-static void
-add_href (ExchangeHierarchy *hier, EFolder *folder, gpointer hrefs)
-{
- gchar *uri = g_strdup (e_folder_exchange_get_internal_uri (folder));
-
- g_ptr_array_add (hrefs, (gpointer) uri);
-}
-
-static GPtrArray *
-get_hrefs (ExchangeHierarchySomeDAV *hsd)
-{
- GPtrArray *hrefs;
-
- hrefs = g_ptr_array_new ();
- exchange_hierarchy_webdav_offline_scan_subtree (EXCHANGE_HIERARCHY (hsd), add_href, hrefs);
- return hrefs;
-}
-
-/**
- * exchange_hierarchy_foreign_add_folder:
- * @hier: the hierarchy
- * @folder_name: the name of the folder to add
- * @folder: on successful return, the created folder
- *
- * Adds a new folder to @hier.
- *
- * Return value: the folder result.
- **/
-ExchangeAccountFolderResult
-exchange_hierarchy_foreign_add_folder (ExchangeHierarchy *hier,
- const gchar *folder_name,
- EFolder **folder)
-{
- ExchangeAccountFolderResult result;
- const gchar *folder_type = NULL;
- const gchar *physical_uri = NULL;
- gchar *new_folder_name;
- guint folder_mask = 0;
-
- result = create_internal (hier, hier->toplevel, folder_name, NULL, folder);
- if (result == EXCHANGE_ACCOUNT_FOLDER_OK) {
- /* Add the esources */
- folder_type = e_folder_get_type_string (*folder);
- physical_uri = e_folder_get_physical_uri (*folder);
- new_folder_name = g_strdup_printf("%s's %s",
- hier->owner_name, folder_name);
-
- if (!(strcmp (folder_type, "calendar")) ||
- !(strcmp (folder_type, "calendar/public"))) {
- folder_mask = EXCHANGE_CALENDAR_FOLDER | FORIEGN_FOLDER_FLAG;
- add_folder_esource (hier->account,
- folder_mask,
- new_folder_name,
- physical_uri);
- }
- else if (!(strcmp (folder_type, "tasks")) ||
- !(strcmp (folder_type, "tasks/public"))) {
- folder_mask = EXCHANGE_TASKS_FOLDER | FORIEGN_FOLDER_FLAG;
- add_folder_esource (hier->account,
- folder_mask,
- new_folder_name,
- physical_uri);
- }
- else if (!(strcmp (folder_type, "contacts")) ||
- !(strcmp (folder_type, "contacts/public")) ||
- !(strcmp (folder_type, "contacts/ldap"))) {
- folder_mask = EXCHANGE_CONTACTS_FOLDER | FORIEGN_FOLDER_FLAG;
- add_folder_esource (hier->account,
- folder_mask,
- new_folder_name,
- physical_uri);
- }
- g_free (new_folder_name);
- }
- return result;
-}
-
-static ExchangeHierarchy *
-hierarchy_foreign_new (ExchangeAccount *account,
- const gchar *hierarchy_name,
- const gchar *physical_uri_prefix,
- const gchar *internal_uri_prefix,
- const gchar *owner_name,
- const gchar *owner_email,
- const gchar *source_uri)
-{
- ExchangeHierarchyForeign *hfor;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- hfor = g_object_new (EXCHANGE_TYPE_HIERARCHY_FOREIGN, NULL);
-
- exchange_hierarchy_webdav_construct (EXCHANGE_HIERARCHY_WEBDAV (hfor),
- account,
- EXCHANGE_HIERARCHY_FOREIGN,
- hierarchy_name,
- physical_uri_prefix,
- internal_uri_prefix,
- owner_name, owner_email,
- source_uri,
- FALSE);
-
- return EXCHANGE_HIERARCHY (hfor);
-}
-
-/**
- * exchange_hierarchy_foreign_new:
- * @account: an #ExchangeAccount
- * @hierarchy_name: the name of the hierarchy
- * @physical_uri_prefix: the prefix of physical URIs in this hierarchy
- * @internal_uri_prefix: the prefix of internal (http) URIs in this hierarchy
- * @owner_name: display name of the owner of the hierarchy
- * @owner_email: email address of the owner of the hierarchy
- * @source_uri: evolution-mail source uri for the hierarchy
- *
- * Creates a new (initially empty) hierarchy for another user's
- * folders.
- *
- * Return value: the new hierarchy.
- **/
-ExchangeHierarchy *
-exchange_hierarchy_foreign_new (ExchangeAccount *account,
- const gchar *hierarchy_name,
- const gchar *physical_uri_prefix,
- const gchar *internal_uri_prefix,
- const gchar *owner_name,
- const gchar *owner_email,
- const gchar *source_uri)
-{
- ExchangeHierarchy *hier;
- gchar *mf_path;
- GHashTable *props;
- xmlDoc *doc;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- hier = hierarchy_foreign_new (account, hierarchy_name,
- physical_uri_prefix,
- internal_uri_prefix,
- owner_name, owner_email,
- source_uri);
-
- props = g_hash_table_new (g_str_hash, g_str_equal);
- g_hash_table_insert (props, (gpointer) "name", (gchar *)hierarchy_name);
- g_hash_table_insert (props, (gpointer) "physical_uri_prefix",
- (gchar *)physical_uri_prefix);
- g_hash_table_insert (props, (gpointer) "internal_uri_prefix",
- (gchar *)internal_uri_prefix);
- g_hash_table_insert (props, (gpointer) "owner_name", (gchar *)owner_name);
- g_hash_table_insert (props, (gpointer) "owner_email", (gchar *)owner_email);
- g_hash_table_insert (props, (gpointer) "source_uri", (gchar *)source_uri);
-
- mf_path = e_folder_exchange_get_storage_file (hier->toplevel, "hierarchy.xml");
- doc = e_xml_from_hash (props, E_XML_HASH_TYPE_PROPERTY,
- "foreign-hierarchy");
- e_xml_save_file (mf_path, doc);
- g_hash_table_destroy (props);
- g_free (mf_path);
- xmlFreeDoc (doc);
-
- return hier;
-}
-
-/**
- * exchange_hierarchy_foreign_new_from_dir:
- * @account: an #ExchangeAccount
- * @folder_path: pathname to a directory containing a hierarchy.xml file
- *
- * Recreates a new hierarchy from saved values.
- *
- * Return value: the new hierarchy.
- **/
-ExchangeHierarchy *
-exchange_hierarchy_foreign_new_from_dir (ExchangeAccount *account,
- const gchar *folder_path)
-{
- ExchangeHierarchy *hier;
- gchar *mf_path;
- GHashTable *props;
- xmlDoc *doc;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
- g_return_val_if_fail (folder_path != NULL, NULL);
-
- mf_path = g_build_filename (folder_path, "hierarchy.xml", NULL);
-
- doc = e_xml_parse_file (mf_path);
- g_free (mf_path);
-
- if (!doc)
- return NULL;
-
- props = e_xml_to_hash (doc, E_XML_HASH_TYPE_PROPERTY);
- xmlFreeDoc (doc);
-
- hier = hierarchy_foreign_new (account,
- g_hash_table_lookup (props, "name"),
- g_hash_table_lookup (props, "physical_uri_prefix"),
- g_hash_table_lookup (props, "internal_uri_prefix"),
- g_hash_table_lookup (props, "owner_name"),
- g_hash_table_lookup (props, "owner_email"),
- g_hash_table_lookup (props, "source_uri"));
-
- e_xml_destroy_hash (props);
- return hier;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __EXCHANGE_HIERARCHY_FOREIGN_H__
-#define __EXCHANGE_HIERARCHY_FOREIGN_H__
-
-#include "exchange-hierarchy-somedav.h"
-
-G_BEGIN_DECLS
-
-#define EXCHANGE_TYPE_HIERARCHY_FOREIGN (exchange_hierarchy_foreign_get_type ())
-#define EXCHANGE_HIERARCHY_FOREIGN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXCHANGE_TYPE_HIERARCHY_FOREIGN, ExchangeHierarchyForeign))
-#define EXCHANGE_HIERARCHY_FOREIGN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EXCHANGE_TYPE_HIERARCHY_FOREIGN, ExchangeHierarchyForeignClass))
-#define EXCHANGE_IS_HIERARCHY_FOREIGN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXCHANGE_TYPE_HIERARCHY_FOREIGN))
-#define EXCHANGE_IS_HIERARCHY_FOREIGN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EXCHANGE_TYPE_HIERARCHY_FOREIGN))
-
-typedef struct _ExchangeHierarchyForeignPrivate ExchangeHierarchyForeignPrivate;
-
-struct _ExchangeHierarchyForeign {
- ExchangeHierarchySomeDAV parent;
-
- ExchangeHierarchyForeignPrivate *priv;
-};
-
-struct _ExchangeHierarchyForeignClass {
- ExchangeHierarchySomeDAVClass parent_class;
-
-};
-
-typedef struct _ExchangeHierarchyForeignClass ExchangeHierarchyForeignClass;
-typedef struct _ExchangeHierarchyForeign ExchangeHierarchyForeign;
-
-GType exchange_hierarchy_foreign_get_type (void);
-
-ExchangeHierarchy *exchange_hierarchy_foreign_new (ExchangeAccount *account,
- const gchar *hierarchy_name,
- const gchar *physical_uri_prefix,
- const gchar *internal_uri_prefix,
- const gchar *owner_name,
- const gchar *owner_email,
- const gchar *source_uri);
-ExchangeHierarchy *exchange_hierarchy_foreign_new_from_dir (ExchangeAccount *account,
- const gchar *folder_path);
-
-ExchangeAccountFolderResult exchange_hierarchy_foreign_add_folder (ExchangeHierarchy *hier,
- const gchar *folder_name,
- EFolder **folder);
-
-G_END_DECLS
-
-#endif /* __EXCHANGE_HIERARCHY_FOREIGN_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2002-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* ExchangeHierarchyGAL: class for the Global Address List hierarchy
- * of an Exchange storage. (Currently the "hierarchy" only contains
- * a single folder, but see bugzilla #21029.)
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "exchange-hierarchy-gal.h"
-#include "exchange-account.h"
-#include "e-folder-exchange.h"
-#include "exchange-esource.h"
-
-#include <libedataserver/e-source-list.h>
-
-#define PARENT_TYPE EXCHANGE_TYPE_HIERARCHY
-
-E2K_MAKE_TYPE (exchange_hierarchy_gal, ExchangeHierarchyGAL, NULL, NULL, PARENT_TYPE)
-
-ExchangeHierarchy *
-exchange_hierarchy_gal_new (ExchangeAccount *account,
- const gchar *hierarchy_name,
- const gchar *physical_uri_prefix)
-{
- ExchangeHierarchy *hier;
- EFolder *toplevel;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
- g_return_val_if_fail (hierarchy_name != NULL, NULL);
- g_return_val_if_fail (physical_uri_prefix != NULL, NULL);
-
- hier = g_object_new (EXCHANGE_TYPE_HIERARCHY_GAL, NULL);
-
- toplevel = e_folder_exchange_new (hier, hierarchy_name,
- "contacts/ldap", NULL,
- physical_uri_prefix,
- physical_uri_prefix);
- exchange_hierarchy_construct (hier, account,
- EXCHANGE_HIERARCHY_GAL, toplevel,
- NULL, NULL, NULL);
- /* Add ESource */
- add_folder_esource (hier->account, EXCHANGE_CONTACTS_FOLDER,
- hierarchy_name, physical_uri_prefix);
-
- g_object_unref (toplevel);
-
- return hier;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __EXCHANGE_HIERARCHY_GAL_H__
-#define __EXCHANGE_HIERARCHY_GAL_H__
-
-#include "exchange-hierarchy.h"
-
-G_BEGIN_DECLS
-
-#define EXCHANGE_TYPE_HIERARCHY_GAL (exchange_hierarchy_gal_get_type ())
-#define EXCHANGE_HIERARCHY_GAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXCHANGE_TYPE_HIERARCHY_GAL, ExchangeHierarchyGAL))
-#define EXCHANGE_HIERARCHY_GAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EXCHANGE_TYPE_HIERARCHY_GAL, ExchangeHierarchyGALClass))
-#define EXCHANGE_IS_HIERARCHY_GAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXCHANGE_TYPE_HIERARCHY_GAL))
-#define EXCHANGE_IS_HIERARCHY_GAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EXCHANGE_TYPE_HIERARCHY_GAL))
-
-struct _ExchangeHierarchyGAL {
- ExchangeHierarchy parent;
-
-};
-
-struct _ExchangeHierarchyGALClass {
- ExchangeHierarchyClass parent_class;
-
-};
-
-GType exchange_hierarchy_gal_get_type (void);
-
-ExchangeHierarchy *exchange_hierarchy_gal_new (ExchangeAccount *account,
- const gchar *hierarchy_name,
- const gchar *physical_uri_prefix);
-
-G_END_DECLS
-
-#endif /* __EXCHANGE_HIERARCHY_GAL_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2002-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* ExchangeHierarchySomeDAV: class for a hierarchy consisting of a
- * specific group of WebDAV folders
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "exchange-hierarchy-somedav.h"
-#include "exchange-account.h"
-#include "e-folder-exchange.h"
-#include "e2k-propnames.h"
-#include "e2k-uri.h"
-#include "e2k-utils.h"
-
-#include <libedataserver/e-xml-hash-utils.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-struct _ExchangeHierarchySomeDAVPrivate {
- gboolean scanned;
-};
-
-enum {
- HREF_UNREADABLE,
- LAST_SIGNAL
-};
-
-static guint signals [LAST_SIGNAL] = { 0 };
-
-#define PARENT_TYPE EXCHANGE_TYPE_HIERARCHY_WEBDAV
-static ExchangeHierarchyWebDAVClass *parent_class = NULL;
-
-static ExchangeAccountFolderResult scan_subtree (ExchangeHierarchy *hier,
- EFolder *folder,
- gint mode);
-static void finalize (GObject *object);
-
-static void
-class_init (GObjectClass *object_class)
-{
- ExchangeHierarchyClass *exchange_hierarchy_class =
- EXCHANGE_HIERARCHY_CLASS (object_class);
-
- parent_class = g_type_class_ref (PARENT_TYPE);
-
- /* virtual method override */
- object_class->finalize = finalize;
-
- exchange_hierarchy_class->scan_subtree = scan_subtree;
-
- /* signals */
- signals[HREF_UNREADABLE] =
- g_signal_new ("href_unreadable",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ExchangeHierarchySomeDAVClass, href_unreadable),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1,
- G_TYPE_STRING);
-}
-
-static void
-init (GObject *object)
-{
- ExchangeHierarchySomeDAV *hsd = EXCHANGE_HIERARCHY_SOMEDAV (object);
-
- hsd->priv = g_new0 (ExchangeHierarchySomeDAVPrivate, 1);
-}
-
-static void
-finalize (GObject *object)
-{
- ExchangeHierarchySomeDAV *hsd = EXCHANGE_HIERARCHY_SOMEDAV (object);
-
- g_free (hsd->priv);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-E2K_MAKE_TYPE (exchange_hierarchy_somedav, ExchangeHierarchySomeDAV, class_init, init, PARENT_TYPE)
-
-static inline gboolean
-folder_is_unreadable (E2kProperties *props)
-{
- gchar *access;
-
- access = e2k_properties_get_prop (props, PR_ACCESS);
- return !access || !atoi (access);
-}
-
-static const gchar *folder_props[] = {
- E2K_PR_EXCHANGE_FOLDER_CLASS,
- E2K_PR_HTTPMAIL_UNREAD_COUNT,
- E2K_PR_DAV_DISPLAY_NAME,
- PR_ACCESS
-};
-static const gint n_folder_props = sizeof (folder_props) / sizeof (folder_props[0]);
-
-static ExchangeAccountFolderResult
-scan_subtree (ExchangeHierarchy *hier, EFolder *folder, gint mode)
-{
- ExchangeHierarchySomeDAV *hsd = EXCHANGE_HIERARCHY_SOMEDAV (hier);
- GPtrArray *hrefs;
- E2kResultIter *iter;
- E2kResult *result;
- gint folders_returned=0, folders_added=0, i;
- E2kHTTPStatus status;
- ExchangeAccountFolderResult folder_result;
- EFolder *iter_folder = NULL;
-
- /* FIXME : Temporarily allow a rescan of the hierarchy. The proper fix
- is to handle the folder list either in ExchangeAccount or in the
- plugins/exchange backend separately by listening to signals.
- if (hsd->priv->scanned || folder != hier->toplevel) */
- if (folder != hier->toplevel)
- return EXCHANGE_ACCOUNT_FOLDER_OK;
- hsd->priv->scanned = TRUE;
-
- if (mode == OFFLINE_MODE)
- return EXCHANGE_ACCOUNT_FOLDER_OK;
-
- hrefs = exchange_hierarchy_somedav_get_hrefs (hsd);
- if (!hrefs)
- return EXCHANGE_ACCOUNT_FOLDER_OK;
- if (!hrefs->len) {
- g_ptr_array_free (hrefs, TRUE);
- return EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
- }
-
- iter = e_folder_exchange_bpropfind_start (hier->toplevel, NULL,
- (const gchar **)hrefs->pdata,
- hrefs->len,
- folder_props,
- n_folder_props);
-
- while ((result = e2k_result_iter_next (iter))) {
- folders_returned++;
-
- /* If you have "folder visible" permission but nothing
- * else, you'll be able to fetch properties, but not
- * see anything in the folder. In that case, PR_ACCESS
- * will be 0, and we ignore the folder.
- */
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (result->status) ||
- folder_is_unreadable (result->props)) {
- exchange_hierarchy_somedav_href_unreadable (hsd, result->href);
- continue;
- }
-
- folders_added++;
- iter_folder = exchange_hierarchy_webdav_parse_folder (
- EXCHANGE_HIERARCHY_WEBDAV (hier),
- hier->toplevel, result);
- exchange_hierarchy_new_folder (hier, iter_folder);
- g_object_unref (iter_folder);
- }
- status = e2k_result_iter_free (iter);
-
- if (folders_returned == 0)
- folder_result = EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
- else if (folders_added == 0)
- folder_result = EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED;
- else
- folder_result = exchange_hierarchy_webdav_status_to_folder_result (status);
-
- for (i = 0; i < hrefs->len; i++)
- g_free (hrefs->pdata[i]);
- g_ptr_array_free (hrefs, TRUE);
-
- return folder_result;
-}
-
-GPtrArray *
-exchange_hierarchy_somedav_get_hrefs (ExchangeHierarchySomeDAV *hsd)
-{
- g_return_val_if_fail (EXCHANGE_IS_HIERARCHY_SOMEDAV (hsd), NULL);
-
- return EXCHANGE_GET_HIERARCHY_SOMEDAV_CLASS (hsd)->get_hrefs (hsd);
-}
-
-void
-exchange_hierarchy_somedav_href_unreadable (ExchangeHierarchySomeDAV *hsd,
- const gchar *href)
-{
- g_return_if_fail (EXCHANGE_IS_HIERARCHY_SOMEDAV (hsd));
- g_return_if_fail (href != NULL);
-
- g_signal_emit (hsd, signals[HREF_UNREADABLE], 0, href);
-}
-
-ExchangeAccountFolderResult
-exchange_hierarchy_somedav_add_folder (ExchangeHierarchySomeDAV *hsd,
- const gchar *uri)
-{
- ExchangeHierarchyWebDAV *hwd;
- ExchangeHierarchy *hier;
- E2kContext *ctx;
- E2kHTTPStatus status;
- E2kResult *results;
- gint nresults = 0;
- EFolder *folder;
-
- g_return_val_if_fail (EXCHANGE_IS_HIERARCHY_SOMEDAV (hsd),
- EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
- g_return_val_if_fail (uri != NULL,
- EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
-
- hwd = EXCHANGE_HIERARCHY_WEBDAV (hsd);
- hier = EXCHANGE_HIERARCHY (hsd);
- ctx = exchange_account_get_context (hier->account);
-
- status = e2k_context_propfind (ctx, NULL, uri,
- folder_props, n_folder_props,
- &results, &nresults);
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status))
- return exchange_hierarchy_webdav_status_to_folder_result (status);
-
- if (nresults == 0)
- return EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
-
- if (folder_is_unreadable (results[0].props)) {
- e2k_results_free (results, nresults);
- return EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED;
- }
-
- folder = exchange_hierarchy_webdav_parse_folder (hwd, hier->toplevel,
- &results[0]);
- e2k_results_free (results, nresults);
-
- if (!folder)
- return EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
-
- exchange_hierarchy_new_folder (hier, folder);
- g_object_unref (folder);
- return EXCHANGE_ACCOUNT_FOLDER_OK;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __EXCHANGE_HIERARCHY_SOMEDAV_H__
-#define __EXCHANGE_HIERARCHY_SOMEDAV_H__
-
-#include "exchange-hierarchy-webdav.h"
-
-G_BEGIN_DECLS
-
-#define EXCHANGE_TYPE_HIERARCHY_SOMEDAV (exchange_hierarchy_somedav_get_type ())
-#define EXCHANGE_HIERARCHY_SOMEDAV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXCHANGE_TYPE_HIERARCHY_SOMEDAV, ExchangeHierarchySomeDAV))
-#define EXCHANGE_HIERARCHY_SOMEDAV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EXCHANGE_TYPE_HIERARCHY_SOMEDAV, ExchangeHierarchySomeDAVClass))
-#define EXCHANGE_IS_HIERARCHY_SOMEDAV(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXCHANGE_TYPE_HIERARCHY_SOMEDAV))
-#define EXCHANGE_IS_HIERARCHY_SOMEDAV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EXCHANGE_TYPE_HIERARCHY_SOMEDAV))
-#define EXCHANGE_GET_HIERARCHY_SOMEDAV_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EXCHANGE_TYPE_HIERARCHY_SOMEDAV, ExchangeHierarchySomeDAVClass))
-
-struct _ExchangeHierarchySomeDAV {
- ExchangeHierarchyWebDAV parent;
-
- ExchangeHierarchySomeDAVPrivate *priv;
-};
-
-struct _ExchangeHierarchySomeDAVClass {
- ExchangeHierarchyWebDAVClass parent_class;
-
- /* signals */
- void (*href_unreadable) (ExchangeHierarchySomeDAV *hsd, const gchar *href);
-
- /* methods */
- GPtrArray *(*get_hrefs) (ExchangeHierarchySomeDAV *hsd);
-};
-
-GType exchange_hierarchy_somedav_get_type (void);
-
-GPtrArray *exchange_hierarchy_somedav_get_hrefs (ExchangeHierarchySomeDAV *hsd);
-ExchangeAccountFolderResult exchange_hierarchy_somedav_add_folder (ExchangeHierarchySomeDAV *hsd,
- const gchar *uri);
-
-/* signal emitter */
-void exchange_hierarchy_somedav_href_unreadable (ExchangeHierarchySomeDAV *hsd,
- const gchar *href);
-
-G_END_DECLS
-
-#endif /* __EXCHANGE_HIERARCHY_SOMEDAV_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2002-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* ExchangeHierarchyWebDAV: class for a normal WebDAV folder hierarchy
- * in the Exchange storage. Eg, the "Personal Folders" and "Public
- * Folders" hierarchies.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-
-#include "libedataserverui/e-passwords.h"
-#include "libedataserver/e-source-list.h"
-
-#include "exchange-hierarchy-webdav.h"
-#include "exchange-account.h"
-#include "e-folder-exchange.h"
-#include "e2k-context.h"
-#include "e2k-path.h"
-#include "e2k-propnames.h"
-#include "e2k-restriction.h"
-#include "e2k-uri.h"
-#include "e2k-utils.h"
-#include "exchange-folder-size.h"
-#include "exchange-esource.h"
-
-#define d(x)
-
-#define URI_ENCODE_CHARS "@;:/?=."
-
-struct _ExchangeHierarchyWebDAVPrivate {
- GHashTable *folders_by_internal_path;
- gboolean deep_searchable;
- gchar *trash_path;
- gdouble total_folder_size;
-};
-
-#define PARENT_TYPE EXCHANGE_TYPE_HIERARCHY
-static ExchangeHierarchyClass *parent_class = NULL;
-
-static void folder_type_map_init (void);
-
-static void dispose (GObject *object);
-static void finalize (GObject *object);
-static gboolean is_empty (ExchangeHierarchy *hier);
-static void rescan (ExchangeHierarchy *hier);
-static ExchangeAccountFolderResult scan_subtree (ExchangeHierarchy *hier,
- EFolder *folder,
- gint mode);
-static ExchangeAccountFolderResult create_folder (ExchangeHierarchy *hier,
- EFolder *parent,
- const gchar *name,
- const gchar *type);
-static ExchangeAccountFolderResult remove_folder (ExchangeHierarchy *hier,
- EFolder *folder);
-static ExchangeAccountFolderResult xfer_folder (ExchangeHierarchy *hier,
- EFolder *source,
- EFolder *dest_parent,
- const gchar *dest_name,
- gboolean remove_source);
-
-static void hierarchy_new_folder (ExchangeHierarchy *hier, EFolder *folder,
- gpointer user_data);
-static void hierarchy_removed_folder (ExchangeHierarchy *hier, EFolder *folder,
- gpointer user_data);
-
-static void
-class_init (GObjectClass *object_class)
-{
- ExchangeHierarchyClass *exchange_hierarchy_class =
- EXCHANGE_HIERARCHY_CLASS (object_class);
-
- folder_type_map_init ();
-
- parent_class = g_type_class_ref (PARENT_TYPE);
-
- /* virtual method override */
- object_class->dispose = dispose;
- object_class->finalize = finalize;
-
- exchange_hierarchy_class->is_empty = is_empty;
- exchange_hierarchy_class->rescan = rescan;
- exchange_hierarchy_class->scan_subtree = scan_subtree;
- exchange_hierarchy_class->create_folder = create_folder;
- exchange_hierarchy_class->remove_folder = remove_folder;
- exchange_hierarchy_class->xfer_folder = xfer_folder;
-}
-
-static void
-init (GObject *object)
-{
- ExchangeHierarchyWebDAV *hwd = EXCHANGE_HIERARCHY_WEBDAV (object);
-
- hwd->priv = g_new0 (ExchangeHierarchyWebDAVPrivate, 1);
- hwd->priv->folders_by_internal_path = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_object_unref);
- hwd->priv->total_folder_size = 0;
-
- g_signal_connect (object, "new_folder",
- G_CALLBACK (hierarchy_new_folder), NULL);
- g_signal_connect (object, "removed_folder",
- G_CALLBACK (hierarchy_removed_folder), NULL);
-}
-
-static void
-dispose (GObject *object)
-{
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-finalize (GObject *object)
-{
- ExchangeHierarchyWebDAV *hwd = EXCHANGE_HIERARCHY_WEBDAV (object);
-
- g_hash_table_destroy (hwd->priv->folders_by_internal_path);
- g_free (hwd->priv->trash_path);
- g_free (hwd->priv);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-E2K_MAKE_TYPE (exchange_hierarchy_webdav, ExchangeHierarchyWebDAV, class_init, init, PARENT_TYPE)
-
-typedef struct {
- const gchar *contentclass, *component;
- gboolean offline_supported;
-} ExchangeFolderType;
-
-static ExchangeFolderType folder_types[] = {
- { "IPF.Note", "mail", FALSE },
- { "IPF.Contact", "contacts", FALSE },
- { "IPF.Appointment", "calendar", FALSE },
- { "IPF.Task", "tasks", FALSE },
- { NULL, NULL }
-};
-static GHashTable *folder_type_map;
-
-static void
-folder_type_map_init (void)
-{
- gint i;
-
- folder_type_map = g_hash_table_new (g_str_hash, g_str_equal);
- for (i = 0; folder_types[i].contentclass; i++) {
- g_hash_table_insert (folder_type_map,
- (gpointer) folder_types[i].contentclass,
- &folder_types[i]);
- }
-}
-
-/* We maintain the folders_by_internal_path hash table by listening
- * to our own signal emissions. (This lets ExchangeHierarchyForeign
- * remove its folders by just calling exchange_hierarchy_removed_folder.)
- */
-static void
-hierarchy_new_folder (ExchangeHierarchy *hier, EFolder *folder,
- gpointer user_data)
-{
- const gchar *internal_uri;
- gchar *mf_path;
-
- g_return_if_fail (E_IS_FOLDER (folder));
- internal_uri = e_folder_exchange_get_internal_uri (folder);
-
- /* This should ideally not be needed. But, this causes a problem when the
- server has identical folder names [ internal_uri ] for folders. Very much
- possible in the case of favorite folders */
- if (g_hash_table_lookup (EXCHANGE_HIERARCHY_WEBDAV (hier)->priv->folders_by_internal_path,
- (gchar *)e2k_uri_path (internal_uri)))
- return;
-
- g_hash_table_insert (EXCHANGE_HIERARCHY_WEBDAV (hier)->priv->folders_by_internal_path,
- (gchar *)e2k_uri_path (internal_uri), g_object_ref (folder));
-
- mf_path = e_folder_exchange_get_storage_file (folder, "connector-metadata.xml");
- e_folder_exchange_save_to_file (folder, mf_path);
- g_free (mf_path);
-}
-
-static void
-hierarchy_removed_folder (ExchangeHierarchy *hier, EFolder *folder,
- gpointer user_data)
-{
- const gchar *internal_uri = e_folder_exchange_get_internal_uri (folder);
- gchar *mf_path;
-
- g_hash_table_remove (EXCHANGE_HIERARCHY_WEBDAV (hier)->priv->folders_by_internal_path,
- (gchar *)e2k_uri_path (internal_uri));
-
- mf_path = e_folder_exchange_get_storage_file (folder, "connector-metadata.xml");
- g_unlink (mf_path);
- g_free (mf_path);
-
- e_path_rmdir (hier->account->storage_dir,
- e_folder_exchange_get_path (folder));
-}
-
-static gboolean
-is_empty (ExchangeHierarchy *hier)
-{
- ExchangeHierarchyWebDAV *hwd = EXCHANGE_HIERARCHY_WEBDAV (hier);
-
- /* 1, not 0, because there will always be an entry for toplevel */
- return g_hash_table_size (hwd->priv->folders_by_internal_path) == 1;
-}
-
-static EFolder *
-e_folder_webdav_new (ExchangeHierarchy *hier, const gchar *internal_uri,
- EFolder *parent, const gchar *name, const gchar *type,
- const gchar *outlook_class, gint unread,
- gboolean offline_supported)
-{
- EFolder *folder;
- gchar *real_type, *http_uri, *physical_uri, *fixed_name = NULL;
-
- d( g_print ("exchange-hierarchy-webdave.c:e_folder_webdave_new: internal_uri=[%s], name=[%s], type=[%s], class=[%s]\n",
- internal_uri, name, type, outlook_class));
-
- if (hier->type == EXCHANGE_HIERARCHY_PUBLIC &&
- !strstr (type, "/public"))
- real_type = g_strdup_printf ("%s/public", type);
- else if (hier->type == EXCHANGE_HIERARCHY_FOREIGN &&
- !strcmp (type, "calendar"))
- real_type = g_strdup ("calendar/public"); /* Hack */
- else
- real_type = g_strdup (type);
-
- fixed_name = e2k_uri_encode (name, FALSE, URI_ENCODE_CHARS);
- physical_uri = e2k_uri_concat (e_folder_get_physical_uri (parent), fixed_name);
- g_free (fixed_name);
-
- if (internal_uri) {
- folder = e_folder_exchange_new (hier, name,
- real_type, outlook_class,
- physical_uri, internal_uri);
- } else {
- gchar *temp_name;
- gchar *encoded_name = NULL;
- const gchar *new_internal_uri;
- gint len;
-
- len = strlen (name);
-
- /* appending "/" here, so that hash table lookup in rescan() succeeds */
- if (name[len-1] != '/') {
- encoded_name = e2k_uri_encode (name, FALSE, URI_ENCODE_CHARS);
- } else {
- temp_name = g_strndup (name, len-1);
- encoded_name = e2k_uri_encode (temp_name, FALSE, URI_ENCODE_CHARS);
- g_free (temp_name);
- }
- temp_name = g_strdup_printf ("%s/", encoded_name);
- g_free (encoded_name);
-
- new_internal_uri = e_folder_exchange_get_internal_uri (parent);
- http_uri = e2k_uri_concat (new_internal_uri, temp_name);
- d(g_print ("exchange-hierarchy-webdave.c:e_folder_webdave_new: http_uri=[%s], new_internal_uri=[%s], temp_name=[%s], name[%s]\n",
- http_uri, new_internal_uri, temp_name, name));
- g_free (temp_name);
-
- folder = e_folder_exchange_new (hier, name,
- real_type, outlook_class,
- physical_uri, http_uri);
- g_free (http_uri);
- }
- g_free (physical_uri);
- g_free (real_type);
-
- if (unread && hier->type != EXCHANGE_HIERARCHY_PUBLIC)
- e_folder_set_unread_count (folder, unread);
- if (offline_supported)
- e_folder_set_can_sync_offline (folder, offline_supported);
-
- /* FIXME: set is_stock */
-
- return folder;
-}
-
-static ExchangeAccountFolderResult
-create_folder (ExchangeHierarchy *hier, EFolder *parent,
- const gchar *name, const gchar *type)
-{
- EFolder *dest;
- E2kProperties *props;
- E2kHTTPStatus status;
- gchar *permanent_url = NULL;
- gint i, mode;
-
- exchange_account_is_offline (hier->account, &mode);
- if (mode != ONLINE_MODE)
- return EXCHANGE_ACCOUNT_FOLDER_OFFLINE;
-
- for (i = 0; folder_types[i].component; i++) {
- if (!strcmp (folder_types[i].component, type))
- break;
- }
- if (!folder_types[i].component)
- return EXCHANGE_ACCOUNT_FOLDER_UNKNOWN_TYPE;
-
- dest = e_folder_webdav_new (hier, NULL, parent, name, type,
- folder_types[i].contentclass, 0,
- folder_types[i].offline_supported);
-
- props = e2k_properties_new ();
- e2k_properties_set_string (props, E2K_PR_EXCHANGE_FOLDER_CLASS,
- g_strdup (folder_types[i].contentclass));
-
- status = e_folder_exchange_mkcol (dest, NULL, props,
- &permanent_url);
- e2k_properties_free (props);
-
- if (E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
- e_folder_exchange_set_permanent_uri (dest, permanent_url);
- g_free (permanent_url);
- exchange_hierarchy_new_folder (hier, dest);
- g_object_unref (dest);
-
- /* update the folder size table, new folder, initialize the size to 0 */
- exchange_account_folder_size_add (hier->account, name, 0);
- return EXCHANGE_ACCOUNT_FOLDER_OK;
- }
-
- g_object_unref (dest);
- if (status == E2K_HTTP_METHOD_NOT_ALLOWED)
- return EXCHANGE_ACCOUNT_FOLDER_ALREADY_EXISTS;
- else if (status == E2K_HTTP_CONFLICT)
- return EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
- else if (status == E2K_HTTP_FORBIDDEN)
- return EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED;
- else
- return EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR;
-}
-
-static ExchangeAccountFolderResult
-remove_folder (ExchangeHierarchy *hier, EFolder *folder)
-{
- E2kHTTPStatus status;
- gint mode;
-
- exchange_account_is_offline (hier->account, &mode);
-
- if (mode != ONLINE_MODE)
- return EXCHANGE_ACCOUNT_FOLDER_OFFLINE;
-
- if (folder == hier->toplevel)
- return EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED;
-
- status = e_folder_exchange_delete (folder, NULL);
- if (E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
- exchange_hierarchy_removed_folder (hier, folder);
-
- /* update the folder size info */
- exchange_account_folder_size_remove (hier->account,
- e_folder_get_name(folder));
- return EXCHANGE_ACCOUNT_FOLDER_OK;
- } else
- return EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR;
-}
-
-static ExchangeAccountFolderResult
-xfer_folder (ExchangeHierarchy *hier, EFolder *source,
- EFolder *dest_parent, const gchar *dest_name,
- gboolean remove_source)
-{
- E2kHTTPStatus status;
- EFolder *dest;
- gchar *permanent_url = NULL, *physical_uri, *source_parent;
- const gchar *folder_type = NULL, *source_folder_name;
- ExchangeAccountFolderResult ret_code;
- gint mode;
-
- exchange_account_is_offline (hier->account, &mode);
- if (mode != ONLINE_MODE)
- return EXCHANGE_ACCOUNT_FOLDER_OFFLINE;
-
- if (source == hier->toplevel)
- return EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR;
-
- dest = e_folder_webdav_new (hier, NULL, dest_parent, dest_name,
- e_folder_get_type_string (source),
- e_folder_exchange_get_outlook_class (source),
- e_folder_get_unread_count (source),
- e_folder_get_can_sync_offline (source));
-
- status = e_folder_exchange_transfer_dir (source, NULL, dest,
- remove_source,
- &permanent_url);
-
- if (E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
- folder_type = e_folder_get_type_string (source);
- if (permanent_url)
- e_folder_exchange_set_permanent_uri (dest, permanent_url);
- if (remove_source)
- exchange_hierarchy_removed_folder (hier, source);
- exchange_hierarchy_new_folder (hier, dest);
- scan_subtree (hier, dest, mode);
- physical_uri = g_strdup (e_folder_get_physical_uri (source));
- ret_code = EXCHANGE_ACCOUNT_FOLDER_OK;
-
- /* Find if folder movement or rename.
- * update folder size in case of rename.
- */
-
- source_folder_name = strrchr (physical_uri, '/') + 1;
- source_parent = g_strndup (physical_uri,
- source_folder_name - physical_uri);
- if (!strcmp (e_folder_get_physical_uri (dest_parent), source_parent)) {
- /* rename - remove folder entry from hash, and
- * update the hash table with new name
- */
- exchange_account_folder_size_rename (hier->account,
- source_folder_name+1, dest_name);
- }
- g_free (source_parent);
- } else {
- physical_uri = e2k_uri_concat (
- e_folder_get_physical_uri (dest_parent),
- dest_name);
- g_object_unref (dest);
- if (status == E2K_HTTP_FORBIDDEN ||
- status == E2K_HTTP_UNAUTHORIZED)
- ret_code = EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED;
- else
- ret_code = EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR;
- }
-
- /* Remove the ESource of the source folder, in case of rename/move */
- if ((hier->type == EXCHANGE_HIERARCHY_PERSONAL ||
- hier->type == EXCHANGE_HIERARCHY_FAVORITES) && remove_source &&
- ret_code == EXCHANGE_ACCOUNT_FOLDER_OK) {
-
- if ((strcmp (folder_type, "calendar") == 0) ||
- (strcmp (folder_type, "calendar/public") == 0)) {
- remove_folder_esource (hier->account,
- EXCHANGE_CALENDAR_FOLDER,
- physical_uri);
- }
- else if ((strcmp (folder_type, "tasks") == 0) ||
- (strcmp (folder_type, "tasks/public") == 0)) {
- remove_folder_esource (hier->account,
- EXCHANGE_TASKS_FOLDER,
- physical_uri);
- }
- else if ((strcmp (folder_type, "contacts") == 0) ||
- (strcmp (folder_type, "contacts/public") == 0)) {
- remove_folder_esource (hier->account,
- EXCHANGE_CONTACTS_FOLDER,
- physical_uri);
- }
- }
- if (physical_uri)
- g_free (physical_uri);
- return ret_code;
-}
-
-static void
-add_href (gpointer path, gpointer folder, gpointer hrefs)
-{
- const gchar *folder_type;
-
- folder_type = e_folder_get_type_string (folder);
-
- if (!folder_type)
- return;
-
- if (!strcmp (folder_type, "noselect"))
- return;
-
- g_ptr_array_add (hrefs, path);
-}
-
-/* E2K_PR_EXCHANGE_FOLDER_SIZE also can be used for reading folder size */
-static const gchar *rescan_props[] = {
- E2K_PR_EXCHANGE_FOLDER_SIZE,
- E2K_PR_HTTPMAIL_UNREAD_COUNT
-};
-static const gint n_rescan_props = sizeof (rescan_props) / sizeof (rescan_props[0]);
-
-static void
-rescan (ExchangeHierarchy *hier)
-{
- ExchangeHierarchyWebDAV *hwd = EXCHANGE_HIERARCHY_WEBDAV (hier);
- const gchar *prop = E2K_PR_HTTPMAIL_UNREAD_COUNT;
- const gchar *folder_size, *folder_name;
- GPtrArray *hrefs;
- E2kResultIter *iter;
- E2kResult *result;
- EFolder *folder;
- gint unread, mode;
- gboolean personal = ( hier->type == EXCHANGE_HIERARCHY_PERSONAL );
- gdouble fsize_d;
-
- exchange_account_is_offline (hier->account, &mode);
- if ( (mode != ONLINE_MODE) ||
- hier->type == EXCHANGE_HIERARCHY_PUBLIC)
- return;
-
- hrefs = g_ptr_array_new ();
- g_hash_table_foreach (hwd->priv->folders_by_internal_path,
- add_href, hrefs);
- if (!hrefs->len) {
- g_ptr_array_free (hrefs, TRUE);
- return;
- }
-
- g_object_ref (hier);
- iter = e_folder_exchange_bpropfind_start (hier->toplevel, NULL,
- (const gchar **)hrefs->pdata,
- hrefs->len,
- rescan_props, n_rescan_props);
- g_ptr_array_free (hrefs, TRUE);
-
- while ((result = e2k_result_iter_next (iter))) {
- folder = g_hash_table_lookup (hwd->priv->folders_by_internal_path,
- e2k_uri_path (result->href));
- if (!folder)
- continue;
-
- prop = e2k_properties_get_prop (result->props,
- E2K_PR_HTTPMAIL_UNREAD_COUNT);
- if (!prop)
- continue;
- unread = atoi (prop);
-
- if (unread != e_folder_get_unread_count (folder))
- e_folder_set_unread_count (folder, unread);
-
- folder_size = e2k_properties_get_prop (result->props,
- E2K_PR_EXCHANGE_FOLDER_SIZE);
-
- if (folder_size) {
- folder_name = e_folder_get_name (folder);
- fsize_d = g_ascii_strtod (folder_size, NULL)/1024;
- exchange_account_folder_size_add (hier->account,
- folder_name, fsize_d);
- if (personal)
- hwd->priv->total_folder_size =
- hwd->priv->total_folder_size + fsize_d;
- }
- }
- e2k_result_iter_free (iter);
- g_object_unref (hier);
-}
-
-ExchangeAccountFolderResult
-exchange_hierarchy_webdav_status_to_folder_result (E2kHTTPStatus status)
-{
- if (E2K_HTTP_STATUS_IS_SUCCESSFUL (status))
- return EXCHANGE_ACCOUNT_FOLDER_OK;
- else if (status == E2K_HTTP_NOT_FOUND)
- return EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
- else if (status == E2K_HTTP_UNAUTHORIZED)
- return EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED;
- else
- return EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR;
-}
-
-gdouble
-exchange_hierarchy_webdav_get_total_folder_size (ExchangeHierarchyWebDAV *hwd)
-{
- g_return_val_if_fail (EXCHANGE_IS_HIERARCHY_WEBDAV (hwd), -1);
-
- return hwd->priv->total_folder_size;
-}
-
-EFolder *
-exchange_hierarchy_webdav_parse_folder (ExchangeHierarchyWebDAV *hwd,
- EFolder *parent,
- E2kResult *result)
-{
- EFolder *folder;
- ExchangeFolderType *folder_type;
- const gchar *name, *prop, *outlook_class, *permanenturl;
- gint unread;
- gboolean hassubs;
-
- g_return_val_if_fail (EXCHANGE_IS_HIERARCHY_WEBDAV (hwd), NULL);
- g_return_val_if_fail (E_IS_FOLDER (parent), NULL);
-
- /* It's possible to have a localized inbox folder named, eg,
- * "Innboks", with children whose URIs go through "Inbox"
- * instead. (See bugzilla 27065.) This is probably related to
- * the IMAP "INBOX" convention. Anyway, the important bit is
- * that you can't know a folder's parent URI just by looking
- * at its own URI. Since we only ever scan one folder at a
- * time here, we just keep track of what the parent was. If we
- * were going to read multiple folders at once, we could deal
- * with this by fetching DAV:parentname.
- */
-
- name = e2k_properties_get_prop (result->props,
- E2K_PR_DAV_DISPLAY_NAME);
- if (!name)
- return NULL;
-
- prop = e2k_properties_get_prop (result->props,
- E2K_PR_HTTPMAIL_UNREAD_COUNT);
- unread = prop ? atoi (prop) : 0;
- prop = e2k_properties_get_prop (result->props,
- E2K_PR_DAV_HAS_SUBS);
- hassubs = prop && atoi (prop);
-
- outlook_class = e2k_properties_get_prop (result->props,
- E2K_PR_EXCHANGE_FOLDER_CLASS);
- folder_type = NULL;
- if (outlook_class)
- folder_type = g_hash_table_lookup (folder_type_map, outlook_class);
- if (!folder_type)
- folder_type = &folder_types[0]; /* mail */
- if (!outlook_class)
- outlook_class = folder_type->contentclass;
-
- /*
- * The permanenturl Field provides a unique identifier for an item
- * across the *store* and will not change as long as the item remains
- * in the same folder. The permanenturl Field contains the ID of the
- * parent folder of the item, which changes when the item is moved to a
- * different folder or deleted. Changing a field on an item will not
- * change the permanenturl Field and neither will adding more items to
- * the folder with the same display name or message subject.
- */
- permanenturl = e2k_properties_get_prop (result->props,
- E2K_PR_EXCHANGE_PERMANENTURL);
- /* Check for errors */
-
- folder = e_folder_webdav_new (EXCHANGE_HIERARCHY (hwd),
- result->href, parent,
- name, folder_type->component,
- outlook_class, unread,
- folder_type->offline_supported);
- if (hwd->priv->trash_path && !strcmp (e2k_uri_path (result->href), hwd->priv->trash_path))
- e_folder_set_custom_icon (folder, "stock_delete");
- if (hassubs)
- e_folder_exchange_set_has_subfolders (folder, TRUE);
- if (permanenturl) {
- /* Favorite folders and subscribed folders will not have
- * permanenturl
- */
- e_folder_exchange_set_permanent_uri (folder, permanenturl);
- }
-
- return folder;
-}
-
-static void
-add_folders (ExchangeHierarchy *hier, EFolder *folder, gpointer folders)
-{
- g_object_ref (folder);
- g_ptr_array_add (folders, folder);
-}
-
-static const gchar *folder_props[] = {
- E2K_PR_EXCHANGE_FOLDER_CLASS,
- E2K_PR_HTTPMAIL_UNREAD_COUNT,
- E2K_PR_DAV_DISPLAY_NAME,
- E2K_PR_EXCHANGE_PERMANENTURL,
- E2K_PR_EXCHANGE_FOLDER_SIZE,
- E2K_PR_DAV_HAS_SUBS
-};
-static const gint n_folder_props = sizeof (folder_props) / sizeof (folder_props[0]);
-
-static const gchar *pub_folder_props[] = {
- E2K_PR_EXCHANGE_FOLDER_CLASS,
- E2K_PR_DAV_DISPLAY_NAME,
- E2K_PR_EXCHANGE_PERMANENTURL,
- E2K_PR_DAV_HAS_SUBS
-};
-static const gint n_pub_folder_props = sizeof (pub_folder_props) / sizeof (pub_folder_props[0]);
-
-static ExchangeAccountFolderResult
-scan_subtree (ExchangeHierarchy *hier, EFolder *parent, gint mode)
-{
- static E2kRestriction *folders_rn;
- ExchangeHierarchyWebDAV *hwd = EXCHANGE_HIERARCHY_WEBDAV (hier);
- GSList *subtrees = NULL;
- E2kResultIter *iter;
- E2kResult *result;
- E2kHTTPStatus status;
- EFolder *folder, *tmp;
- GPtrArray *folders;
- gint i;
- gdouble fsize_d;
- const gchar *name, *folder_size, *deleted_items_uri, *int_uri;
- gboolean personal = ( EXCHANGE_HIERARCHY (hwd)->type == EXCHANGE_HIERARCHY_PERSONAL );
-
- if (parent) {
- if (!e_folder_exchange_get_rescan_tree (parent)) {
- d(g_print ("%s(%d):%s: Donot RESCAN [%s] \n", __FILE__, __LINE__, __PRETTY_FUNCTION__,
- e_folder_get_name (parent)));
- return EXCHANGE_ACCOUNT_FOLDER_OK;
- }
- }
-
- if (mode == OFFLINE_MODE) {
- folders = g_ptr_array_new ();
- exchange_hierarchy_webdav_offline_scan_subtree (EXCHANGE_HIERARCHY (hier), add_folders, folders);
- for (i = 0; i <folders->len; i++) {
- tmp = (EFolder *)folders->pdata[i];
- exchange_hierarchy_new_folder (hier, (EFolder *)folders->pdata[i]);
- }
- return EXCHANGE_ACCOUNT_FOLDER_OK;
- }
-
- if (!folders_rn) {
- folders_rn =
- e2k_restriction_andv (
- e2k_restriction_prop_bool (E2K_PR_DAV_IS_COLLECTION,
- E2K_RELOP_EQ, TRUE),
- e2k_restriction_prop_bool (E2K_PR_DAV_IS_HIDDEN,
- E2K_RELOP_EQ, FALSE),
- NULL);
- }
-
- if (hier->type == EXCHANGE_HIERARCHY_PUBLIC)
- iter = e_folder_exchange_search_start (parent, NULL,
- pub_folder_props,
- n_pub_folder_props,
- folders_rn, NULL, TRUE);
- else
- iter = e_folder_exchange_search_start (parent, NULL,
- folder_props, n_folder_props,
- folders_rn, NULL, TRUE);
-
- while ((result = e2k_result_iter_next (iter))) {
- folder = exchange_hierarchy_webdav_parse_folder (hwd, parent, result);
- if (!folder)
- continue;
-
- if (hwd->priv->deep_searchable &&
- e_folder_exchange_get_has_subfolders (folder)) {
- e_folder_exchange_set_has_subfolders (folder, FALSE);
- subtrees = g_slist_prepend (subtrees, g_object_ref (folder));
- }
- exchange_hierarchy_new_folder (hier, folder);
- g_object_unref (folder);
-
- /* Check the folder size here */
- if (hier->type != EXCHANGE_HIERARCHY_PUBLIC) {
- name = e2k_properties_get_prop (result->props,
- E2K_PR_DAV_DISPLAY_NAME);
- folder_size = e2k_properties_get_prop (result->props,
- E2K_PR_EXCHANGE_FOLDER_SIZE);
-
- /* FIXME : Find a better way of doing this */
- fsize_d = g_ascii_strtod (folder_size, NULL)/1024;
- exchange_account_folder_size_add (hier->account, name, fsize_d);
- }
-
- if (personal) {
- /* calculate mail box size only for personal folders */
- hwd->priv->total_folder_size =
- hwd->priv->total_folder_size + fsize_d;
- }
-
- }
-
- status = e2k_result_iter_free (iter);
-
- deleted_items_uri = exchange_account_get_standard_uri (hier->account, "deleteditems");
-
- while (subtrees) {
- folder = subtrees->data;
- subtrees = g_slist_remove (subtrees, folder);
-
- /* Dont scan the subtree for deleteditems folder */
- int_uri = e_folder_exchange_get_internal_uri (folder);
- if (int_uri && deleted_items_uri && !strcmp (int_uri, deleted_items_uri)) {
- g_object_unref (folder);
- continue;
- }
-
- scan_subtree (hier, folder, mode);
- g_object_unref (folder);
- }
-
- e_folder_exchange_set_rescan_tree (parent, FALSE);
-
- return exchange_hierarchy_webdav_status_to_folder_result (status);
-}
-
-struct scan_offline_data {
- ExchangeHierarchy *hier;
- ExchangeHierarchyWebDAVScanCallback callback;
- gpointer user_data;
- GPtrArray *badpaths;
-};
-
-static gboolean
-scan_offline_cb (const gchar *physical_path, const gchar *path, gpointer data)
-{
- struct scan_offline_data *sod = data;
- EFolder *folder;
- gchar *mf_name;
-
- mf_name = g_build_filename (physical_path, "connector-metadata.xml", NULL);
- folder = e_folder_exchange_new_from_file (sod->hier, mf_name);
- if (!folder) {
- g_unlink (mf_name);
- g_free (mf_name);
- if (!sod->badpaths)
- sod->badpaths = g_ptr_array_new ();
- g_ptr_array_add (sod->badpaths, g_strdup (path));
- return TRUE;
- }
- g_free (mf_name);
-
- sod->callback (sod->hier, folder, sod->user_data);
- g_object_unref (folder);
-
- return TRUE;
-}
-
-/**
- * exchange_hierarchy_webdav_offline_scan_subtree:
- * @hier: a (webdav) hierarchy
- * @callbackb: a callback
- * @user_data: data for @cb
- *
- * Scans the offline folder tree cache for @hier and calls @cb
- * with each folder successfully constructed from offline data
- **/
-void
-exchange_hierarchy_webdav_offline_scan_subtree (ExchangeHierarchy *hier,
- ExchangeHierarchyWebDAVScanCallback callback,
- gpointer user_data)
-{
- struct scan_offline_data sod;
- const gchar *path;
- gchar *dir, *prefix;
- gint i;
-
- g_return_if_fail (EXCHANGE_IS_HIERARCHY (hier));
-
- sod.hier = hier;
- sod.callback = callback;
- sod.user_data = user_data;
- sod.badpaths = NULL;
-
- path = e_folder_exchange_get_path (hier->toplevel);
- prefix = e2k_strdup_with_trailing_slash (path);
- dir = e_path_to_physical (hier->account->storage_dir, prefix);
- g_free (prefix);
- e_path_find_folders (dir, scan_offline_cb, &sod);
-
- if (sod.badpaths) {
- for (i = 0; i < sod.badpaths->len; i++) {
- e_path_rmdir (dir, sod.badpaths->pdata[i]);
- g_free (sod.badpaths->pdata[i]);
- }
- g_ptr_array_free (sod.badpaths, TRUE);
- }
-
- g_free (dir);
-}
-
-void
-exchange_hierarchy_webdav_construct (ExchangeHierarchyWebDAV *hwd,
- ExchangeAccount *account,
- ExchangeHierarchyType type,
- const gchar *hierarchy_name,
- const gchar *physical_uri_prefix,
- const gchar *internal_uri_prefix,
- const gchar *owner_name,
- const gchar *owner_email,
- const gchar *source_uri,
- gboolean deep_searchable)
-{
- EFolder *toplevel;
-
- g_return_if_fail (EXCHANGE_IS_HIERARCHY_WEBDAV (hwd));
- g_return_if_fail (EXCHANGE_IS_ACCOUNT (account));
-
- hwd->priv->deep_searchable = deep_searchable;
-
- toplevel = e_folder_exchange_new (EXCHANGE_HIERARCHY (hwd),
- hierarchy_name,
- "noselect", NULL,
- physical_uri_prefix,
- internal_uri_prefix);
- e_folder_set_custom_icon (toplevel, "stock_folder");
- e_folder_exchange_set_has_subfolders (toplevel, TRUE);
- exchange_hierarchy_construct (EXCHANGE_HIERARCHY (hwd),
- account, type, toplevel,
- owner_name, owner_email, source_uri);
- g_object_unref (toplevel);
-
- if (type == EXCHANGE_HIERARCHY_PERSONAL) {
- const gchar *trash_uri;
-
- trash_uri = exchange_account_get_standard_uri (account, "deleteditems");
- if (trash_uri)
- hwd->priv->trash_path = e2k_strdup_with_trailing_slash (e2k_uri_path (trash_uri));
- }
-}
-
-ExchangeHierarchy *
-exchange_hierarchy_webdav_new (ExchangeAccount *account,
- ExchangeHierarchyType type,
- const gchar *hierarchy_name,
- const gchar *physical_uri_prefix,
- const gchar *internal_uri_prefix,
- const gchar *owner_name,
- const gchar *owner_email,
- const gchar *source_uri,
- gboolean deep_searchable)
-{
- ExchangeHierarchy *hier;
-
- g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
-
- hier = g_object_new (EXCHANGE_TYPE_HIERARCHY_WEBDAV, NULL);
-
- exchange_hierarchy_webdav_construct (EXCHANGE_HIERARCHY_WEBDAV (hier),
- account, type, hierarchy_name,
- physical_uri_prefix,
- internal_uri_prefix,
- owner_name, owner_email,
- source_uri, deep_searchable);
- return hier;
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright 2001-2004 Novell, Inc. */
-
-#ifndef __EXCHANGE_HIERARCHY_WEBDAV_H__
-#define __EXCHANGE_HIERARCHY_WEBDAV_H__
-
-#include "exchange-hierarchy.h"
-/* #include "exchange-folder-size.h" */
-
-G_BEGIN_DECLS
-
-#define EXCHANGE_TYPE_HIERARCHY_WEBDAV (exchange_hierarchy_webdav_get_type ())
-#define EXCHANGE_HIERARCHY_WEBDAV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXCHANGE_TYPE_HIERARCHY_WEBDAV, ExchangeHierarchyWebDAV))
-#define EXCHANGE_HIERARCHY_WEBDAV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EXCHANGE_TYPE_HIERARCHY_WEBDAV, ExchangeHierarchyWebDAVClass))
-#define EXCHANGE_IS_HIERARCHY_WEBDAV(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXCHANGE_TYPE_HIERARCHY_WEBDAV))
-#define EXCHANGE_IS_HIERARCHY_WEBDAV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EXCHANGE_TYPE_HIERARCHY_WEBDAV))
-
-struct _ExchangeHierarchyWebDAV {
- ExchangeHierarchy parent;
-
- ExchangeHierarchyWebDAVPrivate *priv;
-};
-
-struct _ExchangeHierarchyWebDAVClass {
- ExchangeHierarchyClass parent_class;
-
-};
-
-GType exchange_hierarchy_webdav_get_type (void);
-
-ExchangeHierarchy *exchange_hierarchy_webdav_new (ExchangeAccount *account,
- ExchangeHierarchyType type,
- const gchar *hierarchy_name,
- const gchar *physical_uri_prefix,
- const gchar *internal_uri_prefix,
- const gchar *owner_name,
- const gchar *owner_email,
- const gchar *source_uri,
- gboolean deep_searchable);
-
-/* for subclasses */
-ExchangeAccountFolderResult exchange_hierarchy_webdav_status_to_folder_result (E2kHTTPStatus status);
-EFolder *exchange_hierarchy_webdav_parse_folder (ExchangeHierarchyWebDAV *hwd,
- EFolder *parent,
- E2kResult *result);
-
-void exchange_hierarchy_webdav_construct (ExchangeHierarchyWebDAV *hwd,
- ExchangeAccount *account,
- ExchangeHierarchyType type,
- const gchar *hierarchy_name,
- const gchar *physical_uri_prefix,
- const gchar *internal_uri_prefix,
- const gchar *owner_name,
- const gchar *owner_email,
- const gchar *source_uri,
- gboolean deep_searchable);
-
-typedef void (*ExchangeHierarchyWebDAVScanCallback) (ExchangeHierarchy *hier,
- EFolder *folder,
- gpointer user_data);
-void exchange_hierarchy_webdav_offline_scan_subtree (ExchangeHierarchy *hier,
- ExchangeHierarchyWebDAVScanCallback cb,
- gpointer user_data);
-
-gdouble exchange_hierarchy_webdav_get_total_folder_size (ExchangeHierarchyWebDAV *hwd);
-
-G_END_DECLS
-
-#endif /* __EXCHANGE_HIERARCHY_WEBDAV_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2002-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* ExchangeHierarchy: abstract class for a hierarchy of folders
- * in an Exchange storage. Subclasses of ExchangeHierarchy implement
- * normal WebDAV hierarchies, the GAL hierarchy, and hierarchies
- * of individually-selected other users' folders.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "exchange-hierarchy.h"
-#include "e-folder-exchange.h"
-
-enum {
- NEW_FOLDER,
- REMOVED_FOLDER,
- LAST_SIGNAL
-};
-
-static guint signals [LAST_SIGNAL] = { 0 };
-
-#define PARENT_TYPE G_TYPE_OBJECT
-static GObjectClass *parent_class = NULL;
-
-#define HIER_CLASS(hier) (EXCHANGE_HIERARCHY_CLASS (G_OBJECT_GET_CLASS (hier)))
-
-static void dispose (GObject *object);
-static void finalize (GObject *object);
-static gboolean is_empty (ExchangeHierarchy *hier);
-static void add_to_storage (ExchangeHierarchy *hier);
-static ExchangeAccountFolderResult scan_subtree (ExchangeHierarchy *hier,
- EFolder *folder,
- gint mode);
-static void rescan (ExchangeHierarchy *hier);
-static ExchangeAccountFolderResult create_folder (ExchangeHierarchy *hier,
- EFolder *parent,
- const gchar *name,
- const gchar *type);
-static ExchangeAccountFolderResult remove_folder (ExchangeHierarchy *hier,
- EFolder *folder);
-static ExchangeAccountFolderResult xfer_folder (ExchangeHierarchy *hier,
- EFolder *source,
- EFolder *dest_parent,
- const gchar *dest_name,
- gboolean remove_source);
-
-static void
-class_init (GObjectClass *object_class)
-{
- ExchangeHierarchyClass *exchange_hierarchy_class =
- EXCHANGE_HIERARCHY_CLASS (object_class);
-
- parent_class = g_type_class_ref (PARENT_TYPE);
-
- /* methods */
- object_class->dispose = dispose;
- object_class->finalize = finalize;
-
- exchange_hierarchy_class->is_empty = is_empty;
- exchange_hierarchy_class->add_to_storage = add_to_storage;
- exchange_hierarchy_class->rescan = rescan;
- exchange_hierarchy_class->scan_subtree = scan_subtree;
- exchange_hierarchy_class->create_folder = create_folder;
- exchange_hierarchy_class->remove_folder = remove_folder;
- exchange_hierarchy_class->xfer_folder = xfer_folder;
-
- /* signals */
- signals[NEW_FOLDER] =
- g_signal_new ("new_folder",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ExchangeHierarchyClass, new_folder),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1,
- G_TYPE_POINTER);
- signals[REMOVED_FOLDER] =
- g_signal_new ("removed_folder",
- G_OBJECT_CLASS_TYPE (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ExchangeHierarchyClass, removed_folder),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1,
- G_TYPE_POINTER);
-}
-
-static void
-dispose (GObject *object)
-{
- ExchangeHierarchy *hier = EXCHANGE_HIERARCHY (object);
-
- if (hier->toplevel) {
- g_object_unref (hier->toplevel);
- hier->toplevel = NULL;
- }
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-finalize (GObject *object)
-{
- ExchangeHierarchy *hier = EXCHANGE_HIERARCHY (object);
-
- g_free (hier->owner_name);
- g_free (hier->owner_email);
- g_free (hier->source_uri);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-E2K_MAKE_TYPE (exchange_hierarchy, ExchangeHierarchy, class_init, NULL, PARENT_TYPE)
-
-/**
- * exchange_hierarchy_new_folder:
- * @hier: the hierarchy
- * @folder: the new folder
- *
- * Emits a %new_folder signal.
- **/
-void
-exchange_hierarchy_new_folder (ExchangeHierarchy *hier,
- EFolder *folder)
-{
- g_return_if_fail (EXCHANGE_IS_HIERARCHY (hier));
- g_return_if_fail (E_IS_FOLDER (folder));
-
- g_signal_emit (hier, signals[NEW_FOLDER], 0, folder);
-}
-
-/**
- * exchange_hierarchy_removed_folder:
- * @hier: the hierarchy
- * @folder: the (about-to-be-)removed folder
- *
- * Emits a %removed_folder signal.
- **/
-void
-exchange_hierarchy_removed_folder (ExchangeHierarchy *hier,
- EFolder *folder)
-{
- g_return_if_fail (EXCHANGE_IS_HIERARCHY (hier));
- g_return_if_fail (E_IS_FOLDER (folder));
-
- g_signal_emit (hier, signals[REMOVED_FOLDER], 0, folder);
-}
-
-static gboolean
-is_empty (ExchangeHierarchy *hier)
-{
- return FALSE;
-}
-
-gboolean
-exchange_hierarchy_is_empty (ExchangeHierarchy *hier)
-{
- g_return_val_if_fail (EXCHANGE_IS_HIERARCHY (hier), TRUE);
-
- return HIER_CLASS (hier)->is_empty (hier);
-}
-
-static ExchangeAccountFolderResult
-create_folder (ExchangeHierarchy *hier, EFolder *parent,
- const gchar *name, const gchar *type)
-{
- return EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED;
-}
-
-static ExchangeAccountFolderResult
-remove_folder (ExchangeHierarchy *hier, EFolder *folder)
-{
- return EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED;
-}
-
-static ExchangeAccountFolderResult
-xfer_folder (ExchangeHierarchy *hier, EFolder *source,
- EFolder *dest_parent, const gchar *dest_name,
- gboolean remove_source)
-{
- return EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED;
-}
-
-/**
- * exchange_hierarchy_create_folder:
- * @hier: the hierarchy
- * @parent: the parent folder of the new folder
- * @name: name of the new folder (UTF8)
- * @type: Evolution folder type of the new folder
- *
- * Attempts to create a new folder.
- *
- * Return value: the result code
- **/
-ExchangeAccountFolderResult
-exchange_hierarchy_create_folder (ExchangeHierarchy *hier, EFolder *parent,
- const gchar *name, const gchar *type)
-{
- g_return_val_if_fail (EXCHANGE_IS_HIERARCHY (hier), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
- g_return_val_if_fail (E_IS_FOLDER (parent), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
- g_return_val_if_fail (name != NULL, EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
- g_return_val_if_fail (type != NULL, EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
-
- return HIER_CLASS (hier)->create_folder (hier, parent, name, type);
-}
-
-/**
- * exchange_hierarchy_remove_folder:
- * @hier: the hierarchy
- * @folder: the folder to remove
- *
- * Attempts to remove a folder.
- *
- * Return value: the result code
- **/
-ExchangeAccountFolderResult
-exchange_hierarchy_remove_folder (ExchangeHierarchy *hier, EFolder *folder)
-{
- g_return_val_if_fail (EXCHANGE_IS_HIERARCHY (hier), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
- g_return_val_if_fail (E_IS_FOLDER (folder), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
-
- return HIER_CLASS (hier)->remove_folder (hier, folder);
-}
-
-/**
- * exchange_hierarchy_xfer_folder:
- * @hier: the hierarchy
- * @source: the source folder
- * @dest_parent: the parent of the destination folder
- * @dest_name: name of the destination (UTF8)
- * @remove_source: %TRUE if this is a move, %FALSE if it is a copy
- *
- * Attempts to move or copy a folder.
- *
- * Return value: the result code
- **/
-ExchangeAccountFolderResult
-exchange_hierarchy_xfer_folder (ExchangeHierarchy *hier, EFolder *source,
- EFolder *dest_parent, const gchar *dest_name,
- gboolean remove_source)
-{
- g_return_val_if_fail (EXCHANGE_IS_HIERARCHY (hier), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
- g_return_val_if_fail (E_IS_FOLDER (source), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
- g_return_val_if_fail (E_IS_FOLDER (dest_parent), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
- g_return_val_if_fail (dest_name != NULL, EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
-
- return HIER_CLASS (hier)->xfer_folder (hier, source,
- dest_parent, dest_name,
- remove_source);
-}
-
-static void
-rescan (ExchangeHierarchy *hier)
-{
- ;
-}
-
-/**
- * exchange_hierarchy_rescan:
- * @hier: the hierarchy
- *
- * Tells the hierarchy to rescan its folder tree
- **/
-void
-exchange_hierarchy_rescan (ExchangeHierarchy *hier)
-{
- g_return_if_fail (EXCHANGE_IS_HIERARCHY (hier));
-
- HIER_CLASS (hier)->rescan (hier);
-}
-
-static ExchangeAccountFolderResult
-scan_subtree (ExchangeHierarchy *hier, EFolder *folder, gint mode)
-{
- return EXCHANGE_ACCOUNT_FOLDER_OK;
-}
-
-/**
- * exchange_hierarchy_scan_subtree:
- * @hier: the hierarchy
- * @folder: the folder to scan under
- *
- * Scans for folders in @hier underneath @folder, emitting %new_folder
- * signals for each one found. Depending on the kind of hierarchy,
- * this may initiate a recursive scan.
- *
- * Return value: the result code
- **/
-ExchangeAccountFolderResult
-exchange_hierarchy_scan_subtree (ExchangeHierarchy *hier, EFolder *folder, gint mode)
-{
- g_return_val_if_fail (EXCHANGE_IS_HIERARCHY (hier), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
- g_return_val_if_fail (E_IS_FOLDER (folder), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
-
- return HIER_CLASS (hier)->scan_subtree (hier, folder, mode);
-}
-
-static void
-add_to_storage (ExchangeHierarchy *hier)
-{
- e_folder_set_sorting_priority (hier->toplevel, hier->type);
- exchange_hierarchy_new_folder (hier, hier->toplevel);
-}
-
-/**
- * exchange_hierarchy_add_to_storage:
- * @hier: the hierarchy
- *
- * Tells the hierarchy to fill in its folder tree, emitting %new_folder
- * signals as appropriate.
- **/
-void
-exchange_hierarchy_add_to_storage (ExchangeHierarchy *hier)
-{
- g_return_if_fail (EXCHANGE_IS_HIERARCHY (hier));
-
- HIER_CLASS (hier)->add_to_storage (hier);
-}
-
-/**
- * exchange_hierarchy_construct:
- * @hier: the hierarchy
- * @account: the hierarchy's account
- * @type: the type of hierarchy
- * @toplevel: the top-level folder of the hierarchy
- * @owner_name: the display name of the owner of this hierarchy
- * @owner_email: the email address of the owner of this hierarchy
- * @source_uri: the evolution-mail source URI of this hierarchy.
- *
- * Constructs the hierarchy. @owner_name, @owner_email, and @source_uri
- * can be %NULL if not relevant to this hierarchy.
- **/
-void
-exchange_hierarchy_construct (ExchangeHierarchy *hier,
- ExchangeAccount *account,
- ExchangeHierarchyType type,
- EFolder *toplevel,
- const gchar *owner_name,
- const gchar *owner_email,
- const gchar *source_uri)
-{
- g_return_if_fail (EXCHANGE_IS_HIERARCHY (hier));
- g_return_if_fail (EXCHANGE_IS_ACCOUNT (account));
- g_return_if_fail (E_IS_FOLDER (toplevel));
-
- /* We don't ref the account since we'll be destroyed when
- * the account is
- */
- hier->account = account;
-
- hier->toplevel = toplevel;
- g_object_ref (toplevel);
-
- hier->type = type;
- hier->owner_name = g_strdup (owner_name);
- hier->owner_email = g_strdup (owner_email);
- hier->source_uri = g_strdup (source_uri);
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef __EXCHANGE_HIERARCHY_H__
-#define __EXCHANGE_HIERARCHY_H__
-
-#include "exchange-types.h"
-#include "exchange-account.h"
-#include "e-folder.h"
-
-G_BEGIN_DECLS
-
-#define EXCHANGE_TYPE_HIERARCHY (exchange_hierarchy_get_type ())
-#define EXCHANGE_HIERARCHY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXCHANGE_TYPE_HIERARCHY, ExchangeHierarchy))
-#define EXCHANGE_HIERARCHY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EXCHANGE_TYPE_HIERARCHY, ExchangeHierarchyClass))
-#define EXCHANGE_IS_HIERARCHY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXCHANGE_TYPE_HIERARCHY))
-#define EXCHANGE_IS_HIERARCHY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EXCHANGE_TYPE_HIERARCHY))
-
-struct _ExchangeHierarchy {
- GObject parent;
-
- ExchangeAccount *account;
- ExchangeHierarchyType type;
- EFolder *toplevel;
-
- gchar *owner_name;
- gchar *owner_email;
- gchar *source_uri;
-
- gboolean hide_private_items;
-};
-
-struct _ExchangeHierarchyClass {
- GObjectClass parent_class;
-
- /* methods */
- gboolean (*is_empty) (ExchangeHierarchy *hier);
-
- void (*add_to_storage) (ExchangeHierarchy *hier);
- void (*rescan) (ExchangeHierarchy *hier);
- ExchangeAccountFolderResult (*scan_subtree) (ExchangeHierarchy *hier,
- EFolder *folder,
- gint mode);
-
- ExchangeAccountFolderResult (*create_folder) (ExchangeHierarchy *hier,
- EFolder *parent,
- const gchar *name,
- const gchar *type);
- ExchangeAccountFolderResult (*remove_folder) (ExchangeHierarchy *hier,
- EFolder *folder);
- ExchangeAccountFolderResult (*xfer_folder) (ExchangeHierarchy *hier,
- EFolder *source,
- EFolder *dest_parent,
- const gchar *dest_name,
- gboolean remove_source);
-
- /* signals */
- void (*new_folder) (ExchangeHierarchy *hier,
- EFolder *folder);
- void (*removed_folder) (ExchangeHierarchy *hier,
- EFolder *folder);
-};
-
-GType exchange_hierarchy_get_type (void);
-
-void exchange_hierarchy_construct (ExchangeHierarchy *hier,
- ExchangeAccount *account,
- ExchangeHierarchyType type,
- EFolder *toplevel,
- const gchar *owner_name,
- const gchar *owner_email,
- const gchar *source_uri);
-
-void exchange_hierarchy_new_folder (ExchangeHierarchy *hier,
- EFolder *folder);
-void exchange_hierarchy_removed_folder (ExchangeHierarchy *hier,
- EFolder *folder);
-
-gboolean exchange_hierarchy_is_empty (ExchangeHierarchy *hier);
-
-void exchange_hierarchy_add_to_storage (ExchangeHierarchy *hier);
-void exchange_hierarchy_rescan (ExchangeHierarchy *hier);
-ExchangeAccountFolderResult exchange_hierarchy_scan_subtree (ExchangeHierarchy *hier,
- EFolder *folder,
- gint mode);
-
-ExchangeAccountFolderResult exchange_hierarchy_create_folder (ExchangeHierarchy *hier,
- EFolder *parent,
- const gchar *name,
- const gchar *type);
-ExchangeAccountFolderResult exchange_hierarchy_remove_folder (ExchangeHierarchy *hier,
- EFolder *folder);
-ExchangeAccountFolderResult exchange_hierarchy_xfer_folder (ExchangeHierarchy *hier,
- EFolder *source,
- EFolder *dest_parent,
- const gchar *dest_name,
- gboolean remove_source);
-
-G_END_DECLS
-
-#endif /* __EXCHANGE_HIERARCHY_H__ */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2002-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* exchange-oof: Out of Office code */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "exchange-oof.h"
-#include "exchange-account.h"
-#include "e2k-propnames.h"
-#include "e2k-utils.h"
-#include "e2k-uri.h"
-
-#include <string.h>
-
-/* Taken from gal/util/e-util.c */
-static gchar *
-find_str_case (const gchar *haystack, const gchar *needle, const gchar *end)
-{
- /* find the needle in the haystack neglecting case */
- const gchar *ptr;
- gint len;
-
- g_return_val_if_fail (haystack != NULL, NULL);
- g_return_val_if_fail (needle != NULL, NULL);
-
- len = strlen(needle);
- if (len > strlen(haystack))
- return NULL;
-
- if (len == 0)
- return (gchar *) haystack;
-
- for (ptr = haystack; ptr + len < end; ptr++)
- if (!g_ascii_strncasecmp (ptr, needle, len))
- return (gchar *) ptr;
-
- return NULL;
-
-}
-/**
- * exchange_oof_get:
- * @account: an #ExchangeAccount
- * @oof: pointer to variable to pass back OOF state in
- * @message: pointer to variable to pass back OOF message in
- *
- * Checks if Out-of-Office is enabled for @account and returns the
- * state in *@oof and the message in *@message (which the caller
- * must free).
- *
- * Return value: %TRUE if the OOF state was read, %FALSE if an error
- * occurred.
- **/
-gboolean
-exchange_oof_get (ExchangeAccount *account, gboolean *oof, gchar **message)
-{
- E2kContext *ctx;
- E2kHTTPStatus status;
- gchar *url, *p = NULL, *checked, *ta_start, *ta_end;
- SoupBuffer *response = NULL;
- const gchar *body, *end;
-
- ctx = exchange_account_get_context (account);
- if (!ctx)
- return FALSE;
-
- if (!message) {
- /* Do this the easy way */
- const gchar *prop = E2K_PR_EXCHANGE_OOF_STATE;
- E2kResult *results;
- gint nresults = 0;
-
- url = e2k_uri_concat (account->home_uri, "NON_IPM_SUBTREE/");
- status = e2k_context_propfind (ctx, NULL, url, &prop, 1,
- &results, &nresults);
- g_free (url);
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status) || nresults == 0)
- return FALSE;
-
- prop = e2k_properties_get_prop (results[0].props, E2K_PR_EXCHANGE_OOF_STATE);
- *oof = prop && atoi (prop);
-
- e2k_results_free (results, nresults);
- return TRUE;
- }
-
- url = e2k_uri_concat (account->home_uri, "?Cmd=options");
- status = e2k_context_get_owa (ctx, NULL, url, FALSE, &response);
- g_free (url);
- if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status))
- return FALSE;
-
- body = response->data;
- end = body + response->length;
- p = find_str_case (body, "<!--End OOF Assist-->", end);
- if (p)
- end = p;
-
- p = find_str_case (body, "name=\"OofState\"", end);
- if (p)
- p = find_str_case (body, "value=\"1\"", end);
- if (!p) {
- g_warning ("Could not find OofState in options page");
- soup_buffer_free (response);
- return FALSE;
- }
-
- checked = find_str_case (p, "checked", end);
- *oof = (checked && checked < strchr (p, '>'));
-
- if (message) {
- ta_end = find_str_case (p, "</textarea>", end);
- if (!ta_end) {
- g_warning ("Could not find OOF text in options page");
- soup_buffer_free (response);
- *message = g_strdup ("");
- return TRUE;
- }
- for (ta_start = ta_end - 1; ta_start > p; ta_start--) {
- if (*ta_start == '>')
- break;
- }
- if (*ta_start++ != '>') {
- g_warning ("Could not find OOF text in options page");
- soup_buffer_free (response);
- *message = g_strdup ("");
- return TRUE;
- }
-
- *message = g_strndup (ta_start, ta_end - ta_start);
- /* FIXME: HTML decode */
-
- }
-
- soup_buffer_free (response);
- return TRUE;
-}
-
-/**
- * exchange_oof_set:
- * @account: an #ExchangeAccount
- * @oof: new OOF state
- * @message: new OOF message, or %NULL
- *
- * Sets the OOF state for @account to @oof.
- *
- * Return value: %TRUE if the OOF state was updated, %FALSE if an
- * error occurred.
- **/
-gboolean
-exchange_oof_set (ExchangeAccount *account, gboolean oof, const gchar *message)
-{
- E2kContext *ctx;
- E2kHTTPStatus status;
-
- ctx = exchange_account_get_context (account);
- if (!ctx)
- return FALSE;
-
- if (message) {
- gchar *body, *message_enc;
-
- message_enc = e2k_uri_encode (message, FALSE, NULL);
- body = g_strdup_printf ("Cmd=options&OofState=%d&"
- "OofReply=%s",
- oof ? 1 : 0, message_enc);
- status = e2k_context_post (ctx, NULL, account->home_uri,
- "application/x-www-form-urlencoded",
- body, strlen (body), NULL, NULL);
- g_free (message_enc);
- g_free (body);
- } else {
- E2kProperties *props;
- gchar *url;
-
- props = e2k_properties_new ();
- e2k_properties_set_bool (props, E2K_PR_EXCHANGE_OOF_STATE, oof);
- url = e2k_uri_concat (account->home_uri, "NON_IPM_SUBTREE/");
- /* Need to pass TRUE for "create" here or it won't work */
- status = e2k_context_proppatch (ctx, NULL, url, props,
- TRUE, NULL);
- g_free (url);
- e2k_properties_free (props);
- }
-
- return E2K_HTTP_STATUS_IS_SUCCESSFUL (status) ||
- E2K_HTTP_STATUS_IS_REDIRECTION (status);
-}
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2002-2004 Novell, Inc. */
-
-#ifndef __EXCHANGE_OOF_H__
-#define __EXCHANGE_OOF_H__
-
-#include "exchange-types.h"
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-gboolean exchange_oof_get (ExchangeAccount *account,
- gboolean *oof,
- gchar **mmsg);
-gboolean exchange_oof_set (ExchangeAccount *account,
- gboolean oof,
- const gchar *msg);
-
-G_END_DECLS
-
-#endif /* __EXCHANGE_OOF_H__ */
+++ /dev/null
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* Copyright (C) 2002-2004 Novell, Inc. */
-
-#include "e2k-types.h"
-#include <glib-object.h>
-
-#ifndef __EXCHANGE_TYPES_H__
-#define __EXCHANGE_TYPES_H__
-
-typedef struct _ExchangeAccount ExchangeAccount;
-typedef struct _ExchangeAccountPrivate ExchangeAccountPrivate;
-typedef struct _ExchangeAccountClass ExchangeAccountClass;
-typedef struct _ExchangeConfigListener ExchangeConfigListener;
-typedef struct _ExchangeConfigListenerPrivate ExchangeConfigListenerPrivate;
-typedef struct _ExchangeConfigListenerClass ExchangeConfigListenerClass;
-typedef struct _ExchangeHierarchy ExchangeHierarchy;
-typedef struct _ExchangeHierarchyPrivate ExchangeHierarchyPrivate;
-typedef struct _ExchangeHierarchyClass ExchangeHierarchyClass;
-typedef struct _ExchangeHierarchyFavorites ExchangeHierarchyFavorites;
-typedef struct _ExchangeHierarchyFavoritesPrivate ExchangeHierarchyFavoritesPrivate;
-typedef struct _ExchangeHierarchyFavoritesClass ExchangeHierarchyFavoritesClass;
-typedef struct _ExchangeHierarchyGAL ExchangeHierarchyGAL;
-typedef struct _ExchangeHierarchyGALPrivate ExchangeHierarchyGALPrivate;
-typedef struct _ExchangeHierarchyGALClass ExchangeHierarchyGALClass;
-typedef struct _ExchangeHierarchySomeDAV ExchangeHierarchySomeDAV;
-typedef struct _ExchangeHierarchySomeDAVPrivate ExchangeHierarchySomeDAVPrivate;
-typedef struct _ExchangeHierarchySomeDAVClass ExchangeHierarchySomeDAVClass;
-typedef struct _ExchangeHierarchyWebDAV ExchangeHierarchyWebDAV;
-typedef struct _ExchangeHierarchyWebDAVPrivate ExchangeHierarchyWebDAVPrivate;
-typedef struct _ExchangeHierarchyWebDAVClass ExchangeHierarchyWebDAVClass;
-typedef struct _ExchangeOfflineHandler ExchangeOfflineHandler;
-typedef struct _ExchangeOfflineHandlerClass ExchangeOfflineHandlerClass;
-typedef struct _ExchangePermissionsDialog ExchangePermissionsDialog;
-typedef struct _ExchangePermissionsDialogPrivate ExchangePermissionsDialogPrivate;
-typedef struct _ExchangePermissionsDialogClass ExchangePermissionsDialogClass;
-typedef struct _ExchangeStorage ExchangeStorage;
-typedef struct _ExchangeStoragePrivate ExchangeStoragePrivate;
-typedef struct _ExchangeStorageClass ExchangeStorageClass;
-
-typedef struct _EFolderExchange EFolderExchange;
-typedef struct _EFolderExchangePrivate EFolderExchangePrivate;
-typedef struct _EFolderExchangeClass EFolderExchangeClass;
-
-typedef struct XCBackend XCBackend;
-typedef struct XCBackendPrivate XCBackendPrivate;
-typedef struct XCBackendClass XCBackendClass;
-
-typedef struct XCBackendComponent XCBackendComponent;
-typedef struct XCBackendComponentPrivate XCBackendComponentPrivate;
-typedef struct XCBackendComponentClass XCBackendComponentClass;
-
-typedef struct XCBackendView XCBackendView;
-typedef struct XCBackendViewPrivate XCBackendViewPrivate;
-typedef struct XCBackendViewClass XCBackendViewClass;
-
-typedef enum {
- EXCHANGE_HIERARCHY_PERSONAL,
- EXCHANGE_HIERARCHY_FAVORITES,
- EXCHANGE_HIERARCHY_PUBLIC,
- EXCHANGE_HIERARCHY_GAL,
- EXCHANGE_HIERARCHY_FOREIGN
-} ExchangeHierarchyType;
-
-G_END_DECLS
-
-#endif /* __EXCHANGE_TYPES_H__ */
+++ /dev/null
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-datarootdir=@datarootdir@
-datadir=@datadir@
-
-idldir=@idldir@
-IDL_INCLUDES=-I ${idldir} @IDL_INCLUDES@
-
-privincludedir=@privincludedir@
-
-Name: libexchange
-Description: Client library for accessing Exchange server through webdav.
-Version: @VERSION@
-Requires: libsoup-2.4 >= @LIBSOUP_REQUIRED@
-Libs: -L${libdir} -lexchange-storage-1.2
-Cflags: -I${privincludedir}/exchange
+++ /dev/null
-2005-04-21 Sarfraaz Ahmed <asarfraaz@novell.com>
-
- * Moved the code to e-d-s from exchange
-
-2005-02-08 David Malcolm <dmalcolm@redhat.com>
-
- * Makefile.am:
-
- Use appropriate libtool macro for convenience libraries
- (_LTLIBRARIES, rather than _LTLIBRARIES), since some architectures
- do not allow using static libraries this way.
-
-2005-01-08 Not Zed <NotZed@Ximian.com>
-
- ** See Ximian Bug #70323.
-
- * xntlm-md4.c, xntlm-des.c: convert all unsigned long/long to
- guint32, it expects them to be 32 bits.
-
-2004-04-23 Dan Winship <danw@ximian.com>
-
- * xntlm.c (xntlm_negotiate): Redo the doc comment to make gtk-doc
- happy
-
-2003-11-13 Dan Winship <danw@ximian.com>
-
- * xntlm-des.c: ANSIfy prototypes for gtk-doc
-
-2003-10-07 Dan Winship <danw@ximian.com>
-
- * xntlm.c (ntlm_lanmanager_hash): fix a gcc 3.3 warning
-
-2003-04-08 Dan Winship <danw@ximian.com>
-
- * xntlm.c (setup_schedule): Fix to not read uninitialized memory
- to make valgrind/purify happy
-
-2003-04-04 Dan Winship <danw@ximian.com>
-
- * xntlm-des.h: add XNTLM_DES_ENCRYPT and XNTLM_DES_DECRYPT defines.
-
- * xntlm-des.c (xntlm_deskey): make the key arg const.
-
- * xntlm.c (setup_schedule): s/0/XNTLM_DES_ENCRYPT/
-
-2003-03-19 Dan Winship <danw@ximian.com>
-
- * Makefile.am: Make this a static library
-
-2003-02-26 Dan Winship <danw@ximian.com>
-
- * xntlm.c (strip_dup): Fix a bug
-
-2003-02-21 Dan Winship <danw@ximian.com>
-
- * xntlm.c, xntlm-des.c, xntlm-md4.c: #include config.h
-
-2002-08-05 Dan Winship <danw@ximian.com>
-
- * Split this code out of camel/soup and tidy it up
-
+++ /dev/null
-noinst_LTLIBRARIES = libxntlm.la
-
-libxntlm_la_SOURCES = \
- xntlm.c \
- xntlm.h \
- xntlm-des.c \
- xntlm-des.h \
- xntlm-md4.c \
- xntlm-md4.h
-
-libxntlm_la_CPPFLAGS = \
- $(AM_CPPFLAGS) \
- -I$(top_srcdir) \
- $(GLIB_CFLAGS)
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2001-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "xntlm-des.h"
-#include <string.h>
-
-/* Public domain DES implementation from Phil Karn */
-
-static guint32 Spbox[8][64] = {
- { 0x01010400,0x00000000,0x00010000,0x01010404,
- 0x01010004,0x00010404,0x00000004,0x00010000,
- 0x00000400,0x01010400,0x01010404,0x00000400,
- 0x01000404,0x01010004,0x01000000,0x00000004,
- 0x00000404,0x01000400,0x01000400,0x00010400,
- 0x00010400,0x01010000,0x01010000,0x01000404,
- 0x00010004,0x01000004,0x01000004,0x00010004,
- 0x00000000,0x00000404,0x00010404,0x01000000,
- 0x00010000,0x01010404,0x00000004,0x01010000,
- 0x01010400,0x01000000,0x01000000,0x00000400,
- 0x01010004,0x00010000,0x00010400,0x01000004,
- 0x00000400,0x00000004,0x01000404,0x00010404,
- 0x01010404,0x00010004,0x01010000,0x01000404,
- 0x01000004,0x00000404,0x00010404,0x01010400,
- 0x00000404,0x01000400,0x01000400,0x00000000,
- 0x00010004,0x00010400,0x00000000,0x01010004 },
- { 0x80108020,0x80008000,0x00008000,0x00108020,
- 0x00100000,0x00000020,0x80100020,0x80008020,
- 0x80000020,0x80108020,0x80108000,0x80000000,
- 0x80008000,0x00100000,0x00000020,0x80100020,
- 0x00108000,0x00100020,0x80008020,0x00000000,
- 0x80000000,0x00008000,0x00108020,0x80100000,
- 0x00100020,0x80000020,0x00000000,0x00108000,
- 0x00008020,0x80108000,0x80100000,0x00008020,
- 0x00000000,0x00108020,0x80100020,0x00100000,
- 0x80008020,0x80100000,0x80108000,0x00008000,
- 0x80100000,0x80008000,0x00000020,0x80108020,
- 0x00108020,0x00000020,0x00008000,0x80000000,
- 0x00008020,0x80108000,0x00100000,0x80000020,
- 0x00100020,0x80008020,0x80000020,0x00100020,
- 0x00108000,0x00000000,0x80008000,0x00008020,
- 0x80000000,0x80100020,0x80108020,0x00108000 },
- { 0x00000208,0x08020200,0x00000000,0x08020008,
- 0x08000200,0x00000000,0x00020208,0x08000200,
- 0x00020008,0x08000008,0x08000008,0x00020000,
- 0x08020208,0x00020008,0x08020000,0x00000208,
- 0x08000000,0x00000008,0x08020200,0x00000200,
- 0x00020200,0x08020000,0x08020008,0x00020208,
- 0x08000208,0x00020200,0x00020000,0x08000208,
- 0x00000008,0x08020208,0x00000200,0x08000000,
- 0x08020200,0x08000000,0x00020008,0x00000208,
- 0x00020000,0x08020200,0x08000200,0x00000000,
- 0x00000200,0x00020008,0x08020208,0x08000200,
- 0x08000008,0x00000200,0x00000000,0x08020008,
- 0x08000208,0x00020000,0x08000000,0x08020208,
- 0x00000008,0x00020208,0x00020200,0x08000008,
- 0x08020000,0x08000208,0x00000208,0x08020000,
- 0x00020208,0x00000008,0x08020008,0x00020200 },
- { 0x00802001,0x00002081,0x00002081,0x00000080,
- 0x00802080,0x00800081,0x00800001,0x00002001,
- 0x00000000,0x00802000,0x00802000,0x00802081,
- 0x00000081,0x00000000,0x00800080,0x00800001,
- 0x00000001,0x00002000,0x00800000,0x00802001,
- 0x00000080,0x00800000,0x00002001,0x00002080,
- 0x00800081,0x00000001,0x00002080,0x00800080,
- 0x00002000,0x00802080,0x00802081,0x00000081,
- 0x00800080,0x00800001,0x00802000,0x00802081,
- 0x00000081,0x00000000,0x00000000,0x00802000,
- 0x00002080,0x00800080,0x00800081,0x00000001,
- 0x00802001,0x00002081,0x00002081,0x00000080,
- 0x00802081,0x00000081,0x00000001,0x00002000,
- 0x00800001,0x00002001,0x00802080,0x00800081,
- 0x00002001,0x00002080,0x00800000,0x00802001,
- 0x00000080,0x00800000,0x00002000,0x00802080 },
- { 0x00000100,0x02080100,0x02080000,0x42000100,
- 0x00080000,0x00000100,0x40000000,0x02080000,
- 0x40080100,0x00080000,0x02000100,0x40080100,
- 0x42000100,0x42080000,0x00080100,0x40000000,
- 0x02000000,0x40080000,0x40080000,0x00000000,
- 0x40000100,0x42080100,0x42080100,0x02000100,
- 0x42080000,0x40000100,0x00000000,0x42000000,
- 0x02080100,0x02000000,0x42000000,0x00080100,
- 0x00080000,0x42000100,0x00000100,0x02000000,
- 0x40000000,0x02080000,0x42000100,0x40080100,
- 0x02000100,0x40000000,0x42080000,0x02080100,
- 0x40080100,0x00000100,0x02000000,0x42080000,
- 0x42080100,0x00080100,0x42000000,0x42080100,
- 0x02080000,0x00000000,0x40080000,0x42000000,
- 0x00080100,0x02000100,0x40000100,0x00080000,
- 0x00000000,0x40080000,0x02080100,0x40000100 },
- { 0x20000010,0x20400000,0x00004000,0x20404010,
- 0x20400000,0x00000010,0x20404010,0x00400000,
- 0x20004000,0x00404010,0x00400000,0x20000010,
- 0x00400010,0x20004000,0x20000000,0x00004010,
- 0x00000000,0x00400010,0x20004010,0x00004000,
- 0x00404000,0x20004010,0x00000010,0x20400010,
- 0x20400010,0x00000000,0x00404010,0x20404000,
- 0x00004010,0x00404000,0x20404000,0x20000000,
- 0x20004000,0x00000010,0x20400010,0x00404000,
- 0x20404010,0x00400000,0x00004010,0x20000010,
- 0x00400000,0x20004000,0x20000000,0x00004010,
- 0x20000010,0x20404010,0x00404000,0x20400000,
- 0x00404010,0x20404000,0x00000000,0x20400010,
- 0x00000010,0x00004000,0x20400000,0x00404010,
- 0x00004000,0x00400010,0x20004010,0x00000000,
- 0x20404000,0x20000000,0x00400010,0x20004010 },
- { 0x00200000,0x04200002,0x04000802,0x00000000,
- 0x00000800,0x04000802,0x00200802,0x04200800,
- 0x04200802,0x00200000,0x00000000,0x04000002,
- 0x00000002,0x04000000,0x04200002,0x00000802,
- 0x04000800,0x00200802,0x00200002,0x04000800,
- 0x04000002,0x04200000,0x04200800,0x00200002,
- 0x04200000,0x00000800,0x00000802,0x04200802,
- 0x00200800,0x00000002,0x04000000,0x00200800,
- 0x04000000,0x00200800,0x00200000,0x04000802,
- 0x04000802,0x04200002,0x04200002,0x00000002,
- 0x00200002,0x04000000,0x04000800,0x00200000,
- 0x04200800,0x00000802,0x00200802,0x04200800,
- 0x00000802,0x04000002,0x04200802,0x04200000,
- 0x00200800,0x00000000,0x00000002,0x04200802,
- 0x00000000,0x00200802,0x04200000,0x00000800,
- 0x04000002,0x04000800,0x00000800,0x00200002 },
- { 0x10001040,0x00001000,0x00040000,0x10041040,
- 0x10000000,0x10001040,0x00000040,0x10000000,
- 0x00040040,0x10040000,0x10041040,0x00041000,
- 0x10041000,0x00041040,0x00001000,0x00000040,
- 0x10040000,0x10000040,0x10001000,0x00001040,
- 0x00041000,0x00040040,0x10040040,0x10041000,
- 0x00001040,0x00000000,0x00000000,0x10040040,
- 0x10000040,0x10001000,0x00041040,0x00040000,
- 0x00041040,0x00040000,0x10041000,0x00001000,
- 0x00000040,0x10040040,0x00001000,0x00041040,
- 0x10001000,0x00000040,0x10000040,0x10040000,
- 0x10040040,0x10000000,0x00040000,0x10001040,
- 0x00000000,0x10041040,0x00040040,0x10000040,
- 0x10040000,0x10001000,0x10001040,0x00000000,
- 0x10041040,0x00041000,0x00041000,0x00001040,
- 0x00001040,0x00040040,0x10000000,0x10041000 }
-};
-
-#undef F
-#define F(l,r,key){\
- work = ((r >> 4) | (r << 28)) ^ key[0];\
- l ^= Spbox[6][work & 0x3f];\
- l ^= Spbox[4][(work >> 8) & 0x3f];\
- l ^= Spbox[2][(work >> 16) & 0x3f];\
- l ^= Spbox[0][(work >> 24) & 0x3f];\
- work = r ^ key[1];\
- l ^= Spbox[7][work & 0x3f];\
- l ^= Spbox[5][(work >> 8) & 0x3f];\
- l ^= Spbox[3][(work >> 16) & 0x3f];\
- l ^= Spbox[1][(work >> 24) & 0x3f];\
-}
-/* Encrypt or decrypt a block of data in ECB mode */
-void
-xntlm_des(XNTLM_DES_KS ks, guchar block[8])
-{
- guint32 left,right,work;
-
- /* Read input block and place in left/right in big-endian order */
- left = ((guint32)block[0] << 24)
- | ((guint32)block[1] << 16)
- | ((guint32)block[2] << 8)
- | (guint32)block[3];
- right = ((guint32)block[4] << 24)
- | ((guint32)block[5] << 16)
- | ((guint32)block[6] << 8)
- | (guint32)block[7];
-
- /* Hoey's clever initial permutation algorithm, from Outerbridge
- * (see Schneier p 478)
- *
- * The convention here is the same as Outerbridge: rotate each
- * register left by 1 bit, i.e., so that "left" contains permuted
- * input bits 2, 3, 4, ... 1 and "right" contains 33, 34, 35, ... 32
- * (using origin-1 numbering as in the FIPS). This allows us to avoid
- * one of the two rotates that would otherwise be required in each of
- * the 16 rounds.
- */
- work = ((left >> 4) ^ right) & 0x0f0f0f0f;
- right ^= work;
- left ^= work << 4;
- work = ((left >> 16) ^ right) & 0xffff;
- right ^= work;
- left ^= work << 16;
- work = ((right >> 2) ^ left) & 0x33333333;
- left ^= work;
- right ^= (work << 2);
- work = ((right >> 8) ^ left) & 0xff00ff;
- left ^= work;
- right ^= (work << 8);
- right = (right << 1) | (right >> 31);
- work = (left ^ right) & 0xaaaaaaaa;
- left ^= work;
- right ^= work;
- left = (left << 1) | (left >> 31);
-
- /* Now do the 16 rounds */
- F(left,right,ks[0]);
- F(right,left,ks[1]);
- F(left,right,ks[2]);
- F(right,left,ks[3]);
- F(left,right,ks[4]);
- F(right,left,ks[5]);
- F(left,right,ks[6]);
- F(right,left,ks[7]);
- F(left,right,ks[8]);
- F(right,left,ks[9]);
- F(left,right,ks[10]);
- F(right,left,ks[11]);
- F(left,right,ks[12]);
- F(right,left,ks[13]);
- F(left,right,ks[14]);
- F(right,left,ks[15]);
-
- /* Inverse permutation, also from Hoey via Outerbridge and Schneier */
- right = (right << 31) | (right >> 1);
- work = (left ^ right) & 0xaaaaaaaa;
- left ^= work;
- right ^= work;
- left = (left >> 1) | (left << 31);
- work = ((left >> 8) ^ right) & 0xff00ff;
- right ^= work;
- left ^= work << 8;
- work = ((left >> 2) ^ right) & 0x33333333;
- right ^= work;
- left ^= work << 2;
- work = ((right >> 16) ^ left) & 0xffff;
- left ^= work;
- right ^= work << 16;
- work = ((right >> 4) ^ left) & 0x0f0f0f0f;
- left ^= work;
- right ^= work << 4;
-
- /* Put the block back into the user's buffer with final swap */
- block[0] = right >> 24;
- block[1] = right >> 16;
- block[2] = right >> 8;
- block[3] = right;
- block[4] = left >> 24;
- block[5] = left >> 16;
- block[6] = left >> 8;
- block[7] = left;
-}
-
-/* Key schedule-related tables from FIPS-46 */
-
-/* permuted choice table (key) */
-static guchar pc1[] = {
- 57, 49, 41, 33, 25, 17, 9,
- 1, 58, 50, 42, 34, 26, 18,
- 10, 2, 59, 51, 43, 35, 27,
- 19, 11, 3, 60, 52, 44, 36,
-
- 63, 55, 47, 39, 31, 23, 15,
- 7, 62, 54, 46, 38, 30, 22,
- 14, 6, 61, 53, 45, 37, 29,
- 21, 13, 5, 28, 20, 12, 4
-};
-
-/* number left rotations of pc1 */
-static guchar totrot[] = {
- 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
-};
-
-/* permuted choice key (table) */
-static guchar pc2[] = {
- 14, 17, 11, 24, 1, 5,
- 3, 28, 15, 6, 21, 10,
- 23, 19, 12, 4, 26, 8,
- 16, 7, 27, 20, 13, 2,
- 41, 52, 31, 37, 47, 55,
- 30, 40, 51, 45, 33, 48,
- 44, 49, 39, 56, 34, 53,
- 46, 42, 50, 36, 29, 32
-};
-
-/* End of DES-defined tables */
-
-/* bit 0 is left-most in byte */
-static gint bytebit[] = {
- 0200,0100,040,020,010,04,02,01
-};
-
-/* Generate key schedule for encryption or decryption
- * depending on the value of "decrypt"
- */
-void
-xntlm_deskey(XNTLM_DES_KS k, const guchar *key, gint decrypt)
-{
- guchar pc1m[56]; /* place to modify pc1 into */
- guchar pcr[56]; /* place to rotate pc1 into */
- register gint i,j,l;
- gint m;
- guchar ks[8];
-
- for (j=0; j<56; j++) { /* convert pc1 to bits of key */
- l=pc1[j]-1; /* integer bit location */
- m = l & 07; /* find bit */
- pc1m[j]=(key[l>>3] & /* find which key byte l is in */
- bytebit[m]) /* and which bit of that byte */
- ? 1 : 0; /* and store 1-bit result */
- }
- for (i=0; i<16; i++) { /* key chunk for each iteration */
- memset(ks,0,sizeof(ks)); /* Clear key schedule */
- for (j=0; j<56; j++) /* rotate pc1 the right amount */
- pcr[j] = pc1m[(l=j+totrot[decrypt? 15-i : i])<(j<28? 28 : 56) ? l: l-28];
- /* rotate left and right halves independently */
- for (j=0; j<48; j++){ /* select bits individually */
- /* check bit that goes to ks[j] */
- if (pcr[pc2[j]-1]) {
- /* mask it in if it's there */
- l= j % 6;
- ks[j/6] |= bytebit[l] >> 2;
- }
- }
- /* Now convert to packed odd/even interleaved form */
- k[i][0] = ((guint32)ks[0] << 24)
- | ((guint32)ks[2] << 16)
- | ((guint32)ks[4] << 8)
- | ((guint32)ks[6]);
- k[i][1] = ((guint32)ks[1] << 24)
- | ((guint32)ks[3] << 16)
- | ((guint32)ks[5] << 8)
- | ((guint32)ks[7]);
- }
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef _XNTLM_DES_H
-#define _XNTLM_DES_H
-
-#include <glib.h>
-
-typedef guint32 XNTLM_DES_KS[16][2];
-
-enum {
- XNTLM_DES_ENCRYPT = 0,
- XNTLM_DES_DECRYPT = 1
-};
-
-void xntlm_deskey (XNTLM_DES_KS ks, const guchar *key, gint decrypt);
-
-void xntlm_des (XNTLM_DES_KS ks, guchar block[8]);
-
-#endif /* _XNTLM_DES_H */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2001-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib.h>
-#include "xntlm-md4.h"
-
-#include <string.h>
-
-/* MD4 encoder. The reference implementation in RFC1320 isn't
- * GPL-compatible.
- */
-
-#define F(X,Y,Z) ( ((X)&(Y)) | ((~(X))&(Z)) )
-#define G(X,Y,Z) ( ((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z)) )
-#define H(X,Y,Z) ( (X)^(Y)^(Z) )
-#define ROT(val, n) ( ((val) << (n)) | ((val) >> (32 - (n))) )
-
-static void
-md4sum_round (const guchar *M,
- guint32 *AA, guint32 *BB,
- guint32 *CC, guint32 *DD)
-{
- guint32 A, B, C, D, X[16];
- gint i;
-
- for (i = 0; i < 16; i++) {
- X[i] = (M[i*4]) | (M[i*4 + 1] << 8) |
- (M[i*4 + 2] << 16) | (M[i*4 + 3] << 24);
- }
-
- A = *AA;
- B = *BB;
- C = *CC;
- D = *DD;
-
- A = ROT (A + F(B, C, D) + X[0], 3);
- D = ROT (D + F(A, B, C) + X[1], 7);
- C = ROT (C + F(D, A, B) + X[2], 11);
- B = ROT (B + F(C, D, A) + X[3], 19);
- A = ROT (A + F(B, C, D) + X[4], 3);
- D = ROT (D + F(A, B, C) + X[5], 7);
- C = ROT (C + F(D, A, B) + X[6], 11);
- B = ROT (B + F(C, D, A) + X[7], 19);
- A = ROT (A + F(B, C, D) + X[8], 3);
- D = ROT (D + F(A, B, C) + X[9], 7);
- C = ROT (C + F(D, A, B) + X[10], 11);
- B = ROT (B + F(C, D, A) + X[11], 19);
- A = ROT (A + F(B, C, D) + X[12], 3);
- D = ROT (D + F(A, B, C) + X[13], 7);
- C = ROT (C + F(D, A, B) + X[14], 11);
- B = ROT (B + F(C, D, A) + X[15], 19);
-
- A = ROT (A + G(B, C, D) + X[0] + 0x5A827999, 3);
- D = ROT (D + G(A, B, C) + X[4] + 0x5A827999, 5);
- C = ROT (C + G(D, A, B) + X[8] + 0x5A827999, 9);
- B = ROT (B + G(C, D, A) + X[12] + 0x5A827999, 13);
- A = ROT (A + G(B, C, D) + X[1] + 0x5A827999, 3);
- D = ROT (D + G(A, B, C) + X[5] + 0x5A827999, 5);
- C = ROT (C + G(D, A, B) + X[9] + 0x5A827999, 9);
- B = ROT (B + G(C, D, A) + X[13] + 0x5A827999, 13);
- A = ROT (A + G(B, C, D) + X[2] + 0x5A827999, 3);
- D = ROT (D + G(A, B, C) + X[6] + 0x5A827999, 5);
- C = ROT (C + G(D, A, B) + X[10] + 0x5A827999, 9);
- B = ROT (B + G(C, D, A) + X[14] + 0x5A827999, 13);
- A = ROT (A + G(B, C, D) + X[3] + 0x5A827999, 3);
- D = ROT (D + G(A, B, C) + X[7] + 0x5A827999, 5);
- C = ROT (C + G(D, A, B) + X[11] + 0x5A827999, 9);
- B = ROT (B + G(C, D, A) + X[15] + 0x5A827999, 13);
-
- A = ROT (A + H(B, C, D) + X[0] + 0x6ED9EBA1, 3);
- D = ROT (D + H(A, B, C) + X[8] + 0x6ED9EBA1, 9);
- C = ROT (C + H(D, A, B) + X[4] + 0x6ED9EBA1, 11);
- B = ROT (B + H(C, D, A) + X[12] + 0x6ED9EBA1, 15);
- A = ROT (A + H(B, C, D) + X[2] + 0x6ED9EBA1, 3);
- D = ROT (D + H(A, B, C) + X[10] + 0x6ED9EBA1, 9);
- C = ROT (C + H(D, A, B) + X[6] + 0x6ED9EBA1, 11);
- B = ROT (B + H(C, D, A) + X[14] + 0x6ED9EBA1, 15);
- A = ROT (A + H(B, C, D) + X[1] + 0x6ED9EBA1, 3);
- D = ROT (D + H(A, B, C) + X[9] + 0x6ED9EBA1, 9);
- C = ROT (C + H(D, A, B) + X[5] + 0x6ED9EBA1, 11);
- B = ROT (B + H(C, D, A) + X[13] + 0x6ED9EBA1, 15);
- A = ROT (A + H(B, C, D) + X[3] + 0x6ED9EBA1, 3);
- D = ROT (D + H(A, B, C) + X[11] + 0x6ED9EBA1, 9);
- C = ROT (C + H(D, A, B) + X[7] + 0x6ED9EBA1, 11);
- B = ROT (B + H(C, D, A) + X[15] + 0x6ED9EBA1, 15);
-
- *AA += A;
- *BB += B;
- *CC += C;
- *DD += D;
-}
-
-/**
- * xntlm_md4sum:
- * @in: the input data
- * @nbytes: the length of @in in bytes
- * @digest: buffer to compute the digest
- *
- * Computes the MD4 checksum of @in and puts it in @digest.
- **/
-void
-xntlm_md4sum (const guchar *in, gint nbytes, guchar digest[16])
-{
- guchar M[128];
- guint32 A, B, C, D;
- gint pbytes, nbits = nbytes * 8, remaining_bytes;
- gint total_len, offset;
-
- pbytes = (120 - (nbytes % 64)) % 64;
- total_len = nbytes + pbytes + 8;
-
- A = 0x67452301;
- B = 0xEFCDAB89;
- C = 0x98BADCFE;
- D = 0x10325476;
-
- for (offset = 0; offset < nbytes - 64; offset += 64)
- md4sum_round (in + offset, &A, &B, &C, &D);
-
- /* Copy the leftover part of the message into M */
- remaining_bytes = nbytes - offset;
- memcpy (M, in + offset, remaining_bytes);
-
- /* Append a single "1" bit and appropriate padding */
- M[remaining_bytes] = 0x80;
- memset (M + remaining_bytes + 1, 0, pbytes - 1 + 8);
-
- /* Append length. */
- M[remaining_bytes + pbytes] = nbits & 0xFF;
- M[remaining_bytes + pbytes + 1] = (nbits >> 8) & 0xFF;
- M[remaining_bytes + pbytes + 2] = (nbits >> 16) & 0xFF;
- M[remaining_bytes + pbytes + 3] = (nbits >> 24) & 0xFF;
- /* We assume nbits is less than 2^32 */
-
- md4sum_round (M, &A, &B, &C, &D);
- if (remaining_bytes > 56)
- md4sum_round (M + 64, &A, &B, &C, &D);
-
- digest[0] = A & 0xFF;
- digest[1] = (A >> 8) & 0xFF;
- digest[2] = (A >> 16) & 0xFF;
- digest[3] = (A >> 24) & 0xFF;
- digest[4] = B & 0xFF;
- digest[5] = (B >> 8) & 0xFF;
- digest[6] = (B >> 16) & 0xFF;
- digest[7] = (B >> 24) & 0xFF;
- digest[8] = C & 0xFF;
- digest[9] = (C >> 8) & 0xFF;
- digest[10] = (C >> 16) & 0xFF;
- digest[11] = (C >> 24) & 0xFF;
- digest[12] = D & 0xFF;
- digest[13] = (D >> 8) & 0xFF;
- digest[14] = (D >> 16) & 0xFF;
- digest[15] = (D >> 24) & 0xFF;
-}
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef _XNTLM_MD4_H
-#define _XNTLM_MD4_H
-
-void xntlm_md4sum (const guchar *in, gint nbytes,
- guchar digest[16]);
-
-#endif /* _XNTLM_MD4_H */
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2001-2004 Novell, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU Lesser General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "xntlm.h"
-#include "xntlm-des.h"
-#include "xntlm-md4.h"
-
-#include <ctype.h>
-#include <string.h>
-
-static guchar NTLM_NEGOTIATE_MESSAGE[] = {
- 'N', 'T', 'L', 'M', 'S', 'S', 'P', 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x06, 0x82, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00
-};
-
-/**
- * xntlm_negotiate:
- *
- * Creates an NTLM Type 1 (Negotiate) message
- *
- * Return value: the message
- **/
-GByteArray *
-xntlm_negotiate (void)
-{
- GByteArray *message;
-
- message = g_byte_array_new ();
- g_byte_array_append (message, NTLM_NEGOTIATE_MESSAGE,
- sizeof (NTLM_NEGOTIATE_MESSAGE));
- return message;
-}
-
-#define GET_SHORTY(p) ((p)[0] + ((p)[1] << 8))
-
-static gchar *
-strip_dup (guchar *mem, gint len)
-{
- gchar *buf = g_malloc (len / 2 + 1), *p = buf;
-
- while (len > 0) {
- *p = (gchar)*mem;
- p++;
- mem += 2;
- len -= 2;
- }
-
- *p = '\0';
- return buf;
-}
-
-#define NTLM_CHALLENGE_NONCE_POS 24
-#define NTLM_CHALLENGE_NONCE_LEN 8
-
-#define NTLM_CHALLENGE_DATA_OFFSET_POS 44
-#define NTLM_CHALLENGE_DATA_LENGTH_POS 40
-
-#define NTLM_CHALLENGE_DATA_NT_DOMAIN 2
-#define NTLM_CHALLENGE_DATA_W2K_DOMAIN 4
-
-#define NTLM_CHALLENGE_BASE_SIZE 48
-
-/**
- * xntlm_parse_challenge:
- * @challenge: buffer containing an NTLM Type 2 (Challenge) message
- * @len: the length of @challenge
- * @nonce: return variable for the challenge nonce, or %NULL
- * @nt_domain: return variable for the server NT domain, or %NULL
- * @w2k_domain: return variable for the server W2k domain, or %NULL
- *
- * Attempts to parse the challenge in @challenge. If @nonce is
- * non-%NULL, the 8-byte nonce from @challenge will be returned in it.
- * Likewise, if @nt_domain and/or @w2k_domain are non-%NULL, the
- * server's domain names will be returned in them. The strings
- * returned must be freed with g_free().
- *
- * Return value: %TRUE if the challenge could be parsed,
- * %FALSE otherwise.
- **/
-gboolean
-xntlm_parse_challenge (gpointer challenge, gint len, gchar **nonce,
- gchar **nt_domain, gchar **w2k_domain)
-{
- guchar *chall = (guchar *)challenge;
- gint off, dlen, doff, type;
-
- if (len < NTLM_CHALLENGE_BASE_SIZE)
- return FALSE;
-
- off = GET_SHORTY (chall + NTLM_CHALLENGE_DATA_OFFSET_POS);
- dlen = GET_SHORTY (chall + NTLM_CHALLENGE_DATA_LENGTH_POS);
- if (len < off + dlen)
- return FALSE;
-
- if (nonce) {
- *nonce = g_memdup (chall + NTLM_CHALLENGE_NONCE_POS,
- NTLM_CHALLENGE_NONCE_LEN);
- }
-
- if (!nt_domain && !w2k_domain)
- return TRUE;
-
- while (off < len - 4) {
- type = GET_SHORTY (chall + off);
- dlen = GET_SHORTY (chall + off + 2);
- doff = off + 4;
- if (doff + dlen > len)
- break;
-
- switch (type) {
- case NTLM_CHALLENGE_DATA_NT_DOMAIN:
- if (nt_domain)
- *nt_domain = strip_dup (chall + doff, dlen);
- break;
- case NTLM_CHALLENGE_DATA_W2K_DOMAIN:
- if (w2k_domain)
- *w2k_domain = strip_dup (chall + doff, dlen);
- break;
- }
-
- off = doff + dlen;
- }
-
- return TRUE;
-}
-
-static void
-ntlm_set_string (GByteArray *ba, gint offset, const gchar *data, gint len)
-{
- ba->data[offset ] = ba->data[offset + 2] = len & 0xFF;
- ba->data[offset + 1] = ba->data[offset + 3] = (len >> 8) & 0xFF;
- ba->data[offset + 4] = ba->len & 0xFF;
- ba->data[offset + 5] = (ba->len >> 8) & 0xFF;
- g_byte_array_append (ba, (guint8 *) data, len);
-}
-
-static void ntlm_lanmanager_hash (const gchar *password, gchar hash[21]);
-static void ntlm_nt_hash (const gchar *password, gchar hash[21]);
-static void ntlm_calc_response (const guchar key[21],
- const guchar plaintext[8],
- guchar results[24]);
-
-static guchar NTLM_RESPONSE_MESSAGE_HEADER[] = {
- 'N', 'T', 'L', 'M', 'S', 'S', 'P', 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x02, 0x82, 0x00, 0x00
-};
-
-#define NTLM_RESPONSE_BASE_SIZE 64
-#define NTLM_RESPONSE_LM_RESP_OFFSET 12
-#define NTLM_RESPONSE_NT_RESP_OFFSET 20
-#define NTLM_RESPONSE_DOMAIN_OFFSET 28
-#define NTLM_RESPONSE_USER_OFFSET 36
-#define NTLM_RESPONSE_WORKSTATION_OFFSET 44
-
-/**
- * xntlm_authenticate:
- * @nonce: the nonce from an NTLM Type 2 (Challenge) message
- * @domain: the NT domain to authenticate against
- * @user: the name of the user in @domain
- * @password: @user's password
- * @workstation: the name of the local workstation authenticated
- * against, or %NULL.
- *
- * Generates an NTLM Type 3 (Authenticate) message from the given
- * data. @workstation is provided for completeness, but can basically
- * always be left %NULL.
- *
- * Return value: the NTLM Type 3 message
- **/
-GByteArray *
-xntlm_authenticate (const gchar *nonce, const gchar *domain,
- const gchar *user, const gchar *password,
- const gchar *workstation)
-{
- GByteArray *message;
- guchar hash[21], lm_resp[24], nt_resp[24];
-
- if (!workstation)
- workstation = "";
-
- message = g_byte_array_new ();
-
- ntlm_lanmanager_hash (password, (gchar *) hash);
- ntlm_calc_response (hash, (guchar *) nonce, lm_resp);
- ntlm_nt_hash (password, (gchar *) hash);
- ntlm_calc_response (hash, (guchar *) nonce, nt_resp);
-
- g_byte_array_set_size (message, NTLM_RESPONSE_BASE_SIZE);
- memset (message->data, 0, NTLM_RESPONSE_BASE_SIZE);
- memcpy (message->data, NTLM_RESPONSE_MESSAGE_HEADER,
- sizeof (NTLM_RESPONSE_MESSAGE_HEADER));
-
- ntlm_set_string (message, NTLM_RESPONSE_DOMAIN_OFFSET,
- domain, strlen (domain));
- ntlm_set_string (message, NTLM_RESPONSE_USER_OFFSET,
- user, strlen (user));
- ntlm_set_string (message, NTLM_RESPONSE_WORKSTATION_OFFSET,
- workstation, strlen (workstation));
- ntlm_set_string (message, NTLM_RESPONSE_LM_RESP_OFFSET,
- (gchar *) lm_resp, sizeof (lm_resp));
- ntlm_set_string (message, NTLM_RESPONSE_NT_RESP_OFFSET,
- (gchar *) nt_resp, sizeof (nt_resp));
-
- return message;
-}
-
-static void
-setup_schedule (const guchar *key_56, XNTLM_DES_KS ks)
-{
- guchar key[8];
- gint i, c, bit;
-
- key[0] = (key_56[0]);
- key[1] = (key_56[1] >> 1) | ((key_56[0] << 7) & 0xFF);
- key[2] = (key_56[2] >> 2) | ((key_56[1] << 6) & 0xFF);
- key[3] = (key_56[3] >> 3) | ((key_56[2] << 5) & 0xFF);
- key[4] = (key_56[4] >> 4) | ((key_56[3] << 4) & 0xFF);
- key[5] = (key_56[5] >> 5) | ((key_56[4] << 3) & 0xFF);
- key[6] = (key_56[6] >> 6) | ((key_56[5] << 2) & 0xFF);
- key[7] = ((key_56[6] << 1) & 0xFF);
-
- /* Fix parity */
- for (i = 0; i < 8; i++) {
- for (c = bit = 0; bit < 8; bit++)
- if (key [i] & (1 << bit))
- c++;
- if (!(c & 1))
- key [i] ^= 0x01;
- }
-
- xntlm_deskey (ks, key, XNTLM_DES_ENCRYPT);
-}
-
-static guchar LM_PASSWORD_MAGIC[] = {
- 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25,
- 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25,
- 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static void
-ntlm_lanmanager_hash (const gchar *password, gchar hash[21])
-{
- guchar lm_password [15];
- XNTLM_DES_KS ks;
- guint i;
-
- for (i = 0; i < 14 && password [i]; i++)
- lm_password [i] = toupper ((guchar) password [i]);
-
- for (; i < sizeof (lm_password); i++)
- lm_password [i] = '\0';
-
- memcpy (hash, LM_PASSWORD_MAGIC, sizeof (LM_PASSWORD_MAGIC));
-
- setup_schedule (lm_password, ks);
- xntlm_des (ks, (guchar *) hash);
-
- setup_schedule (lm_password + 7, ks);
- xntlm_des (ks, (guchar *) hash + 8);
-}
-
-static void
-ntlm_nt_hash (const gchar *password, gchar hash[21])
-{
- guchar *buf, *p;
-
- p = buf = g_malloc (strlen (password) * 2);
-
- while (*password) {
- *p++ = *password++;
- *p++ = '\0';
- }
-
- xntlm_md4sum (buf, p - buf, (guchar *) hash);
- memset (hash + 16, 0, 5);
-
- g_free (buf);
-}
-
-static void
-ntlm_calc_response (const guchar key[21], const guchar plaintext[8],
- guchar results[24])
-{
- XNTLM_DES_KS ks;
-
- memcpy (results, plaintext, 8);
- memcpy (results + 8, plaintext, 8);
- memcpy (results + 16, plaintext, 8);
-
- setup_schedule (key, ks);
- xntlm_des (ks, results);
-
- setup_schedule (key + 7, ks);
- xntlm_des (ks, results + 8);
-
- setup_schedule (key + 14, ks);
- xntlm_des (ks, results + 16);
-}
-
+++ /dev/null
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* Copyright (C) 2001-2004 Novell, Inc. */
-
-#ifndef _XNTLM_H
-#define _XNTLM_H
-
-#include <glib.h>
-
-GByteArray *xntlm_negotiate (void);
-gboolean xntlm_parse_challenge (gpointer challenge, gint len, gchar **nonce,
- gchar **nt_domain, gchar **w2k_domain);
-GByteArray *xntlm_authenticate (const gchar *nonce, const gchar *domain,
- const gchar *user, const gchar *password,
- const gchar *workstation);
-
-#endif /* _XNTLM_H */