Fix FSF address (Tobias Mueller, #470445)
[platform/upstream/evolution-data-server.git] / servers / exchange / storage / exchange-hierarchy.c
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., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 /* ExchangeHierarchy: abstract class for a hierarchy of folders
21  * in an Exchange storage. Subclasses of ExchangeHierarchy implement
22  * normal WebDAV hierarchies, the GAL hierarchy, and hierarchies
23  * of individually-selected other users' folders.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 #include "exchange-hierarchy.h"
31 #include "e-folder-exchange.h"
32
33 enum {
34         NEW_FOLDER,
35         REMOVED_FOLDER,
36         LAST_SIGNAL
37 };
38
39 static guint signals [LAST_SIGNAL] = { 0 };
40
41 #define PARENT_TYPE G_TYPE_OBJECT
42 static GObjectClass *parent_class = NULL;
43
44 #define HIER_CLASS(hier) (EXCHANGE_HIERARCHY_CLASS (G_OBJECT_GET_CLASS (hier)))
45
46 static void dispose (GObject *object);
47 static void finalize (GObject *object);
48 static gboolean is_empty        (ExchangeHierarchy *hier);
49 static void add_to_storage      (ExchangeHierarchy *hier);
50 static ExchangeAccountFolderResult scan_subtree  (ExchangeHierarchy *hier,
51                                                   EFolder *folder,
52                                                   int mode);
53 static void                        rescan        (ExchangeHierarchy *hier);
54 static ExchangeAccountFolderResult create_folder (ExchangeHierarchy *hier,
55                                                   EFolder *parent,
56                                                   const char *name,
57                                                   const char *type);
58 static ExchangeAccountFolderResult remove_folder (ExchangeHierarchy *hier,
59                                                   EFolder *folder);
60 static ExchangeAccountFolderResult xfer_folder   (ExchangeHierarchy *hier,
61                                                   EFolder *source,
62                                                   EFolder *dest_parent,
63                                                   const char *dest_name,
64                                                   gboolean remove_source);
65
66 static void
67 class_init (GObjectClass *object_class)
68 {
69         ExchangeHierarchyClass *exchange_hierarchy_class =
70                 EXCHANGE_HIERARCHY_CLASS (object_class);
71
72         parent_class = g_type_class_ref (PARENT_TYPE);
73
74         /* methods */
75         object_class->dispose = dispose;
76         object_class->finalize = finalize;
77
78         exchange_hierarchy_class->is_empty = is_empty;
79         exchange_hierarchy_class->add_to_storage = add_to_storage;
80         exchange_hierarchy_class->rescan = rescan;
81         exchange_hierarchy_class->scan_subtree = scan_subtree;
82         exchange_hierarchy_class->create_folder = create_folder;
83         exchange_hierarchy_class->remove_folder = remove_folder;
84         exchange_hierarchy_class->xfer_folder = xfer_folder;
85
86         /* signals */
87         signals[NEW_FOLDER] =
88                 g_signal_new ("new_folder",
89                               G_OBJECT_CLASS_TYPE (object_class),
90                               G_SIGNAL_RUN_LAST,
91                               G_STRUCT_OFFSET (ExchangeHierarchyClass, new_folder),
92                               NULL, NULL,
93                               g_cclosure_marshal_VOID__POINTER,
94                               G_TYPE_NONE, 1,
95                               G_TYPE_POINTER);
96         signals[REMOVED_FOLDER] =
97                 g_signal_new ("removed_folder",
98                               G_OBJECT_CLASS_TYPE (object_class),
99                               G_SIGNAL_RUN_LAST,
100                               G_STRUCT_OFFSET (ExchangeHierarchyClass, removed_folder),
101                               NULL, NULL,
102                               g_cclosure_marshal_VOID__POINTER,
103                               G_TYPE_NONE, 1,
104                               G_TYPE_POINTER);
105 }
106
107 static void
108 dispose (GObject *object)
109 {
110         ExchangeHierarchy *hier = EXCHANGE_HIERARCHY (object);
111
112         if (hier->toplevel) {
113                 g_object_unref (hier->toplevel);
114                 hier->toplevel = NULL;
115         }
116
117         G_OBJECT_CLASS (parent_class)->dispose (object);
118 }
119
120 static void
121 finalize (GObject *object)
122 {
123         ExchangeHierarchy *hier = EXCHANGE_HIERARCHY (object);
124
125         g_free (hier->owner_name);
126         g_free (hier->owner_email);
127         g_free (hier->source_uri);
128
129         G_OBJECT_CLASS (parent_class)->finalize (object);
130 }
131
132 E2K_MAKE_TYPE (exchange_hierarchy, ExchangeHierarchy, class_init, NULL, PARENT_TYPE)
133
134
135 /**
136  * exchange_hierarchy_new_folder:
137  * @hier: the hierarchy
138  * @folder: the new folder
139  *
140  * Emits a %new_folder signal.
141  **/
142 void
143 exchange_hierarchy_new_folder (ExchangeHierarchy *hier,
144                                EFolder *folder)
145 {
146         g_return_if_fail (EXCHANGE_IS_HIERARCHY (hier));
147         g_return_if_fail (E_IS_FOLDER (folder));
148         
149         g_signal_emit (hier, signals[NEW_FOLDER], 0, folder);
150 }
151
152 /**
153  * exchange_hierarchy_removed_folder:
154  * @hier: the hierarchy
155  * @folder: the (about-to-be-)removed folder
156  *
157  * Emits a %removed_folder signal.
158  **/
159 void
160 exchange_hierarchy_removed_folder (ExchangeHierarchy *hier,
161                                    EFolder *folder)
162 {
163         g_return_if_fail (EXCHANGE_IS_HIERARCHY (hier));
164         g_return_if_fail (E_IS_FOLDER (folder));
165
166         g_signal_emit (hier, signals[REMOVED_FOLDER], 0, folder);
167 }
168
169 static gboolean
170 is_empty (ExchangeHierarchy *hier)
171 {
172         return FALSE;
173 }
174
175 gboolean
176 exchange_hierarchy_is_empty (ExchangeHierarchy *hier)
177 {
178         g_return_val_if_fail (EXCHANGE_IS_HIERARCHY (hier), TRUE);
179
180         return HIER_CLASS (hier)->is_empty (hier);
181 }
182
183
184 static ExchangeAccountFolderResult
185 create_folder (ExchangeHierarchy *hier, EFolder *parent,
186                const char *name, const char *type)
187 {
188         return EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED;
189 }
190
191 static ExchangeAccountFolderResult
192 remove_folder (ExchangeHierarchy *hier, EFolder *folder)
193 {
194         return EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED;
195 }
196
197 static ExchangeAccountFolderResult
198 xfer_folder (ExchangeHierarchy *hier, EFolder *source,
199              EFolder *dest_parent, const char *dest_name,
200              gboolean remove_source)
201 {
202         return EXCHANGE_ACCOUNT_FOLDER_PERMISSION_DENIED;
203 }
204
205 /**
206  * exchange_hierarchy_create_folder:
207  * @hier: the hierarchy
208  * @parent: the parent folder of the new folder
209  * @name: name of the new folder (UTF8)
210  * @type: Evolution folder type of the new folder
211  *
212  * Attempts to create a new folder.
213  *
214  * Return value: the result code
215  **/
216 ExchangeAccountFolderResult
217 exchange_hierarchy_create_folder (ExchangeHierarchy *hier, EFolder *parent,
218                                   const char *name, const char *type)
219 {
220         g_return_val_if_fail (EXCHANGE_IS_HIERARCHY (hier), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
221         g_return_val_if_fail (E_IS_FOLDER (parent), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
222         g_return_val_if_fail (name != NULL, EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
223         g_return_val_if_fail (type != NULL, EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
224
225         return HIER_CLASS (hier)->create_folder (hier, parent, name, type);
226 }
227
228 /**
229  * exchange_hierarchy_remove_folder:
230  * @hier: the hierarchy
231  * @folder: the folder to remove
232  *
233  * Attempts to remove a folder.
234  *
235  * Return value: the result code
236  **/
237 ExchangeAccountFolderResult
238 exchange_hierarchy_remove_folder (ExchangeHierarchy *hier, EFolder *folder)
239 {
240         g_return_val_if_fail (EXCHANGE_IS_HIERARCHY (hier), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
241         g_return_val_if_fail (E_IS_FOLDER (folder), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
242
243         return HIER_CLASS (hier)->remove_folder (hier, folder);
244 }
245
246 /**
247  * exchange_hierarchy_xfer_folder:
248  * @hier: the hierarchy
249  * @source: the source folder
250  * @dest_parent: the parent of the destination folder
251  * @dest_name: name of the destination (UTF8)
252  * @remove_source: %TRUE if this is a move, %FALSE if it is a copy
253  *
254  * Attempts to move or copy a folder.
255  *
256  * Return value: the result code
257  **/
258 ExchangeAccountFolderResult
259 exchange_hierarchy_xfer_folder (ExchangeHierarchy *hier, EFolder *source,
260                                 EFolder *dest_parent, const char *dest_name,
261                                 gboolean remove_source)
262 {
263         g_return_val_if_fail (EXCHANGE_IS_HIERARCHY (hier), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
264         g_return_val_if_fail (E_IS_FOLDER (source), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
265         g_return_val_if_fail (E_IS_FOLDER (dest_parent), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
266         g_return_val_if_fail (dest_name != NULL, EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
267
268         return HIER_CLASS (hier)->xfer_folder (hier, source,
269                                                dest_parent, dest_name,
270                                                remove_source);
271 }
272
273
274 static void
275 rescan (ExchangeHierarchy *hier)
276 {
277         ;
278 }
279
280 /**
281  * exchange_hierarchy_rescan:
282  * @hier: the hierarchy
283  *
284  * Tells the hierarchy to rescan its folder tree
285  **/
286 void
287 exchange_hierarchy_rescan (ExchangeHierarchy *hier)
288 {
289         g_return_if_fail (EXCHANGE_IS_HIERARCHY (hier));
290
291         HIER_CLASS (hier)->rescan (hier);
292 }
293
294
295 static ExchangeAccountFolderResult
296 scan_subtree (ExchangeHierarchy *hier, EFolder *folder, int mode)
297 {
298         return EXCHANGE_ACCOUNT_FOLDER_OK;
299 }
300
301 /**
302  * exchange_hierarchy_scan_subtree:
303  * @hier: the hierarchy
304  * @folder: the folder to scan under
305  *
306  * Scans for folders in @hier underneath @folder, emitting %new_folder
307  * signals for each one found. Depending on the kind of hierarchy,
308  * this may initiate a recursive scan.
309  *
310  * Return value: the result code
311  **/
312 ExchangeAccountFolderResult
313 exchange_hierarchy_scan_subtree (ExchangeHierarchy *hier, EFolder *folder, int mode)
314 {
315         g_return_val_if_fail (EXCHANGE_IS_HIERARCHY (hier), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
316         g_return_val_if_fail (E_IS_FOLDER (folder), EXCHANGE_ACCOUNT_FOLDER_GENERIC_ERROR);
317
318         return HIER_CLASS (hier)->scan_subtree (hier, folder, mode);
319 }
320
321
322 static void
323 add_to_storage (ExchangeHierarchy *hier)
324 {
325         e_folder_set_sorting_priority (hier->toplevel, hier->type);
326         exchange_hierarchy_new_folder (hier, hier->toplevel);
327 }
328
329 /**
330  * exchange_hierarchy_add_to_storage:
331  * @hier: the hierarchy
332  *
333  * Tells the hierarchy to fill in its folder tree, emitting %new_folder
334  * signals as appropriate.
335  **/
336 void
337 exchange_hierarchy_add_to_storage (ExchangeHierarchy *hier)
338 {
339         g_return_if_fail (EXCHANGE_IS_HIERARCHY (hier));
340
341         HIER_CLASS (hier)->add_to_storage (hier);
342 }
343
344
345 /**
346  * exchange_hierarchy_construct:
347  * @hier: the hierarchy
348  * @account: the hierarchy's account
349  * @type: the type of hierarchy
350  * @toplevel: the top-level folder of the hierarchy
351  * @owner_name: the display name of the owner of this hierarchy
352  * @owner_email: the email address of the owner of this hierarchy
353  * @source_uri: the evolution-mail source URI of this hierarchy.
354  *
355  * Constructs the hierarchy. @owner_name, @owner_email, and @source_uri
356  * can be %NULL if not relevant to this hierarchy.
357  **/
358 void
359 exchange_hierarchy_construct (ExchangeHierarchy *hier,
360                               ExchangeAccount *account,
361                               ExchangeHierarchyType type,
362                               EFolder *toplevel,
363                               const char *owner_name,
364                               const char *owner_email,
365                               const char *source_uri)
366 {
367         g_return_if_fail (EXCHANGE_IS_HIERARCHY (hier));
368         g_return_if_fail (EXCHANGE_IS_ACCOUNT (account));
369         g_return_if_fail (E_IS_FOLDER (toplevel));
370
371         /* We don't ref the account since we'll be destroyed when
372          * the account is
373          */
374         hier->account = account;
375
376         hier->toplevel = toplevel;
377         g_object_ref (toplevel);
378
379         hier->type = type;
380         hier->owner_name = g_strdup (owner_name);
381         hier->owner_email = g_strdup (owner_email);
382         hier->source_uri = g_strdup (source_uri);
383 }