1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 /* Copyright (C) 2002-2004 Novell, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU Lesser General Public
7 * License as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
29 #include <sys/types.h>
31 #include <libxml/parser.h>
32 #include <libxml/tree.h>
33 #include <libxml/xmlmemory.h>
36 #include <glib/gstdio.h>
38 #include "libedataserver/e-source-list.h"
39 #include "libedataserver/e-data-server-util.h"
40 #include "libedataserver/e-xml-utils.h"
42 #include "e-folder-exchange.h"
45 #include "exchange-account.h"
46 #include "exchange-esource.h"
47 #include "exchange-hierarchy.h"
51 struct _EFolderExchangePrivate {
52 ExchangeHierarchy *hier;
53 char *internal_uri, *permanent_uri;
54 char *outlook_class, *storage_dir;
56 long long int folder_size;
57 gboolean has_subfolders;
61 #define PARENT_TYPE E_TYPE_FOLDER
62 static EFolderClass *parent_class = NULL;
64 #define EF_CLASS(hier) (E_FOLDER_CLASS (G_OBJECT_GET_CLASS (hier)))
66 static void dispose (GObject *object);
67 static void finalize (GObject *object);
70 class_init (GObjectClass *object_class)
72 parent_class = g_type_class_ref (PARENT_TYPE);
75 object_class->dispose = dispose;
76 object_class->finalize = finalize;
80 init (GObject *object)
82 EFolderExchange *folder = E_FOLDER_EXCHANGE (object);
84 folder->priv = g_new0 (EFolderExchangePrivate, 1);
85 folder->priv->rescan_tree = TRUE;
89 dispose (GObject *object)
91 EFolderExchange *folder = E_FOLDER_EXCHANGE (object);
93 if (folder->priv->hier) {
94 g_object_unref (folder->priv->hier);
95 folder->priv->hier = NULL;
98 G_OBJECT_CLASS (parent_class)->dispose (object);
102 finalize (GObject *object)
104 EFolderExchange *folder = E_FOLDER_EXCHANGE (object);
106 g_free (folder->priv->internal_uri);
107 g_free (folder->priv->permanent_uri);
108 g_free (folder->priv->outlook_class);
109 g_free (folder->priv->storage_dir);
110 g_free (folder->priv->path);
111 g_free (folder->priv);
113 G_OBJECT_CLASS (parent_class)->finalize (object);
116 E2K_MAKE_TYPE (e_folder_exchange, EFolderExchange, class_init, init, PARENT_TYPE)
119 sanitize_path (const char *path)
122 char *new_path = NULL;
125 return g_strdup(""); /* ??? or NULL? */
127 comps = g_strsplit (path, ";", 2);
129 new_path = g_strdup_printf ("%s%s", comps[0], comps[1]);
131 new_path = g_strdup (comps[0]);
140 * e_folder_exchange_new:
141 * @hier: the #ExchangeHierarchy containing the new folder
142 * @name: the display name of the folder
143 * @type: the Evolution type of the folder (eg, "mail")
144 * @outlook_class: the Outlook IPM class of the folder (eg, "IPM.Note")
145 * @physical_uri: the "exchange:" URI of the folder
146 * @internal_uri: the "http:" URI of the folder
148 * Return value: a new #EFolderExchange
151 e_folder_exchange_new (ExchangeHierarchy *hier, const char *name,
152 const char *type, const char *outlook_class,
153 const char *physical_uri, const char *internal_uri)
155 EFolderExchange *efe;
157 char *sanitized_path;
159 g_return_val_if_fail (EXCHANGE_IS_HIERARCHY (hier), NULL);
160 g_return_val_if_fail (name != NULL, NULL);
161 g_return_val_if_fail (type != NULL, NULL);
162 g_return_val_if_fail (physical_uri != NULL, NULL);
163 g_return_val_if_fail (internal_uri != NULL, NULL);
165 d(g_print ("e_folder_exchange_new: name=[%s], type=[%s], internal_uri=[%s], physical_uri=[%s]\n",
166 name, type, internal_uri, physical_uri));
168 efe = g_object_new (E_TYPE_FOLDER_EXCHANGE, NULL);
171 e_folder_construct (ef, name, type, "");
173 efe->priv->hier = hier;
176 efe->priv->internal_uri = g_strdup (internal_uri);
177 e_folder_set_physical_uri (ef, physical_uri);
179 sanitized_path = sanitize_path (e2k_uri_path (physical_uri));
180 e2k_uri_decode (sanitized_path);
181 efe->priv->path = sanitized_path;
182 d(g_print ("e_folder_exchange_new: sanitized=[%s]\n", sanitized_path));
184 efe->priv->outlook_class = g_strdup (outlook_class);
187 if (hier->type == EXCHANGE_HIERARCHY_PERSONAL ||
188 hier->type == EXCHANGE_HIERARCHY_FAVORITES) {
190 if ((strcmp (type, "calendar") == 0) ||
191 (strcmp (type, "calendar/public") == 0)) {
192 add_folder_esource (hier->account,
193 EXCHANGE_CALENDAR_FOLDER,
197 else if ((strcmp (type, "tasks") == 0) ||
198 (strcmp (type, "tasks/public") == 0)) {
199 add_folder_esource (hier->account,
200 EXCHANGE_TASKS_FOLDER,
204 else if ((strcmp (type, "contacts") == 0) ||
205 (strcmp (type, "contacts/public") == 0)) {
206 add_folder_esource (hier->account,
207 EXCHANGE_CONTACTS_FOLDER,
216 * e_folder_exchange_get_internal_uri:
217 * @folder: an #EFolderExchange
219 * Returns the folder's internal (http/https) URI. The caller
220 * should not cache this value, since it may change if the server
221 * sends a redirect when we try to use it.
223 * Return value: @folder's internal (http/https) URI
226 e_folder_exchange_get_internal_uri (EFolder *folder)
228 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
230 return E_FOLDER_EXCHANGE (folder)->priv->internal_uri;
234 * e_folder_exchange_set_internal_uri:
235 * @folder: an #EFolderExchange
236 * @internal_uri: new internal_uri value
238 * Updates @folder's internal URI to reflect a redirection response
242 e_folder_exchange_set_internal_uri (EFolder *folder, const char *internal_uri)
244 EFolderExchange *efe;
246 g_return_if_fail (E_IS_FOLDER_EXCHANGE (folder));
247 g_return_if_fail (internal_uri != NULL);
249 efe = E_FOLDER_EXCHANGE (folder);
250 g_free (efe->priv->internal_uri);
251 efe->priv->internal_uri = g_strdup (internal_uri);
255 * e_folder_exchange_get_path:
256 * @folder: an #EFolderExchange
258 * Return value: @folder's path within its Evolution storage
261 e_folder_exchange_get_path (EFolder *folder)
263 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
265 return E_FOLDER_EXCHANGE (folder)->priv->path;
269 * e_folder_exchange_get_permanent_uri:
270 * @folder: an #EFolderExchange
272 * Returns the folder's permanent URI. See docs/entryids for more
275 * Return value: @folder's permanent URI
278 e_folder_exchange_get_permanent_uri (EFolder *folder)
280 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
282 return E_FOLDER_EXCHANGE (folder)->priv->permanent_uri;
286 * e_folder_exchange_set_permanent_uri:
287 * @folder: an #EFolderExchange
288 * @permanent_uri: permanent_uri value
290 * Sets @folder's permanent URI (which must, for obvious reasons, have
291 * previously been unset).
294 e_folder_exchange_set_permanent_uri (EFolder *folder, const char *permanent_uri)
296 EFolderExchange *efe;
298 g_return_if_fail (E_IS_FOLDER_EXCHANGE (folder));
300 efe = E_FOLDER_EXCHANGE (folder);
301 g_return_if_fail (efe->priv->permanent_uri == NULL && permanent_uri != NULL);
303 efe->priv->permanent_uri = g_strdup (permanent_uri);
307 * e_folder_exchange_get_folder_size:
308 * @folder: an #EFolderExchange
310 * Returns the folder's size. See docs/entryids for more
313 * Return value: @folder's size
316 e_folder_exchange_get_folder_size (EFolder *folder)
318 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), -1);
320 return E_FOLDER_EXCHANGE (folder)->priv->folder_size;
324 * e_folder_exchange_set_folder_size:
325 * @folder: an #EFolderExchange
326 * @folder_size: folder size
328 * Sets @folder's folder_size
331 e_folder_exchange_set_folder_size (EFolder *folder, long long int folder_size)
333 EFolderExchange *efe;
335 g_return_if_fail (E_IS_FOLDER_EXCHANGE (folder));
337 efe = E_FOLDER_EXCHANGE (folder);
339 efe->priv->folder_size = folder_size;
344 * e_folder_exchange_get_has_subfolders:
345 * @folder: an #EFolderExchange
347 * Return value: whether or not @folder has subfolders
350 e_folder_exchange_get_has_subfolders (EFolder *folder)
352 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), FALSE);
354 return E_FOLDER_EXCHANGE (folder)->priv->has_subfolders;
358 * e_folder_exchange_set_has_subfolders
359 * @folder: an #EFolderExchange
360 * @has_subfolders: whether or not @folder has subfolders
362 * Sets @folder's has_subfolders flag.
365 e_folder_exchange_set_has_subfolders (EFolder *folder,
366 gboolean has_subfolders)
368 g_return_if_fail (E_IS_FOLDER_EXCHANGE (folder));
370 E_FOLDER_EXCHANGE (folder)->priv->has_subfolders = has_subfolders;
374 * e_folder_exchange_get_rescan_tree:
375 * @folder: an #EFolderExchange
377 * Return value: whether or not to rescan @folder tree
380 e_folder_exchange_get_rescan_tree (EFolder *folder)
382 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), FALSE);
384 return E_FOLDER_EXCHANGE (folder)->priv->rescan_tree;
388 * e_folder_exchange_set_rescan_tree
389 * @folder: an #EFolderExchange
390 * @rescan_tree: whether or not @folder needs to be rescanned
392 * Sets @folder's has_subfolders flag.
395 e_folder_exchange_set_rescan_tree (EFolder *folder,
396 gboolean rescan_tree)
398 g_return_if_fail (E_IS_FOLDER_EXCHANGE (folder));
400 E_FOLDER_EXCHANGE (folder)->priv->rescan_tree = rescan_tree;
404 * e_folder_exchange_get_outlook_class:
405 * @folder: an #EFolderExchange
407 * Return value: @folder's Outlook IPM class
410 e_folder_exchange_get_outlook_class (EFolder *folder)
412 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
414 return E_FOLDER_EXCHANGE (folder)->priv->outlook_class;
418 * e_folder_exchange_get_hierarchy
419 * @folder: an #EFolderExchange
421 * Return value: @folder's hierarchy
424 e_folder_exchange_get_hierarchy (EFolder *folder)
426 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
428 return E_FOLDER_EXCHANGE (folder)->priv->hier;
432 * e_folder_exchange_get_storage_file:
433 * @folder: an #EFolderExchange
434 * @filename: name of a file
436 * This returns a unique filename ending in @filename in the local
437 * storage space reserved for @folder.
439 * Return value: the full filename, which must be freed.
442 e_folder_exchange_get_storage_file (EFolder *folder, const char *filename)
444 EFolderExchange *efe;
447 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
449 efe = (EFolderExchange *)folder;
451 if (!efe->priv->storage_dir) {
452 efe->priv->storage_dir = e_path_to_physical (
453 efe->priv->hier->account->storage_dir,
455 g_mkdir_with_parents (efe->priv->storage_dir, 0755);
458 path = g_build_filename (efe->priv->storage_dir, filename, NULL);
464 * e_folder_exchange_save_to_file:
465 * @folder: the folder
466 * @filename: a filename
468 * Saves all relevant information about @folder to @filename.
470 * Return value: success or failure
473 e_folder_exchange_save_to_file (EFolder *folder, const char *filename)
477 const char *name, *type, *outlook_class;
478 const char *physical_uri, *internal_uri, *permanent_uri;
483 name = e_folder_get_name (folder);
484 type = e_folder_get_type_string (folder);
485 outlook_class = e_folder_exchange_get_outlook_class (folder);
486 physical_uri = e_folder_get_physical_uri (folder);
487 internal_uri = e_folder_exchange_get_internal_uri (folder);
488 permanent_uri = e_folder_exchange_get_permanent_uri (folder);
490 g_return_val_if_fail (name && type && physical_uri && internal_uri,
493 if ((fsize = e_folder_exchange_get_folder_size (folder)) >= 0)
494 folder_size = g_strdup_printf ("%llu", fsize);
498 doc = xmlNewDoc ("1.0");
499 root = xmlNewDocNode (doc, NULL, "connector-folder", NULL);
500 xmlNewProp (root, "version", "1");
501 xmlDocSetRootElement (doc, root);
503 xmlNewChild (root, NULL, "displayname", name);
504 xmlNewChild (root, NULL, "type", type);
505 xmlNewChild (root, NULL, "outlook_class", outlook_class);
506 xmlNewChild (root, NULL, "physical_uri", physical_uri);
507 xmlNewChild (root, NULL, "internal_uri", internal_uri);
508 xmlNewChild (root, NULL, "folder_size", folder_size);
510 xmlNewChild (root, NULL, "permanent_uri", permanent_uri);
512 status = e_xml_save_file (filename, doc);
519 g_free (folder_size);
525 * e_folder_exchange_new_from_file:
526 * @hier: the hierarchy to create the folder under
527 * @filename: a filename
529 * Loads information about a folder from a saved file.
531 * Return value: the folder, or %NULL on a failed load.
534 e_folder_exchange_new_from_file (ExchangeHierarchy *hier, const char *filename)
536 EFolder *folder = NULL;
538 xmlNode *root, *node;
539 char *version, *display_name = NULL;
540 char *type = NULL, *outlook_class = NULL;
541 char *physical_uri = NULL, *internal_uri = NULL;
542 char *permanent_uri = NULL;
543 char *folder_size = NULL;
545 doc = e_xml_parse_file (filename);
550 root = xmlDocGetRootElement (doc);
551 if (root == NULL || strcmp (root->name, "connector-folder") != 0) {
555 version = xmlGetProp (root, "version");
560 if (strcmp (version, "1") != 0) {
567 node = e_xml_get_child_by_name (root, "displayname");
570 display_name = xmlNodeGetContent (node);
572 node = e_xml_get_child_by_name (root, "type");
575 type = xmlNodeGetContent (node);
577 node = e_xml_get_child_by_name (root, "outlook_class");
580 outlook_class = xmlNodeGetContent (node);
582 node = e_xml_get_child_by_name (root, "physical_uri");
585 physical_uri = xmlNodeGetContent (node);
587 node = e_xml_get_child_by_name (root, "internal_uri");
590 internal_uri = xmlNodeGetContent (node);
592 if (!display_name || !type || !physical_uri || !internal_uri)
595 folder = e_folder_exchange_new (hier, display_name,
597 physical_uri, internal_uri);
599 node = e_xml_get_child_by_name (root, "permanent_uri");
601 permanent_uri = xmlNodeGetContent (node);
602 e_folder_exchange_set_permanent_uri (folder, permanent_uri);
605 node = e_xml_get_child_by_name (root, "folder_size");
607 folder_size = xmlNodeGetContent (node);
608 e_folder_exchange_set_folder_size (folder, atoi (folder_size));
612 xmlFree (display_name);
614 xmlFree (outlook_class);
615 xmlFree (physical_uri);
616 xmlFree (internal_uri);
617 xmlFree (permanent_uri);
618 xmlFree (folder_size);
626 /* E2kContext wrappers */
627 #define E_FOLDER_EXCHANGE_CONTEXT(efe) (exchange_account_get_context (((EFolderExchange *)efe)->priv->hier->account))
628 #define E_FOLDER_EXCHANGE_URI(efe) (((EFolderExchange *)efe)->priv->internal_uri)
631 * e_folder_exchange_propfind:
632 * @folder: the folder
633 * @op: pointer to an #E2kOperation to use for cancellation
634 * @props: array of properties to find
635 * @nprops: length of @props
636 * @results: on return, the results
637 * @nresults: length of @results
639 * Performs a PROPFIND operation on @folder. This is a convenience
640 * wrapper around e2k_context_propfind(), qv.
642 * Return value: the HTTP status
645 e_folder_exchange_propfind (EFolder *folder, E2kOperation *op,
646 const char **props, int nprops,
647 E2kResult **results, int *nresults)
649 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), E2K_HTTP_MALFORMED);
651 return e2k_context_propfind (
652 E_FOLDER_EXCHANGE_CONTEXT (folder), op,
653 E_FOLDER_EXCHANGE_URI (folder),
654 props, nprops, results, nresults);
658 * e_folder_exchange_bpropfind_start:
659 * @folder: the folder
660 * @op: pointer to an #E2kOperation to use for cancellation
661 * @hrefs: array of URIs, relative to @folder
662 * @nhrefs: length of @hrefs
663 * @props: array of properties to find
664 * @nprops: length of @props
666 * Begins a BPROPFIND (bulk PROPFIND) operation on @folder for @hrefs.
667 * This is a convenience wrapper around e2k_context_bpropfind_start(),
670 * Return value: an iterator for getting the results
673 e_folder_exchange_bpropfind_start (EFolder *folder, E2kOperation *op,
674 const char **hrefs, int nhrefs,
675 const char **props, int nprops)
677 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
679 return e2k_context_bpropfind_start (
680 E_FOLDER_EXCHANGE_CONTEXT (folder), op,
681 E_FOLDER_EXCHANGE_URI (folder),
682 hrefs, nhrefs, props, nprops);
686 * e_folder_exchange_search_start:
687 * @folder: the folder
688 * @op: pointer to an #E2kOperation to use for cancellation
689 * @props: the properties to search for
690 * @nprops: size of @props array
691 * @rn: the search restriction
692 * @orderby: if non-%NULL, the field to sort the search results by
693 * @ascending: %TRUE for an ascending search, %FALSE for descending.
695 * Begins a SEARCH on the contents of @folder. This is a convenience
696 * wrapper around e2k_context_search_start(), qv.
698 * Return value: an iterator for returning the search results
701 e_folder_exchange_search_start (EFolder *folder, E2kOperation *op,
702 const char **props, int nprops,
703 E2kRestriction *rn, const char *orderby,
706 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
708 return e2k_context_search_start (
709 E_FOLDER_EXCHANGE_CONTEXT (folder), op,
710 E_FOLDER_EXCHANGE_URI (folder),
711 props, nprops, rn, orderby, ascending);
715 * e_folder_exchange_subscribe:
716 * @folder: the folder to subscribe to notifications on
717 * @type: the type of notification to subscribe to
718 * @min_interval: the minimum interval (in seconds) between
720 * @callback: the callback to call when a notification has been
722 * @user_data: data to pass to @callback.
724 * This subscribes to change notifications of the given @type on
725 * @folder. This is a convenience wrapper around
726 * e2k_context_subscribe(), qv.
729 e_folder_exchange_subscribe (EFolder *folder,
730 E2kContextChangeType type, int min_interval,
731 E2kContextChangeCallback callback,
734 g_return_if_fail (E_IS_FOLDER_EXCHANGE (folder));
736 e2k_context_subscribe (E_FOLDER_EXCHANGE_CONTEXT (folder),
737 E_FOLDER_EXCHANGE_URI (folder),
738 type, min_interval, callback, user_data);
742 * e_folder_exchange_unsubscribe:
743 * @folder: the folder to unsubscribe from
745 * Unsubscribes to all notifications on @folder. This is a convenience
746 * wrapper around e2k_context_unsubscribe(), qv.
749 e_folder_exchange_unsubscribe (EFolder *folder)
753 g_return_if_fail (E_IS_FOLDER_EXCHANGE (folder));
755 /* FIXME : This is a hack as of now. The free_folder in mail-stub
756 gets called when we are in offline and the context is NULL then. */
757 ctx = E_FOLDER_EXCHANGE_CONTEXT (folder);
759 e2k_context_unsubscribe (E_FOLDER_EXCHANGE_CONTEXT (folder),
760 E_FOLDER_EXCHANGE_URI (folder));
765 * e_folder_exchange_transfer_start:
766 * @source: the source folder
767 * @op: pointer to an #E2kOperation to use for cancellation
768 * @dest: the destination folder
769 * @source_hrefs: an array of hrefs to move, relative to @source_folder
770 * @delete_originals: whether or not to delete the original objects
772 * Starts a BMOVE or BCOPY (depending on @delete_originals) operation
773 * on @source. This is a convenience wrapper around
774 * e2k_context_transfer_start(), qv.
776 * Return value: the iterator for the results
779 e_folder_exchange_transfer_start (EFolder *source, E2kOperation *op,
780 EFolder *dest, GPtrArray *source_hrefs,
781 gboolean delete_originals)
783 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (source), NULL);
785 return e2k_context_transfer_start (E_FOLDER_EXCHANGE_CONTEXT (source), op,
786 E_FOLDER_EXCHANGE_URI (source),
787 E_FOLDER_EXCHANGE_URI (dest),
788 source_hrefs, delete_originals);
792 * e_folder_exchange_put_new:
793 * @folder: the folder to PUT the new item into
794 * @op: pointer to an #E2kOperation to use for cancellation
795 * @object_name: base name of the new object (not URI-encoded)
796 * @test_callback: callback to use to test possible object URIs
797 * @user_data: data for @test_callback
798 * @content_type: MIME Content-Type of the data
800 * @length: length of @body
801 * @location: if not %NULL, will contain the Location of the POSTed
803 * @repl_uid: if not %NULL, will contain the Repl-UID of the POSTed
806 * PUTs data into @folder with a new name based on @object_name. This
807 * is a convenience wrapper around e2k_context_put_new(), qv.
809 * Return value: the HTTP status
812 e_folder_exchange_put_new (EFolder *folder,
814 const char *object_name,
815 E2kContextTestCallback test_callback,
817 const char *content_type,
818 const char *body, int length,
819 char **location, char **repl_uid)
821 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), E2K_HTTP_MALFORMED);
823 return e2k_context_put_new (E_FOLDER_EXCHANGE_CONTEXT (folder), op,
824 E_FOLDER_EXCHANGE_URI (folder),
825 object_name, test_callback, user_data,
826 content_type, body, length,
831 * e_folder_exchange_proppatch_new:
832 * @folder: the folder to PROPPATCH a new object in
833 * @op: pointer to an #E2kOperation to use for cancellation
834 * @object_name: base name of the new object (not URI-encoded)
835 * @test_callback: callback to use to test possible object URIs
836 * @user_data: data for @test_callback
837 * @props: the properties to set/remove
838 * @location: if not %NULL, will contain the Location of the
839 * PROPPATCHed object on return
840 * @repl_uid: if not %NULL, will contain the Repl-UID of the
841 * PROPPATCHed object on return
843 * PROPPATCHes data into @folder with a new name based on
844 * @object_name. This is a convenience wrapper around
845 * e2k_context_proppatch_new(), qv.
847 * Return value: the HTTP status
850 e_folder_exchange_proppatch_new (EFolder *folder, E2kOperation *op,
851 const char *object_name,
852 E2kContextTestCallback test_callback,
854 E2kProperties *props,
855 char **location, char **repl_uid)
857 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), E2K_HTTP_MALFORMED);
859 return e2k_context_proppatch_new (E_FOLDER_EXCHANGE_CONTEXT (folder), op,
860 E_FOLDER_EXCHANGE_URI (folder),
862 test_callback, user_data,
868 * e_folder_exchange_bproppatch_start:
869 * @folder: the folder
870 * @op: pointer to an #E2kOperation to use for cancellation
871 * @hrefs: array of URIs, relative to @folder
872 * @nhrefs: length of @hrefs
873 * @props: the properties to set/remove
874 * @create: whether or not to create the objects if they do not exist
876 * Begins BPROPPATCHing @hrefs under @folder. This is a convenience
877 * wrapper around e2k_context_bproppatch_start(), qv.
879 * Return value: an iterator for getting the results of the BPROPPATCH
882 e_folder_exchange_bproppatch_start (EFolder *folder, E2kOperation *op,
883 const char **hrefs, int nhrefs,
884 E2kProperties *props, gboolean create)
886 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
888 return e2k_context_bproppatch_start (E_FOLDER_EXCHANGE_CONTEXT (folder), op,
889 E_FOLDER_EXCHANGE_URI (folder),
890 hrefs, nhrefs, props, create);
894 * e_folder_exchange_bdelete_start:
895 * @folder: the folder
896 * @op: pointer to an #E2kOperation to use for cancellation
897 * @hrefs: array of URIs, relative to @folder, to delete
898 * @nhrefs: length of @hrefs
900 * Begins a BDELETE (bulk DELETE) operation in @folder for @hrefs.
901 * This is a convenience wrapper around e2k_context_bdelete_start(),
904 * Return value: an iterator for returning the results
907 e_folder_exchange_bdelete_start (EFolder *folder, E2kOperation *op,
908 const char **hrefs, int nhrefs)
910 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), NULL);
912 return e2k_context_bdelete_start (E_FOLDER_EXCHANGE_CONTEXT (folder), op,
913 E_FOLDER_EXCHANGE_URI (folder),
918 * e_folder_exchange_mkcol:
919 * @folder: the folder to create
920 * @op: pointer to an #E2kOperation to use for cancellation
921 * @props: properties to set on the new folder, or %NULL
922 * @permanent_url: if not %NULL, will contain the permanent URL of the
923 * new folder on return
925 * Performs a MKCOL operation to create @folder, with optional
926 * additional properties. This is a convenience wrapper around
927 * e2k_context_mkcol(), qv.
929 * Return value: the HTTP status
932 e_folder_exchange_mkcol (EFolder *folder, E2kOperation *op,
933 E2kProperties *props,
934 char **permanent_url)
936 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), E2K_HTTP_MALFORMED);
938 return e2k_context_mkcol (E_FOLDER_EXCHANGE_CONTEXT (folder), op,
939 E_FOLDER_EXCHANGE_URI (folder),
940 props, permanent_url);
944 * e_folder_exchange_delete:
945 * @folder: the folder to delete
946 * @op: pointer to an #E2kOperation to use for cancellation
948 * Attempts to DELETE @folder. This is a convenience wrapper around
949 * e2k_context_delete(), qv.
951 * Return value: the HTTP status
954 e_folder_exchange_delete (EFolder *folder, E2kOperation *op)
956 ExchangeHierarchy *hier;
957 const char *folder_type, *physical_uri;
959 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (folder), E2K_HTTP_MALFORMED);
960 /* remove ESources */
961 hier = e_folder_exchange_get_hierarchy (folder);
963 if (hier->type == EXCHANGE_HIERARCHY_PERSONAL ||
964 hier->type == EXCHANGE_HIERARCHY_FAVORITES) {
965 folder_type = e_folder_get_type_string (folder);
966 physical_uri = e_folder_get_physical_uri (folder);
968 if ((strcmp (folder_type, "calendar") == 0) ||
969 (strcmp (folder_type, "calendar/public") == 0)) {
970 remove_folder_esource (hier->account,
971 EXCHANGE_CALENDAR_FOLDER,
974 else if ((strcmp (folder_type, "tasks") == 0) ||
975 (strcmp (folder_type, "tasks/public") == 0)) {
976 remove_folder_esource (hier->account,
977 EXCHANGE_TASKS_FOLDER,
980 else if ((strcmp (folder_type, "contacts") == 0) ||
981 (strcmp (folder_type, "contacts/public") == 0)) {
982 remove_folder_esource (hier->account,
983 EXCHANGE_CONTACTS_FOLDER,
988 return e2k_context_delete (E_FOLDER_EXCHANGE_CONTEXT (folder), op,
989 E_FOLDER_EXCHANGE_URI (folder));
993 * e_folder_exchange_transfer_dir:
994 * @source: source folder
995 * @op: pointer to an #E2kOperation to use for cancellation
996 * @dest: destination folder
997 * @delete_original: whether or not to delete the original folder
998 * @permanent_url: if not %NULL, will contain the permanent URL of the
999 * new folder on return
1001 * Performs a MOVE or COPY (depending on @delete_original) operation
1002 * on @source. This is a convenience wrapper around
1003 * e2k_context_transfer_dir(), qv.
1005 * Return value: the HTTP status
1008 e_folder_exchange_transfer_dir (EFolder *source, E2kOperation *op,
1009 EFolder *dest, gboolean delete_original,
1010 char **permanent_url)
1012 g_return_val_if_fail (E_IS_FOLDER_EXCHANGE (source), E2K_HTTP_MALFORMED);
1014 return e2k_context_transfer_dir (E_FOLDER_EXCHANGE_CONTEXT (source), op,
1015 E_FOLDER_EXCHANGE_URI (source),
1016 E_FOLDER_EXCHANGE_URI (dest),
1017 delete_original, permanent_url);