~ubuntu-branches/ubuntu/breezy/evolution-data-server/breezy

« back to all changes in this revision

Viewing changes to servers/exchange/storage/exchange-hierarchy-foreign.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-10-10 11:30:56 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20051010113056-rb4vj4kbs8yxft85
Tags: 1.4.1-0ubuntu3
* debian/patches/camel-imap-store.c.patch:
  - Ubuntu 17465: apply patch from
  http://bugzilla.gnome.org/attachment.cgi?id=53234&action=view
  (additional NULL pointer check)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 
2
 
 
3
/* Copyright (C) 2002-2004 Novell, Inc.
 
4
 *
 
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.
 
8
 *
 
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.
 
13
 *
 
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., 59 Temple Place - Suite 330,
 
17
 * Boston, MA 02111-1307, USA.
 
18
 */
 
19
 
 
20
/* ExchangeHierarchyForeign: class for a hierarchy consisting of a
 
21
 * selected subset of folders from another user's mailbox.
 
22
 */
 
23
 
 
24
#ifdef HAVE_CONFIG_H
 
25
#include <config.h>
 
26
#endif
 
27
 
 
28
#include "exchange-hierarchy-foreign.h"
 
29
#include "exchange-account.h"
 
30
#include "e-folder-exchange.h"
 
31
#include "e2k-propnames.h"
 
32
#include "e2k-uri.h"
 
33
#include "e2k-utils.h"
 
34
#include "exchange-esource.h"
 
35
#include "exchange-types.h"
 
36
#include "e2k-types.h"
 
37
 
 
38
#include <libedataserver/e-xml-hash-utils.h>
 
39
#include <libedataserver/e-source-list.h>
 
40
 
 
41
#include <stdlib.h>
 
42
#include <string.h>
 
43
#include <unistd.h>
 
44
 
 
45
struct _ExchangeHierarchyForeignPrivate {
 
46
        GMutex *hide_private_lock;
 
47
        gboolean checked_hide_private;
 
48
};
 
49
 
 
50
extern const char *exchange_localfreebusy_path;
 
51
 
 
52
#define PARENT_TYPE EXCHANGE_TYPE_HIERARCHY_SOMEDAV
 
53
static ExchangeHierarchySomeDAVClass *parent_class = NULL;
 
54
 
 
55
static GPtrArray *get_hrefs (ExchangeHierarchySomeDAV *hsd);
 
56
static ExchangeAccountFolderResult create_folder (ExchangeHierarchy *hier,
 
57
                                                  EFolder *parent,
 
58
                                                  const char *name,
 
59
                                                  const char *type);
 
60
static ExchangeAccountFolderResult remove_folder (ExchangeHierarchy *hier,
 
61
                                                  EFolder *folder);
 
62
static ExchangeAccountFolderResult scan_subtree (ExchangeHierarchy *hier,
 
63
                                                 EFolder *folder,
 
64
                                                 gboolean offline);
 
65
static void finalize (GObject *object);
 
66
 
 
67
static void
 
68
class_init (GObjectClass *object_class)
 
69
{
 
70
        ExchangeHierarchyClass *hierarchy_class =
 
71
                EXCHANGE_HIERARCHY_CLASS (object_class);
 
72
        ExchangeHierarchySomeDAVClass *somedav_class =
 
73
                EXCHANGE_HIERARCHY_SOMEDAV_CLASS (object_class);
 
74
 
 
75
        parent_class = g_type_class_ref (PARENT_TYPE);
 
76
 
 
77
        /* virtual method override */
 
78
        object_class->finalize = finalize;
 
79
 
 
80
        hierarchy_class->create_folder  = create_folder;
 
81
        hierarchy_class->remove_folder  = remove_folder;
 
82
        hierarchy_class->scan_subtree   = scan_subtree;
 
83
 
 
84
        somedav_class->get_hrefs        = get_hrefs;
 
85
}
 
86
 
 
87
static void
 
88
init (GObject *object)
 
89
{
 
90
        ExchangeHierarchyForeign *hfor = EXCHANGE_HIERARCHY_FOREIGN (object);
 
91
        ExchangeHierarchy *hier = EXCHANGE_HIERARCHY (object);
 
92
 
 
93
        hfor->priv = g_new0 (ExchangeHierarchyForeignPrivate, 1);
 
94
        hfor->priv->hide_private_lock = g_mutex_new ();
 
95
        hier->hide_private_items = TRUE;
 
96
}
 
97
 
 
98
static void
 
99
finalize (GObject *object)
 
100
{
 
101
        ExchangeHierarchyForeign *hfor = EXCHANGE_HIERARCHY_FOREIGN (object);
 
102
 
 
103
        g_mutex_free (hfor->priv->hide_private_lock);
 
104
        g_free (hfor->priv);
 
105
 
 
106
        G_OBJECT_CLASS (parent_class)->finalize (object);
 
107
}
 
108
 
 
109
E2K_MAKE_TYPE (exchange_hierarchy_foreign, ExchangeHierarchyForeign, class_init, init, PARENT_TYPE)
 
110
 
 
111
static const char *privacy_props[] = {
 
112
        PR_DELEGATES_ENTRYIDS,
 
113
        PR_DELEGATES_SEE_PRIVATE,
 
114
};
 
115
static const int n_privacy_props = sizeof (privacy_props) / sizeof (privacy_props[0]);
 
116
 
 
117
static void
 
118
check_hide_private (ExchangeHierarchy *hier)
 
119
{
 
120
        ExchangeHierarchyForeign *hfor = EXCHANGE_HIERARCHY_FOREIGN (hier);
 
121
        E2kContext *ctx;
 
122
        E2kHTTPStatus status;
 
123
        E2kResult *results;
 
124
        int nresults, i;
 
125
        GPtrArray *entryids, *privflags;
 
126
        GByteArray *entryid;
 
127
        const char *my_dn, *delegate_dn;
 
128
        char *uri;
 
129
 
 
130
        g_mutex_lock (hfor->priv->hide_private_lock);
 
131
 
 
132
        if (hfor->priv->checked_hide_private) {
 
133
                g_mutex_unlock (hfor->priv->hide_private_lock);
 
134
                return;
 
135
        }
 
136
 
 
137
        uri = e2k_uri_concat (hier->account->home_uri,
 
138
                              "NON_IPM_SUBTREE/Freebusy%20Data/LocalFreebusy.EML");
 
139
        ctx = exchange_account_get_context (hier->account);
 
140
 
 
141
        status = e2k_context_propfind (ctx, NULL, uri,
 
142
                                       privacy_props, n_privacy_props,
 
143
                                       &results, &nresults);
 
144
        g_free (uri);
 
145
 
 
146
        hfor->priv->checked_hide_private = TRUE;
 
147
 
 
148
        if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status) || nresults == 0) {
 
149
                g_mutex_unlock (hfor->priv->hide_private_lock);
 
150
                return;
 
151
        }
 
152
        if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (results[0].status) ||
 
153
            !results[0].props || nresults > 1) {
 
154
                e2k_results_free (results, nresults);
 
155
                g_mutex_unlock (hfor->priv->hide_private_lock);
 
156
                return;
 
157
        }
 
158
 
 
159
        entryids  = e2k_properties_get_prop (results[0].props,
 
160
                                             PR_DELEGATES_ENTRYIDS);
 
161
        privflags = e2k_properties_get_prop (results[0].props,
 
162
                                             PR_DELEGATES_SEE_PRIVATE);
 
163
        if (entryids && privflags) {
 
164
                my_dn = hier->account->legacy_exchange_dn;
 
165
                for (i = 0; i < entryids->len && i < privflags->len; i++) {
 
166
                        entryid = entryids->pdata[i];
 
167
                        delegate_dn = e2k_entryid_to_dn (entryid);
 
168
 
 
169
                        if (delegate_dn &&
 
170
                            !g_ascii_strcasecmp (delegate_dn, my_dn) &&
 
171
                            privflags->pdata[i] &&
 
172
                            atoi (privflags->pdata[i]))
 
173
                                hier->hide_private_items = FALSE;
 
174
                        break;
 
175
                }
 
176
        }
 
177
 
 
178
        e2k_results_free (results, nresults);
 
179
        g_mutex_unlock (hfor->priv->hide_private_lock);
 
180
}
 
181
 
 
182
static void
 
183
remove_all_cb (ExchangeHierarchy *hier, EFolder *folder, gpointer user_data)
 
184
{
 
185
        exchange_hierarchy_removed_folder (hier, folder);
 
186
}
 
187
 
 
188
static void
 
189
hierarchy_foreign_cleanup (ExchangeHierarchy *hier)
 
190
{
 
191
        char *mf_path;
 
192
 
 
193
        exchange_hierarchy_webdav_offline_scan_subtree (hier, remove_all_cb,
 
194
                                                        NULL);
 
195
 
 
196
        mf_path = e_folder_exchange_get_storage_file (hier->toplevel, "hierarchy.xml");
 
197
        unlink (mf_path);
 
198
        g_free (mf_path);
 
199
 
 
200
        exchange_hierarchy_removed_folder (hier, hier->toplevel);
 
201
}
 
202
 
 
203
static const char *folder_props[] = {
 
204
        E2K_PR_EXCHANGE_FOLDER_CLASS,
 
205
        E2K_PR_HTTPMAIL_UNREAD_COUNT,
 
206
        E2K_PR_DAV_DISPLAY_NAME,
 
207
        PR_ACCESS
 
208
};
 
209
static const int n_folder_props = sizeof (folder_props) / sizeof (folder_props[0]);
 
210
 
 
211
static ExchangeAccountFolderResult
 
212
find_folder (ExchangeHierarchy *hier, const char *uri, EFolder **folder_out)
 
213
{
 
214
        ExchangeHierarchyWebDAV *hwd = EXCHANGE_HIERARCHY_WEBDAV (hier);
 
215
        E2kContext *ctx = exchange_account_get_context (hier->account);
 
216
        E2kHTTPStatus status;
 
217
        E2kResult *results;
 
218
        int nresults;
 
219
        EFolder *folder;
 
220
        const char *access;
 
221
        int offline;
 
222
 
 
223
        status = e2k_context_propfind (ctx, NULL, uri,
 
224
                                       folder_props, n_folder_props,
 
225
                                       &results, &nresults);
 
226
        if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) 
 
227
                return exchange_hierarchy_webdav_status_to_folder_result (status);
 
228
        if (nresults == 0)
 
229
                return EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
 
230
 
 
231
        access = e2k_properties_get_prop (results[0].props, PR_ACCESS);
 
232
        if (!access || !atoi (access))
 
233
                return EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED;
 
234
 
 
235
        folder = exchange_hierarchy_webdav_parse_folder (hwd, hier->toplevel,
 
236
                                                         &results[0]);
 
237
        e2k_results_free (results, nresults);
 
238
 
 
239
        if (!folder)
 
240
                return EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST;
 
241
 
 
242
        exchange_hierarchy_new_folder (hier, folder);
 
243
 
 
244
        if (folder_out)
 
245
                *folder_out = folder;
 
246
        else
 
247
                g_object_unref (folder);
 
248
        return EXCHANGE_ACCOUNT_FOLDER_OK;
 
249
}
 
250
 
 
251
static struct {
 
252
        const char *name, *prop;
 
253
} std_folders[] = {
 
254
        { N_("Calendar"),       E2K_PR_STD_FOLDER_CALENDAR },
 
255
        { N_("Contacts"),       E2K_PR_STD_FOLDER_CONTACTS },
 
256
        { N_("Deleted Items"),  E2K_PR_STD_FOLDER_DELETED_ITEMS },
 
257
        { N_("Drafts"),         E2K_PR_STD_FOLDER_DRAFTS },
 
258
        { N_("Inbox"),          E2K_PR_STD_FOLDER_INBOX },
 
259
        { N_("Journal"),        E2K_PR_STD_FOLDER_JOURNAL },
 
260
        { N_("Notes"),          E2K_PR_STD_FOLDER_NOTES },
 
261
        { N_("Outbox"),         E2K_PR_STD_FOLDER_OUTBOX },
 
262
        { N_("Sent Items"),     E2K_PR_STD_FOLDER_SENT_ITEMS },
 
263
        { N_("Tasks"),          E2K_PR_STD_FOLDER_TASKS }
 
264
};
 
265
const static int n_std_folders = sizeof (std_folders) / sizeof (std_folders[0]);
 
266
static ExchangeAccountFolderResult
 
267
create_internal (ExchangeHierarchy *hier, EFolder *parent,
 
268
                 const char *name, const char *type, EFolder **folder_out)
 
269
{
 
270
        ExchangeAccountFolderResult result;
 
271
        char *literal_uri = NULL, *standard_uri = NULL;
 
272
        const char *home_uri;
 
273
        int i;
 
274
        int offline;
 
275
 
 
276
        /* For now, no nesting */
 
277
        if (parent != hier->toplevel || strchr (name + 1, '/'))
 
278
                return EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR;
 
279
 
 
280
        check_hide_private (hier);
 
281
 
 
282
        home_uri = e_folder_exchange_get_internal_uri (hier->toplevel);
 
283
        literal_uri = e2k_uri_concat (home_uri, name);
 
284
        if (exchange_account_get_folder (hier->account, literal_uri)) {
 
285
                g_free (literal_uri);
 
286
                if (exchange_hierarchy_is_empty (hier))
 
287
                        hierarchy_foreign_cleanup (hier);
 
288
                return EXCHANGE_ACCOUNT_FOLDER_ALREADY_EXISTS;
 
289
        }
 
290
 
 
291
        for (i = 0; i < n_std_folders; i++) {
 
292
                if (g_ascii_strcasecmp (std_folders[i].name, name) != 0 &&
 
293
                    g_utf8_collate (_(std_folders[i].name), name) != 0)
 
294
                        continue;
 
295
 
 
296
                standard_uri = exchange_account_get_standard_uri_for (
 
297
                        hier->account, home_uri, std_folders[i].prop);
 
298
                if (!standard_uri)
 
299
                        break;
 
300
                if (!strcmp (literal_uri, standard_uri)) {
 
301
                        g_free (standard_uri);
 
302
                        standard_uri = NULL;
 
303
                        break;
 
304
                }
 
305
 
 
306
                if (exchange_account_get_folder (hier->account, standard_uri)) {
 
307
                        g_free (standard_uri);
 
308
                        g_free (literal_uri);
 
309
                        if (exchange_hierarchy_is_empty (hier))
 
310
                                hierarchy_foreign_cleanup (hier);
 
311
                        return EXCHANGE_ACCOUNT_FOLDER_ALREADY_EXISTS;
 
312
                }
 
313
 
 
314
                break;
 
315
        }
 
316
 
 
317
        result = find_folder (hier, literal_uri, folder_out);
 
318
        if (result == EXCHANGE_ACCOUNT_FOLDER_DOES_NOT_EXIST && standard_uri)
 
319
                result = find_folder (hier, standard_uri, folder_out);
 
320
 
 
321
        g_free (literal_uri);
 
322
        g_free (standard_uri);
 
323
 
 
324
        /* If the hierarchy is now empty, then we must have just been
 
325
         * created but then the add failed. So remove it again.
 
326
         */
 
327
        if (exchange_hierarchy_is_empty (hier))
 
328
                hierarchy_foreign_cleanup (hier);
 
329
 
 
330
        return result;
 
331
}
 
332
 
 
333
 
 
334
static ExchangeAccountFolderResult
 
335
create_folder (ExchangeHierarchy *hier, EFolder *parent,
 
336
               const char *name, const char *type)
 
337
{
 
338
        return create_internal (hier, parent, name, type, NULL);
 
339
}
 
340
 
 
341
static ExchangeAccountFolderResult
 
342
remove_folder (ExchangeHierarchy *hier, EFolder *folder)
 
343
{
 
344
        const char *folder_type, *physical_uri;
 
345
 
 
346
        /* Temp Fix for remove fav folders. see #59168 */
 
347
        /* remove ESources */
 
348
        folder_type = e_folder_get_type_string (folder);
 
349
        physical_uri = e_folder_get_physical_uri (folder);
 
350
 
 
351
        if (strcmp (folder_type, "calendar") == 0) {
 
352
                remove_folder_esource (hier->account,
 
353
                                       EXCHANGE_CALENDAR_FOLDER,
 
354
                                       physical_uri);
 
355
        }
 
356
        else if (strcmp (folder_type, "tasks") == 0) {
 
357
                remove_folder_esource (hier->account,
 
358
                                       EXCHANGE_TASKS_FOLDER,
 
359
                                       physical_uri);
 
360
        }
 
361
        else if (strcmp (folder_type, "contacts") == 0) {
 
362
                remove_folder_esource (hier->account,
 
363
                                       EXCHANGE_CONTACTS_FOLDER,
 
364
                                       physical_uri);
 
365
        }
 
366
        if (folder != hier->toplevel)
 
367
                exchange_hierarchy_removed_folder (hier, folder);
 
368
 
 
369
        if (folder == hier->toplevel || exchange_hierarchy_is_empty (hier))
 
370
                hierarchy_foreign_cleanup (hier);
 
371
 
 
372
        return EXCHANGE_ACCOUNT_FOLDER_OK;
 
373
}
 
374
 
 
375
static ExchangeAccountFolderResult
 
376
scan_subtree (ExchangeHierarchy *hier, EFolder *folder, gboolean offline)
 
377
{
 
378
        ExchangeAccountFolderResult folder_result;
 
379
 
 
380
        check_hide_private (hier);
 
381
 
 
382
        folder_result = EXCHANGE_HIERARCHY_CLASS (parent_class)->scan_subtree (hier, folder, offline);
 
383
 
 
384
        if (exchange_hierarchy_is_empty (hier))
 
385
                hierarchy_foreign_cleanup (hier);
 
386
 
 
387
        return folder_result;
 
388
}
 
389
 
 
390
static void
 
391
add_href (ExchangeHierarchy *hier, EFolder *folder, gpointer hrefs)
 
392
{
 
393
        char *uri = g_strdup (e_folder_exchange_get_internal_uri (folder));
 
394
 
 
395
        g_ptr_array_add (hrefs, (gpointer) uri);
 
396
}
 
397
 
 
398
static GPtrArray *
 
399
get_hrefs (ExchangeHierarchySomeDAV *hsd)
 
400
{
 
401
        GPtrArray *hrefs;
 
402
 
 
403
        hrefs = g_ptr_array_new ();
 
404
        exchange_hierarchy_webdav_offline_scan_subtree (EXCHANGE_HIERARCHY (hsd), add_href, hrefs);
 
405
        return hrefs;
 
406
}
 
407
 
 
408
/**
 
409
 * exchange_hierarchy_foreign_add_folder:
 
410
 * @hier: the hierarchy
 
411
 * @folder_name: the name of the folder to add
 
412
 * @folder: on successful return, the created folder
 
413
 *
 
414
 * Adds a new folder to @hier.
 
415
 *
 
416
 * Return value: the folder result.
 
417
 **/
 
418
ExchangeAccountFolderResult
 
419
exchange_hierarchy_foreign_add_folder (ExchangeHierarchy *hier,
 
420
                                       const char *folder_name,
 
421
                                       EFolder **folder)
 
422
{
 
423
        ExchangeAccountFolderResult result;
 
424
        const char *folder_type = NULL;
 
425
        const char *physical_uri = NULL;
 
426
        char *new_folder_name;
 
427
 
 
428
        result =  create_internal (hier, hier->toplevel, folder_name, NULL, folder);
 
429
        if (result == EXCHANGE_ACCOUNT_FOLDER_OK) {
 
430
                /* Add the esources */
 
431
                folder_type = e_folder_get_type_string (*folder);
 
432
                physical_uri = e_folder_get_physical_uri (*folder);
 
433
                new_folder_name = g_strdup_printf("%s's %s", 
 
434
                                        hier->owner_name, folder_name);
 
435
 
 
436
                if (!(strcmp (folder_type, "calendar")) ||
 
437
                !(strcmp (folder_type, "calendar/public"))) {
 
438
                        add_folder_esource (hier->account,
 
439
                                            EXCHANGE_CALENDAR_FOLDER,
 
440
                                            new_folder_name,
 
441
                                            physical_uri);
 
442
                }
 
443
                else if (!(strcmp (folder_type, "tasks")) ||
 
444
                         !(strcmp (folder_type, "tasks/public"))) {
 
445
                                add_folder_esource (hier->account,
 
446
                                                    EXCHANGE_TASKS_FOLDER,
 
447
                                                    new_folder_name,
 
448
                                                    physical_uri);
 
449
                }
 
450
                else if (!(strcmp (folder_type, "contacts")) ||
 
451
                         !(strcmp (folder_type, "contacts/public")) ||
 
452
                         !(strcmp (folder_type, "contacts/ldap"))) {
 
453
                                add_folder_esource (hier->account,
 
454
                                                    EXCHANGE_CONTACTS_FOLDER,
 
455
                                                    new_folder_name,
 
456
                                                    physical_uri);
 
457
                }
 
458
                g_free (new_folder_name);
 
459
        }
 
460
        return result;
 
461
}
 
462
 
 
463
static ExchangeHierarchy *
 
464
hierarchy_foreign_new (ExchangeAccount *account,
 
465
                       const char *hierarchy_name,
 
466
                       const char *physical_uri_prefix,
 
467
                       const char *internal_uri_prefix,
 
468
                       const char *owner_name,
 
469
                       const char *owner_email,
 
470
                       const char *source_uri)
 
471
{
 
472
        ExchangeHierarchyForeign *hfor;
 
473
 
 
474
        g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
 
475
 
 
476
        hfor = g_object_new (EXCHANGE_TYPE_HIERARCHY_FOREIGN, NULL);
 
477
 
 
478
        exchange_hierarchy_webdav_construct (EXCHANGE_HIERARCHY_WEBDAV (hfor),
 
479
                                             account,
 
480
                                             EXCHANGE_HIERARCHY_FOREIGN,
 
481
                                             hierarchy_name,
 
482
                                             physical_uri_prefix,
 
483
                                             internal_uri_prefix,
 
484
                                             owner_name, owner_email,
 
485
                                             source_uri,
 
486
                                             FALSE);
 
487
 
 
488
        return EXCHANGE_HIERARCHY (hfor);
 
489
}
 
490
 
 
491
/**
 
492
 * exchange_hierarchy_foreign_new:
 
493
 * @account: an #ExchangeAccount
 
494
 * @hierarchy_name: the name of the hierarchy
 
495
 * @physical_uri_prefix: the prefix of physical URIs in this hierarchy
 
496
 * @internal_uri_prefix: the prefix of internal (http) URIs in this hierarchy
 
497
 * @owner_name: display name of the owner of the hierarchy
 
498
 * @owner_email: email address of the owner of the hierarchy
 
499
 * @source_uri: evolution-mail source uri for the hierarchy
 
500
 *
 
501
 * Creates a new (initially empty) hierarchy for another user's
 
502
 * folders.
 
503
 *
 
504
 * Return value: the new hierarchy.
 
505
 **/
 
506
ExchangeHierarchy *
 
507
exchange_hierarchy_foreign_new (ExchangeAccount *account,
 
508
                                const char *hierarchy_name,
 
509
                                const char *physical_uri_prefix,
 
510
                                const char *internal_uri_prefix,
 
511
                                const char *owner_name,
 
512
                                const char *owner_email,
 
513
                                const char *source_uri)
 
514
{
 
515
        ExchangeHierarchy *hier;
 
516
        char *mf_path;
 
517
        GHashTable *props;
 
518
        xmlDoc *doc;
 
519
 
 
520
        g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
 
521
        
 
522
        hier = hierarchy_foreign_new (account, hierarchy_name,
 
523
                                      physical_uri_prefix,
 
524
                                      internal_uri_prefix,
 
525
                                      owner_name, owner_email,
 
526
                                      source_uri);
 
527
 
 
528
        props = g_hash_table_new (g_str_hash, g_str_equal);
 
529
        g_hash_table_insert (props, "name", (char *)hierarchy_name);
 
530
        g_hash_table_insert (props, "physical_uri_prefix",
 
531
                             (char *)physical_uri_prefix);
 
532
        g_hash_table_insert (props, "internal_uri_prefix",
 
533
                             (char *)internal_uri_prefix);
 
534
        g_hash_table_insert (props, "owner_name", (char *)owner_name);
 
535
        g_hash_table_insert (props, "owner_email", (char *)owner_email);
 
536
        g_hash_table_insert (props, "source_uri", (char *)source_uri);
 
537
 
 
538
        mf_path = e_folder_exchange_get_storage_file (hier->toplevel, "hierarchy.xml");
 
539
        doc = e_xml_from_hash (props, E_XML_HASH_TYPE_PROPERTY,
 
540
                               "foreign-hierarchy");
 
541
        xmlSaveFile (mf_path, doc);
 
542
        g_hash_table_destroy (props);
 
543
        g_free (mf_path);
 
544
        xmlFreeDoc (doc);
 
545
 
 
546
        return hier;
 
547
}
 
548
 
 
549
/**
 
550
 * exchange_hierarchy_foreign_new_from_dir:
 
551
 * @account: an #ExchangeAccount
 
552
 * @folder_path: pathname to a directory containing a hierarchy.xml file
 
553
 *
 
554
 * Recreates a new hierarchy from saved values.
 
555
 *
 
556
 * Return value: the new hierarchy.
 
557
 **/
 
558
ExchangeHierarchy *
 
559
exchange_hierarchy_foreign_new_from_dir (ExchangeAccount *account,
 
560
                                         const char *folder_path)
 
561
{
 
562
        ExchangeHierarchy *hier;
 
563
        char *mf_path;
 
564
        GHashTable *props;
 
565
        xmlDoc *doc;
 
566
 
 
567
        g_return_val_if_fail (EXCHANGE_IS_ACCOUNT (account), NULL);
 
568
        g_return_val_if_fail (folder_path != NULL, NULL);
 
569
 
 
570
        mf_path = g_build_filename (folder_path, "hierarchy.xml", NULL);
 
571
        doc = xmlParseFile (mf_path);
 
572
        g_free (mf_path);
 
573
        if (!doc)
 
574
                return NULL;
 
575
 
 
576
        props = e_xml_to_hash (doc, E_XML_HASH_TYPE_PROPERTY);
 
577
        xmlFreeDoc (doc);
 
578
 
 
579
        hier = hierarchy_foreign_new (account,
 
580
                                      g_hash_table_lookup (props, "name"),
 
581
                                      g_hash_table_lookup (props, "physical_uri_prefix"),
 
582
                                      g_hash_table_lookup (props, "internal_uri_prefix"),
 
583
                                      g_hash_table_lookup (props, "owner_name"),
 
584
                                      g_hash_table_lookup (props, "owner_email"),
 
585
                                      g_hash_table_lookup (props, "source_uri"));
 
586
 
 
587
        e_xml_destroy_hash (props);
 
588
        return hier;
 
589
}