1 | /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ |
---|
2 | /* component-factory.c |
---|
3 | * |
---|
4 | * Authors: Ettore Perazzoli <ettore@ximian.com> |
---|
5 | * |
---|
6 | * Copyright (C) 2000 Ximian, Inc. |
---|
7 | * |
---|
8 | * This program is free software; you can redistribute it and/or |
---|
9 | * modify it under the terms of version 2 of the GNU General Public |
---|
10 | * License as published by the Free Software Foundation. |
---|
11 | * |
---|
12 | * This program is distributed in the hope that it will be useful, |
---|
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
15 | * General Public License for more details. |
---|
16 | * |
---|
17 | * You should have received a copy of the GNU General Public |
---|
18 | * License along with this program; if not, write to the |
---|
19 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
---|
20 | * Boston, MA 02111-1307, USA. |
---|
21 | */ |
---|
22 | |
---|
23 | #ifdef HAVE_CONFIG_H |
---|
24 | #include <config.h> |
---|
25 | #endif |
---|
26 | |
---|
27 | #include <bonobo/bonobo-generic-factory.h> |
---|
28 | #include <gal/widgets/e-gui-utils.h> |
---|
29 | |
---|
30 | #include "camel.h" |
---|
31 | |
---|
32 | #include "Evolution.h" |
---|
33 | #include "evolution-storage.h" |
---|
34 | #include "evolution-wizard.h" |
---|
35 | |
---|
36 | #include "folder-browser-factory.h" |
---|
37 | #include "evolution-shell-component.h" |
---|
38 | #include "evolution-shell-component-dnd.h" |
---|
39 | #include "folder-browser.h" |
---|
40 | #include "mail.h" /* YUCK FIXME */ |
---|
41 | #include "mail-config.h" |
---|
42 | #include "mail-tools.h" |
---|
43 | #include "mail-ops.h" |
---|
44 | #include "mail-offline-handler.h" |
---|
45 | #include "mail-local.h" |
---|
46 | #include "mail-session.h" |
---|
47 | #include "mail-mt.h" |
---|
48 | #include "mail-importer.h" |
---|
49 | #include "mail-folder-cache.h" |
---|
50 | |
---|
51 | #include "component-factory.h" |
---|
52 | |
---|
53 | #include "mail-send-recv.h" |
---|
54 | |
---|
55 | #include "mail-vfolder.h" |
---|
56 | #include "mail-autofilter.h" |
---|
57 | |
---|
58 | #define d(x) |
---|
59 | |
---|
60 | char *default_drafts_folder_uri; |
---|
61 | CamelFolder *drafts_folder = NULL; |
---|
62 | char *default_sent_folder_uri; |
---|
63 | CamelFolder *sent_folder = NULL; |
---|
64 | char *default_outbox_folder_uri; |
---|
65 | CamelFolder *outbox_folder = NULL; |
---|
66 | char *evolution_dir; |
---|
67 | |
---|
68 | EvolutionShellClient *global_shell_client = NULL; |
---|
69 | |
---|
70 | RuleContext *search_context = NULL; |
---|
71 | |
---|
72 | static MailAsyncEvent *async_event = NULL; |
---|
73 | |
---|
74 | static GHashTable *storages_hash; |
---|
75 | static EvolutionShellComponent *shell_component; |
---|
76 | |
---|
77 | enum { |
---|
78 | ACCEPTED_DND_TYPE_MESSAGE_RFC822, |
---|
79 | ACCEPTED_DND_TYPE_X_EVOLUTION_MESSAGE, |
---|
80 | ACCEPTED_DND_TYPE_TEXT_URI_LIST, |
---|
81 | }; |
---|
82 | |
---|
83 | static char *accepted_dnd_types[] = { |
---|
84 | "message/rfc822", |
---|
85 | "x-evolution-message", /* ...from an evolution message list... */ |
---|
86 | "text/uri-list", /* ...from nautilus... */ |
---|
87 | NULL |
---|
88 | }; |
---|
89 | |
---|
90 | enum { |
---|
91 | EXPORTED_DND_TYPE_TEXT_URI_LIST, |
---|
92 | }; |
---|
93 | |
---|
94 | static char *exported_dnd_types[] = { |
---|
95 | "text/uri-list", /* we have to export to nautilus as text/uri-list */ |
---|
96 | NULL |
---|
97 | }; |
---|
98 | |
---|
99 | static const EvolutionShellComponentFolderType folder_types[] = { |
---|
100 | { "mail", "evolution-inbox.png", N_("Mail"), N_("Folder containing mail"), TRUE, accepted_dnd_types, exported_dnd_types }, |
---|
101 | { "mailstorage", "evolution-inbox.png", "Mailstorage", N_("Mail storage folder (internal)"), FALSE, NULL, NULL }, |
---|
102 | { "vtrash", "evolution-trash.png", N_("Virtual Trash"), N_("Virtual Trash folder"), FALSE, accepted_dnd_types, exported_dnd_types }, |
---|
103 | { NULL, NULL, NULL, NULL, FALSE, NULL, NULL } |
---|
104 | }; |
---|
105 | |
---|
106 | static const char *schema_types[] = { |
---|
107 | "mailto", |
---|
108 | NULL |
---|
109 | }; |
---|
110 | |
---|
111 | /* EvolutionShellComponent methods and signals. */ |
---|
112 | |
---|
113 | static void |
---|
114 | storage_activate (BonoboControl *control, gboolean activate, |
---|
115 | const char *physical_uri) |
---|
116 | { |
---|
117 | CamelService *store; |
---|
118 | EvolutionStorage *storage; |
---|
119 | CamelException ex; |
---|
120 | |
---|
121 | if (!activate) |
---|
122 | return; |
---|
123 | |
---|
124 | camel_exception_init (&ex); |
---|
125 | store = camel_session_get_service (session, physical_uri, |
---|
126 | CAMEL_PROVIDER_STORE, &ex); |
---|
127 | if (!store) { |
---|
128 | e_notice (NULL, GNOME_MESSAGE_BOX_ERROR, |
---|
129 | _("Cannot connect to store: %s"), |
---|
130 | camel_exception_get_description (&ex)); |
---|
131 | camel_exception_clear (&ex); |
---|
132 | return; |
---|
133 | } |
---|
134 | camel_exception_clear (&ex); |
---|
135 | |
---|
136 | storage = g_hash_table_lookup (storages_hash, store); |
---|
137 | if (storage && !gtk_object_get_data (GTK_OBJECT (storage), "connected")) |
---|
138 | mail_note_store (CAMEL_STORE(store), storage, CORBA_OBJECT_NIL, NULL, NULL); |
---|
139 | camel_object_unref (CAMEL_OBJECT (store)); |
---|
140 | } |
---|
141 | |
---|
142 | static BonoboControl * |
---|
143 | create_noselect_control (void) |
---|
144 | { |
---|
145 | GtkWidget *label; |
---|
146 | |
---|
147 | label = gtk_label_new (_("This folder cannot contain messages.")); |
---|
148 | gtk_widget_show (label); |
---|
149 | return bonobo_control_new (label); |
---|
150 | } |
---|
151 | |
---|
152 | static EvolutionShellComponentResult |
---|
153 | create_view (EvolutionShellComponent *shell_component, |
---|
154 | const char *physical_uri, |
---|
155 | const char *folder_type, |
---|
156 | BonoboControl **control_return, |
---|
157 | void *closure) |
---|
158 | { |
---|
159 | EvolutionShellClient *shell_client; |
---|
160 | GNOME_Evolution_Shell corba_shell; |
---|
161 | BonoboControl *control; |
---|
162 | |
---|
163 | shell_client = evolution_shell_component_get_owner (shell_component); |
---|
164 | corba_shell = bonobo_object_corba_objref (BONOBO_OBJECT (shell_client)); |
---|
165 | |
---|
166 | if (!g_strcasecmp (folder_type, "mail")) { |
---|
167 | const char *noselect; |
---|
168 | CamelURL *url; |
---|
169 | |
---|
170 | url = camel_url_new (physical_uri, NULL); |
---|
171 | noselect = url ? camel_url_get_param (url, "noselect") : NULL; |
---|
172 | if (noselect && !g_strcasecmp (noselect, "yes")) |
---|
173 | control = create_noselect_control (); |
---|
174 | else |
---|
175 | control = folder_browser_factory_new_control (physical_uri, |
---|
176 | corba_shell); |
---|
177 | camel_url_free (url); |
---|
178 | } else if (!g_strcasecmp (folder_type, "mailstorage")) { |
---|
179 | char *uri_dup = g_strdup (physical_uri); |
---|
180 | |
---|
181 | control = create_noselect_control (); |
---|
182 | gtk_object_set_data_full (GTK_OBJECT (control), "physical_uri", |
---|
183 | uri_dup, g_free); |
---|
184 | gtk_signal_connect (GTK_OBJECT (control), "activate", |
---|
185 | storage_activate, uri_dup); |
---|
186 | } else if (!g_strcasecmp (folder_type, "vtrash")) { |
---|
187 | if (!g_strncasecmp (physical_uri, "file:", 5)) |
---|
188 | control = folder_browser_factory_new_control ("vtrash:file:/", corba_shell); |
---|
189 | else |
---|
190 | control = folder_browser_factory_new_control (physical_uri, corba_shell); |
---|
191 | } else |
---|
192 | return EVOLUTION_SHELL_COMPONENT_UNSUPPORTEDTYPE; |
---|
193 | |
---|
194 | if (!control) |
---|
195 | return EVOLUTION_SHELL_COMPONENT_NOTFOUND; |
---|
196 | |
---|
197 | *control_return = control; |
---|
198 | return EVOLUTION_SHELL_COMPONENT_OK; |
---|
199 | } |
---|
200 | |
---|
201 | static void |
---|
202 | create_folder_done (char *uri, CamelFolder *folder, void *data) |
---|
203 | { |
---|
204 | GNOME_Evolution_ShellComponentListener listener = data; |
---|
205 | GNOME_Evolution_ShellComponentListener_Result result; |
---|
206 | CORBA_Environment ev; |
---|
207 | |
---|
208 | if (folder) { |
---|
209 | result = GNOME_Evolution_ShellComponentListener_OK; |
---|
210 | } else { |
---|
211 | result = GNOME_Evolution_ShellComponentListener_INVALID_URI; |
---|
212 | } |
---|
213 | |
---|
214 | CORBA_exception_init (&ev); |
---|
215 | GNOME_Evolution_ShellComponentListener_notifyResult (listener, result, &ev); |
---|
216 | CORBA_Object_release (listener, &ev); |
---|
217 | CORBA_exception_free (&ev); |
---|
218 | } |
---|
219 | |
---|
220 | static void |
---|
221 | create_folder (EvolutionShellComponent *shell_component, |
---|
222 | const char *physical_uri, |
---|
223 | const char *type, |
---|
224 | const GNOME_Evolution_ShellComponentListener listener, |
---|
225 | void *closure) |
---|
226 | { |
---|
227 | CORBA_Environment ev; |
---|
228 | |
---|
229 | CORBA_exception_init (&ev); |
---|
230 | |
---|
231 | if (!strcmp (type, "mail")) { |
---|
232 | mail_get_folder (physical_uri, CAMEL_STORE_FOLDER_CREATE, create_folder_done, |
---|
233 | CORBA_Object_duplicate (listener, &ev), mail_thread_new); |
---|
234 | } else { |
---|
235 | GNOME_Evolution_ShellComponentListener_notifyResult ( |
---|
236 | listener, GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, &ev); |
---|
237 | } |
---|
238 | |
---|
239 | CORBA_exception_free (&ev); |
---|
240 | } |
---|
241 | |
---|
242 | static void |
---|
243 | remove_folder_done (char *uri, gboolean removed, void *data) |
---|
244 | { |
---|
245 | GNOME_Evolution_ShellComponentListener listener = data; |
---|
246 | GNOME_Evolution_ShellComponentListener_Result result; |
---|
247 | CORBA_Environment ev; |
---|
248 | |
---|
249 | if (removed) |
---|
250 | result = GNOME_Evolution_ShellComponentListener_OK; |
---|
251 | else |
---|
252 | result = GNOME_Evolution_ShellComponentListener_INVALID_URI; |
---|
253 | |
---|
254 | CORBA_exception_init (&ev); |
---|
255 | GNOME_Evolution_ShellComponentListener_notifyResult (listener, result, &ev); |
---|
256 | CORBA_Object_release (listener, &ev); |
---|
257 | CORBA_exception_free (&ev); |
---|
258 | } |
---|
259 | |
---|
260 | static void |
---|
261 | remove_folder (EvolutionShellComponent *shell_component, |
---|
262 | const char *physical_uri, |
---|
263 | const char *type, |
---|
264 | const GNOME_Evolution_ShellComponentListener listener, |
---|
265 | void *closure) |
---|
266 | { |
---|
267 | CORBA_Environment ev; |
---|
268 | |
---|
269 | CORBA_exception_init (&ev); |
---|
270 | |
---|
271 | if (strcmp (type, "mail") != 0) { |
---|
272 | GNOME_Evolution_ShellComponentListener_notifyResult (listener, |
---|
273 | GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, &ev); |
---|
274 | CORBA_exception_free (&ev); |
---|
275 | return; |
---|
276 | } |
---|
277 | |
---|
278 | mail_remove_folder (physical_uri, remove_folder_done, CORBA_Object_duplicate (listener, &ev)); |
---|
279 | CORBA_exception_free (&ev); |
---|
280 | } |
---|
281 | |
---|
282 | typedef struct _xfer_folder_data { |
---|
283 | GNOME_Evolution_ShellComponentListener listener; |
---|
284 | gboolean remove_source; |
---|
285 | char *source_uri; |
---|
286 | } xfer_folder_data; |
---|
287 | |
---|
288 | static void |
---|
289 | xfer_folder_done (gboolean ok, void *data) |
---|
290 | { |
---|
291 | xfer_folder_data *xfd = (xfer_folder_data *)data; |
---|
292 | GNOME_Evolution_ShellComponentListener listener = xfd->listener; |
---|
293 | GNOME_Evolution_ShellComponentListener_Result result; |
---|
294 | CORBA_Environment ev; |
---|
295 | |
---|
296 | if (xfd->remove_source && ok) { |
---|
297 | mail_remove_folder (xfd->source_uri, remove_folder_done, xfd->listener); |
---|
298 | } else { |
---|
299 | if (ok) |
---|
300 | result = GNOME_Evolution_ShellComponentListener_OK; |
---|
301 | else |
---|
302 | result = GNOME_Evolution_ShellComponentListener_INVALID_URI; |
---|
303 | |
---|
304 | CORBA_exception_init (&ev); |
---|
305 | GNOME_Evolution_ShellComponentListener_notifyResult (listener, result, &ev); |
---|
306 | CORBA_Object_release (listener, &ev); |
---|
307 | CORBA_exception_free (&ev); |
---|
308 | } |
---|
309 | |
---|
310 | g_free (xfd->source_uri); |
---|
311 | g_free (xfd); |
---|
312 | } |
---|
313 | |
---|
314 | static void |
---|
315 | xfer_folder (EvolutionShellComponent *shell_component, |
---|
316 | const char *source_physical_uri, |
---|
317 | const char *destination_physical_uri, |
---|
318 | const char *type, |
---|
319 | gboolean remove_source, |
---|
320 | const GNOME_Evolution_ShellComponentListener listener, |
---|
321 | void *closure) |
---|
322 | { |
---|
323 | CORBA_Environment ev; |
---|
324 | CamelFolder *source; |
---|
325 | CamelException ex; |
---|
326 | GPtrArray *uids; |
---|
327 | CamelURL *src, *dst; |
---|
328 | |
---|
329 | d(printf("Renaming folder '%s' to dest '%s' type '%s'\n", source_physical_uri, destination_physical_uri, type)); |
---|
330 | |
---|
331 | CORBA_exception_init (&ev); |
---|
332 | |
---|
333 | if (strcmp (type, "mail") != 0) { |
---|
334 | GNOME_Evolution_ShellComponentListener_notifyResult (listener, |
---|
335 | GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, &ev); |
---|
336 | return; |
---|
337 | } |
---|
338 | |
---|
339 | src = camel_url_new(source_physical_uri, NULL); |
---|
340 | if (src == NULL) { |
---|
341 | GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev); |
---|
342 | return; |
---|
343 | } |
---|
344 | |
---|
345 | dst = camel_url_new(destination_physical_uri, NULL); |
---|
346 | if (dst == NULL) { |
---|
347 | camel_url_free(src); |
---|
348 | GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev); |
---|
349 | return; |
---|
350 | } |
---|
351 | |
---|
352 | if (camel_url_get_param(dst, "noselect") != NULL) { |
---|
353 | camel_url_free(src); |
---|
354 | camel_url_free(dst); |
---|
355 | GNOME_Evolution_ShellComponentListener_notifyResult (listener, |
---|
356 | GNOME_Evolution_ShellComponentListener_UNSUPPORTED_OPERATION, &ev); |
---|
357 | return; |
---|
358 | } |
---|
359 | |
---|
360 | camel_exception_init (&ex); |
---|
361 | |
---|
362 | /* If we are really doing a rename, implement it as a rename */ |
---|
363 | if (remove && strcmp(src->protocol, dst->protocol) == 0) { |
---|
364 | char *sname, *dname; |
---|
365 | CamelStore *store; |
---|
366 | |
---|
367 | if (src->fragment) |
---|
368 | sname = src->fragment; |
---|
369 | else { |
---|
370 | if (src->path && *src->path) |
---|
371 | sname = src->path+1; |
---|
372 | else |
---|
373 | sname = ""; |
---|
374 | } |
---|
375 | |
---|
376 | if (dst->fragment) |
---|
377 | dname = dst->fragment; |
---|
378 | else { |
---|
379 | if (dst->path && *dst->path) |
---|
380 | dname = dst->path+1; |
---|
381 | else |
---|
382 | dname = ""; |
---|
383 | } |
---|
384 | |
---|
385 | store = camel_session_get_store(session, source_physical_uri, &ex); |
---|
386 | if (store != NULL) |
---|
387 | camel_store_rename_folder(store, sname, dname, &ex); |
---|
388 | |
---|
389 | if (camel_exception_is_set(&ex)) |
---|
390 | GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev); |
---|
391 | else { |
---|
392 | /* Since the shell doesn't play nice with local folders, we have to do this manually */ |
---|
393 | mail_vfolder_rename_uri(store, source_physical_uri, destination_physical_uri); |
---|
394 | mail_filter_rename_uri(store, source_physical_uri, destination_physical_uri); |
---|
395 | GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_OK, &ev); |
---|
396 | } |
---|
397 | camel_object_unref((CamelObject *)store); |
---|
398 | } else { |
---|
399 | source = mail_tool_uri_to_folder (source_physical_uri, 0, &ex); |
---|
400 | |
---|
401 | if (source) { |
---|
402 | xfer_folder_data *xfd; |
---|
403 | |
---|
404 | xfd = g_new0 (xfer_folder_data, 1); |
---|
405 | xfd->remove_source = remove_source; |
---|
406 | xfd->source_uri = g_strdup (source_physical_uri); |
---|
407 | xfd->listener = CORBA_Object_duplicate (listener, &ev); |
---|
408 | |
---|
409 | uids = camel_folder_get_uids (source); |
---|
410 | mail_transfer_messages (source, uids, remove_source, destination_physical_uri, CAMEL_STORE_FOLDER_CREATE, xfer_folder_done, xfd); |
---|
411 | camel_object_unref (CAMEL_OBJECT (source)); |
---|
412 | } else |
---|
413 | GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev); |
---|
414 | } |
---|
415 | |
---|
416 | CORBA_exception_free (&ev); |
---|
417 | camel_exception_clear (&ex); |
---|
418 | |
---|
419 | camel_url_free(src); |
---|
420 | camel_url_free(dst); |
---|
421 | } |
---|
422 | |
---|
423 | #if 0 |
---|
424 | static void |
---|
425 | populate_folder_context_menu (EvolutionShellComponent *shell_component, |
---|
426 | BonoboUIComponent *uic, |
---|
427 | const char *physical_uri, |
---|
428 | const char *type, |
---|
429 | void *closure) |
---|
430 | { |
---|
431 | #ifdef TRANSLATORS_ONLY |
---|
432 | static char popup_xml_i18n[] = {N_("Properties..."), N_("Change this folder's properties")}; |
---|
433 | #endif |
---|
434 | static char popup_xml[] = |
---|
435 | "<menuitem name=\"ChangeFolderProperties\" verb=\"ChangeFolderProperties\"" |
---|
436 | " _label=\"Properties...\" _tip=\"Change this folder's properties\"/>"; |
---|
437 | |
---|
438 | if (strcmp (type, "mail") != 0) |
---|
439 | return; |
---|
440 | |
---|
441 | bonobo_ui_component_set_translate (uic, EVOLUTION_SHELL_COMPONENT_POPUP_PLACEHOLDER, |
---|
442 | popup_xml, NULL); |
---|
443 | } |
---|
444 | #endif |
---|
445 | |
---|
446 | static char * |
---|
447 | get_dnd_selection (EvolutionShellComponent *shell_component, |
---|
448 | const char *physical_uri, |
---|
449 | int type, |
---|
450 | int *format_return, |
---|
451 | const char **selection_return, |
---|
452 | int *selection_length_return, |
---|
453 | void *closure) |
---|
454 | { |
---|
455 | g_print ("should get dnd selection for %s\n", physical_uri); |
---|
456 | |
---|
457 | return NULL; |
---|
458 | } |
---|
459 | |
---|
460 | /* Destination side DnD */ |
---|
461 | static CORBA_boolean |
---|
462 | destination_folder_handle_motion (EvolutionShellComponentDndDestinationFolder *folder, |
---|
463 | const char *physical_uri, |
---|
464 | const char *folder_type, |
---|
465 | const GNOME_Evolution_ShellComponentDnd_DestinationFolder_Context *destination_context, |
---|
466 | GNOME_Evolution_ShellComponentDnd_Action *suggested_action_return, |
---|
467 | gpointer user_data) |
---|
468 | { |
---|
469 | const char *noselect; |
---|
470 | CamelURL *url; |
---|
471 | |
---|
472 | url = camel_url_new (physical_uri, NULL); |
---|
473 | noselect = camel_url_get_param (url, "noselect"); |
---|
474 | |
---|
475 | if (noselect && !g_strcasecmp (noselect, "yes")) |
---|
476 | /* uh, no way to say "illegal" */ |
---|
477 | *suggested_action_return = GNOME_Evolution_ShellComponentDnd_ACTION_DEFAULT; |
---|
478 | else |
---|
479 | *suggested_action_return = GNOME_Evolution_ShellComponentDnd_ACTION_MOVE; |
---|
480 | |
---|
481 | camel_url_free (url); |
---|
482 | |
---|
483 | return TRUE; |
---|
484 | } |
---|
485 | |
---|
486 | static void |
---|
487 | message_rfc822_dnd (CamelFolder *dest, CamelStream *stream, CamelException *ex) |
---|
488 | { |
---|
489 | CamelMimeParser *mp; |
---|
490 | |
---|
491 | mp = camel_mime_parser_new (); |
---|
492 | camel_mime_parser_scan_from (mp, TRUE); |
---|
493 | camel_mime_parser_init_with_stream (mp, stream); |
---|
494 | |
---|
495 | while (camel_mime_parser_step (mp, 0, 0) == HSCAN_FROM) { |
---|
496 | CamelMessageInfo *info; |
---|
497 | CamelMimeMessage *msg; |
---|
498 | |
---|
499 | msg = camel_mime_message_new (); |
---|
500 | if (camel_mime_part_construct_from_parser (CAMEL_MIME_PART (msg), mp) == -1) { |
---|
501 | camel_object_unref (CAMEL_OBJECT (msg)); |
---|
502 | break; |
---|
503 | } |
---|
504 | |
---|
505 | /* append the message to the folder... */ |
---|
506 | info = g_new0 (CamelMessageInfo, 1); |
---|
507 | camel_folder_append_message (dest, msg, info, ex); |
---|
508 | camel_object_unref (CAMEL_OBJECT (msg)); |
---|
509 | |
---|
510 | if (camel_exception_is_set (ex)) |
---|
511 | break; |
---|
512 | |
---|
513 | /* skip over the FROM_END state */ |
---|
514 | camel_mime_parser_step (mp, 0, 0); |
---|
515 | } |
---|
516 | |
---|
517 | camel_object_unref (CAMEL_OBJECT (mp)); |
---|
518 | } |
---|
519 | |
---|
520 | static CORBA_boolean |
---|
521 | destination_folder_handle_drop (EvolutionShellComponentDndDestinationFolder *dest_folder, |
---|
522 | const char *physical_uri, |
---|
523 | const char *folder_type, |
---|
524 | const GNOME_Evolution_ShellComponentDnd_DestinationFolder_Context *destination_context, |
---|
525 | const GNOME_Evolution_ShellComponentDnd_Action action, |
---|
526 | const GNOME_Evolution_ShellComponentDnd_Data *data, |
---|
527 | gpointer user_data) |
---|
528 | { |
---|
529 | char *tmp, *url, **urls, *in, *inptr, *inend; |
---|
530 | gboolean retval = FALSE; |
---|
531 | const char *noselect; |
---|
532 | CamelFolder *folder; |
---|
533 | CamelStream *stream; |
---|
534 | CamelException ex; |
---|
535 | GPtrArray *uids; |
---|
536 | CamelURL *uri; |
---|
537 | int i, type, fd; |
---|
538 | |
---|
539 | if (action == GNOME_Evolution_ShellComponentDnd_ACTION_LINK) |
---|
540 | return FALSE; /* we can't create links */ |
---|
541 | |
---|
542 | /* this means the drag was cancelled */ |
---|
543 | if (!data->bytes._buffer || data->bytes._length == -1) |
---|
544 | return FALSE; |
---|
545 | |
---|
546 | uri = camel_url_new (physical_uri, NULL); |
---|
547 | noselect = uri ? camel_url_get_param (uri, "noselect") : NULL; |
---|
548 | if (noselect && !g_strcasecmp (noselect, "yes")) { |
---|
549 | camel_url_free (uri); |
---|
550 | return FALSE; |
---|
551 | } |
---|
552 | camel_url_free (uri); |
---|
553 | |
---|
554 | g_print ("in destination_folder_handle_drop (%s)\n", physical_uri); |
---|
555 | |
---|
556 | for (type = 0; accepted_dnd_types[type]; type++) |
---|
557 | if (!strcmp (destination_context->dndType, accepted_dnd_types[type])) |
---|
558 | break; |
---|
559 | |
---|
560 | camel_exception_init (&ex); |
---|
561 | |
---|
562 | /* if this is a local vtrash folder, then it's uri is vtrash:file:/ */ |
---|
563 | if (!strcmp (folder_type, "vtrash") && !strncmp (physical_uri, "file:", 5)) |
---|
564 | physical_uri = "vtrash:file:/"; |
---|
565 | |
---|
566 | switch (type) { |
---|
567 | case ACCEPTED_DND_TYPE_TEXT_URI_LIST: |
---|
568 | folder = mail_tool_uri_to_folder (physical_uri, 0, NULL); |
---|
569 | if (!folder) |
---|
570 | return FALSE; |
---|
571 | |
---|
572 | tmp = g_strndup (data->bytes._buffer, data->bytes._length); |
---|
573 | urls = g_strsplit (tmp, "\n", 0); |
---|
574 | g_free (tmp); |
---|
575 | |
---|
576 | retval = TRUE; |
---|
577 | for (i = 0; urls[i] != NULL && retval; i++) { |
---|
578 | /* get the path component */ |
---|
579 | url = g_strstrip (urls[i]); |
---|
580 | |
---|
581 | uri = camel_url_new (url, NULL); |
---|
582 | g_free (url); |
---|
583 | url = uri->path; |
---|
584 | uri->path = NULL; |
---|
585 | camel_url_free (uri); |
---|
586 | |
---|
587 | fd = open (url, O_RDONLY); |
---|
588 | if (fd == -1) { |
---|
589 | g_free (url); |
---|
590 | /* FIXME: okay, so what do we do in this case? */ |
---|
591 | continue; |
---|
592 | } |
---|
593 | |
---|
594 | stream = camel_stream_fs_new_with_fd (fd); |
---|
595 | message_rfc822_dnd (folder, stream, &ex); |
---|
596 | camel_object_unref (CAMEL_OBJECT (stream)); |
---|
597 | camel_object_unref (CAMEL_OBJECT (folder)); |
---|
598 | |
---|
599 | retval = !camel_exception_is_set (&ex); |
---|
600 | |
---|
601 | if (action == GNOME_Evolution_ShellComponentDnd_ACTION_MOVE && retval) |
---|
602 | unlink (url); |
---|
603 | |
---|
604 | g_free (url); |
---|
605 | } |
---|
606 | |
---|
607 | g_free (urls); |
---|
608 | break; |
---|
609 | case ACCEPTED_DND_TYPE_MESSAGE_RFC822: |
---|
610 | folder = mail_tool_uri_to_folder (physical_uri, 0, &ex); |
---|
611 | if (!folder) { |
---|
612 | camel_exception_clear (&ex); |
---|
613 | return FALSE; |
---|
614 | } |
---|
615 | |
---|
616 | /* write the message(s) out to a CamelStream so we can use it */ |
---|
617 | stream = camel_stream_mem_new (); |
---|
618 | camel_stream_write (stream, data->bytes._buffer, data->bytes._length); |
---|
619 | camel_stream_reset (stream); |
---|
620 | |
---|
621 | message_rfc822_dnd (folder, stream, &ex); |
---|
622 | camel_object_unref (CAMEL_OBJECT (stream)); |
---|
623 | camel_object_unref (CAMEL_OBJECT (folder)); |
---|
624 | break; |
---|
625 | case ACCEPTED_DND_TYPE_X_EVOLUTION_MESSAGE: |
---|
626 | folder = mail_tools_x_evolution_message_parse (data->bytes._buffer, |
---|
627 | data->bytes._length, |
---|
628 | &uids); |
---|
629 | |
---|
630 | if (!folder) |
---|
631 | return FALSE; |
---|
632 | |
---|
633 | mail_transfer_messages (folder, uids, |
---|
634 | action == GNOME_Evolution_ShellComponentDnd_ACTION_MOVE, |
---|
635 | physical_uri, 0, NULL, NULL); |
---|
636 | |
---|
637 | camel_object_unref (CAMEL_OBJECT (folder)); |
---|
638 | break; |
---|
639 | default: |
---|
640 | break; |
---|
641 | } |
---|
642 | |
---|
643 | camel_exception_clear (&ex); |
---|
644 | |
---|
645 | return retval; |
---|
646 | } |
---|
647 | |
---|
648 | |
---|
649 | static struct { |
---|
650 | char *name, **uri; |
---|
651 | CamelFolder **folder; |
---|
652 | } standard_folders[] = { |
---|
653 | { "Drafts", &default_drafts_folder_uri, &drafts_folder }, |
---|
654 | { "Outbox", &default_outbox_folder_uri, &outbox_folder }, |
---|
655 | { "Sent", &default_sent_folder_uri, &sent_folder }, |
---|
656 | }; |
---|
657 | |
---|
658 | static void |
---|
659 | unref_standard_folders (void) |
---|
660 | { |
---|
661 | int i; |
---|
662 | |
---|
663 | for (i = 0; i < sizeof (standard_folders) / sizeof (standard_folders[0]); i++) { |
---|
664 | if (standard_folders[i].folder) { |
---|
665 | CamelFolder *folder = *standard_folders[i].folder; |
---|
666 | |
---|
667 | *standard_folders[i].folder = NULL; |
---|
668 | |
---|
669 | if (CAMEL_OBJECT (folder)->ref_count == 1) |
---|
670 | d(printf ("About to finalise folder %s\n", folder->full_name)); |
---|
671 | else |
---|
672 | d(printf ("Folder %s still has %d extra ref%s on it\n", folder->full_name, |
---|
673 | CAMEL_OBJECT (folder)->ref_count - 1, |
---|
674 | CAMEL_OBJECT (folder)->ref_count - 1 == 1 ? "" : "s")); |
---|
675 | |
---|
676 | camel_object_unref (CAMEL_OBJECT (folder)); |
---|
677 | } |
---|
678 | } |
---|
679 | } |
---|
680 | |
---|
681 | static void |
---|
682 | got_folder (char *uri, CamelFolder *folder, void *data) |
---|
683 | { |
---|
684 | CamelFolder **fp = data; |
---|
685 | |
---|
686 | if (folder) { |
---|
687 | *fp = folder; |
---|
688 | |
---|
689 | camel_object_ref (CAMEL_OBJECT (folder)); |
---|
690 | |
---|
691 | /* emit a changed event, this is a little hack so that the folderinfo cache |
---|
692 | will update knowing whether this is the outbox_folder or not, etc */ |
---|
693 | if (folder == outbox_folder) { |
---|
694 | CamelFolderChangeInfo *changes = camel_folder_change_info_new(); |
---|
695 | |
---|
696 | camel_object_trigger_event((CamelObject *)folder, "folder_changed", changes); |
---|
697 | camel_folder_change_info_free(changes); |
---|
698 | } |
---|
699 | } |
---|
700 | } |
---|
701 | |
---|
702 | static void |
---|
703 | shell_client_destroy (GtkObject *object) |
---|
704 | { |
---|
705 | global_shell_client = NULL; |
---|
706 | } |
---|
707 | |
---|
708 | static void |
---|
709 | warning_clicked (GtkWidget *dialog, gpointer user_data) |
---|
710 | { |
---|
711 | gtk_widget_destroy (dialog); |
---|
712 | } |
---|
713 | |
---|
714 | static void |
---|
715 | owner_set_cb (EvolutionShellComponent *shell_component, |
---|
716 | EvolutionShellClient *shell_client, |
---|
717 | const char *evolution_homedir, |
---|
718 | gpointer user_data) |
---|
719 | { |
---|
720 | GNOME_Evolution_Shell corba_shell; |
---|
721 | const GSList *accounts; |
---|
722 | #ifdef ENABLE_NNTP |
---|
723 | const GSList *news; |
---|
724 | #endif |
---|
725 | int i; |
---|
726 | |
---|
727 | /* FIXME: should we ref this? */ |
---|
728 | global_shell_client = shell_client; |
---|
729 | gtk_signal_connect (GTK_OBJECT (shell_client), "destroy", |
---|
730 | shell_client_destroy, NULL); |
---|
731 | |
---|
732 | evolution_dir = g_strdup (evolution_homedir); |
---|
733 | mail_session_init (); |
---|
734 | |
---|
735 | async_event = mail_async_event_new(); |
---|
736 | |
---|
737 | storages_hash = g_hash_table_new (NULL, NULL); |
---|
738 | |
---|
739 | corba_shell = bonobo_object_corba_objref (BONOBO_OBJECT (shell_client)); |
---|
740 | |
---|
741 | vfolder_load_storage(corba_shell); |
---|
742 | |
---|
743 | accounts = mail_config_get_accounts (); |
---|
744 | mail_load_storages (corba_shell, accounts, TRUE); |
---|
745 | |
---|
746 | #ifdef ENABLE_NNTP |
---|
747 | news = mail_config_get_news (); |
---|
748 | mail_load_storages (corba_shell, news, FALSE); |
---|
749 | #endif |
---|
750 | |
---|
751 | mail_local_storage_startup (shell_client, evolution_dir); |
---|
752 | mail_importer_init (shell_client); |
---|
753 | |
---|
754 | for (i = 0; i < sizeof (standard_folders) / sizeof (standard_folders[0]); i++) { |
---|
755 | *standard_folders[i].uri = g_strdup_printf ("file://%s/local/%s", evolution_dir, standard_folders[i].name); |
---|
756 | mail_msg_wait (mail_get_folder (*standard_folders[i].uri, CAMEL_STORE_FOLDER_CREATE, |
---|
757 | got_folder, standard_folders[i].folder, mail_thread_new)); |
---|
758 | } |
---|
759 | |
---|
760 | mail_autoreceive_setup (); |
---|
761 | |
---|
762 | { |
---|
763 | /* setup the global quick-search context */ |
---|
764 | char *user = g_strdup_printf ("%s/searches.xml", evolution_dir); |
---|
765 | char *system = g_strdup (EVOLUTION_DATADIR "/evolution/vfoldertypes.xml"); |
---|
766 | |
---|
767 | search_context = rule_context_new (); |
---|
768 | gtk_object_set_data_full (GTK_OBJECT (search_context), "user", user, g_free); |
---|
769 | gtk_object_set_data_full (GTK_OBJECT (search_context), "system", system, g_free); |
---|
770 | |
---|
771 | rule_context_add_part_set (search_context, "partset", filter_part_get_type (), |
---|
772 | rule_context_add_part, rule_context_next_part); |
---|
773 | |
---|
774 | rule_context_add_rule_set (search_context, "ruleset", filter_rule_get_type (), |
---|
775 | rule_context_add_rule, rule_context_next_rule); |
---|
776 | |
---|
777 | rule_context_load (search_context, system, user); |
---|
778 | } |
---|
779 | |
---|
780 | if (mail_config_is_corrupt ()) { |
---|
781 | GtkWidget *dialog; |
---|
782 | |
---|
783 | dialog = gnome_warning_dialog (_("Some of your mail settings seem corrupt, " |
---|
784 | "please check that everything is in order.")); |
---|
785 | gtk_signal_connect (GTK_OBJECT (dialog), "clicked", warning_clicked, NULL); |
---|
786 | gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); |
---|
787 | gtk_widget_show (dialog); |
---|
788 | } |
---|
789 | } |
---|
790 | |
---|
791 | static void |
---|
792 | free_storage (gpointer service, gpointer storage, gpointer data) |
---|
793 | { |
---|
794 | if (service) { |
---|
795 | mail_note_store_remove((CamelStore *)service); |
---|
796 | camel_service_disconnect (CAMEL_SERVICE (service), TRUE, NULL); |
---|
797 | camel_object_unref (CAMEL_OBJECT (service)); |
---|
798 | } |
---|
799 | |
---|
800 | if (storage) |
---|
801 | bonobo_object_unref (BONOBO_OBJECT (storage)); |
---|
802 | } |
---|
803 | |
---|
804 | static void |
---|
805 | debug_cb (EvolutionShellComponent *shell_component, gpointer user_data) |
---|
806 | { |
---|
807 | extern gboolean camel_verbose_debug; |
---|
808 | |
---|
809 | camel_verbose_debug = 1; |
---|
810 | } |
---|
811 | |
---|
812 | static void |
---|
813 | interactive_cb (EvolutionShellComponent *shell_component, gboolean on, gpointer user_data) |
---|
814 | { |
---|
815 | mail_session_enable_interaction(on); |
---|
816 | } |
---|
817 | |
---|
818 | static void |
---|
819 | handle_external_uri_cb (EvolutionShellComponent *shell_component, |
---|
820 | const char *uri, |
---|
821 | void *data) |
---|
822 | { |
---|
823 | if (strncmp (uri, "mailto:", 7) != 0) { |
---|
824 | /* FIXME: Exception? The EvolutionShellComponent object should |
---|
825 | give me a chance to do so, but currently it doesn't. */ |
---|
826 | g_warning ("Invalid URI requested to mail component -- %s", uri); |
---|
827 | return; |
---|
828 | } |
---|
829 | |
---|
830 | /* FIXME: Sigh. This shouldn't be here. But the code is messy, so |
---|
831 | I'll just put it here anyway. */ |
---|
832 | send_to_url (uri); |
---|
833 | } |
---|
834 | |
---|
835 | static void |
---|
836 | user_create_new_item_cb (EvolutionShellComponent *shell_component, |
---|
837 | const char *id, |
---|
838 | const char *parent_folder_physical_uri, |
---|
839 | const char *parent_folder_type, |
---|
840 | gpointer data) |
---|
841 | { |
---|
842 | if (!strcmp (id, "message")) { |
---|
843 | send_to_url (NULL); |
---|
844 | return; |
---|
845 | } |
---|
846 | |
---|
847 | g_warning ("Don't know how to create item of type \"%s\"", id); |
---|
848 | } |
---|
849 | |
---|
850 | static gboolean |
---|
851 | idle_quit (gpointer user_data) |
---|
852 | { |
---|
853 | static int shutdown_vfolder = FALSE; |
---|
854 | static int shutdown_shutdown = FALSE; |
---|
855 | |
---|
856 | if (!shutdown_shutdown) { |
---|
857 | if (mail_msg_active(-1)) { |
---|
858 | /* short sleep? */ |
---|
859 | return TRUE; |
---|
860 | } |
---|
861 | |
---|
862 | if (!shutdown_vfolder) { |
---|
863 | shutdown_vfolder = TRUE; |
---|
864 | mail_vfolder_shutdown(); |
---|
865 | return TRUE; |
---|
866 | } |
---|
867 | |
---|
868 | if (mail_async_event_destroy(async_event) == -1) |
---|
869 | return TRUE; |
---|
870 | |
---|
871 | shutdown_shutdown = TRUE; |
---|
872 | g_hash_table_foreach (storages_hash, free_storage, NULL); |
---|
873 | g_hash_table_destroy (storages_hash); |
---|
874 | storages_hash = NULL; |
---|
875 | } |
---|
876 | |
---|
877 | if (e_list_length (folder_browser_factory_get_control_list ())) |
---|
878 | return TRUE; |
---|
879 | |
---|
880 | gtk_main_quit (); |
---|
881 | |
---|
882 | return FALSE; |
---|
883 | } |
---|
884 | |
---|
885 | static void owner_unset_cb (EvolutionShellComponent *shell_component, gpointer user_data); |
---|
886 | |
---|
887 | /* Table for signal handler setup/cleanup */ |
---|
888 | static struct { |
---|
889 | char *sig; |
---|
890 | GtkSignalFunc func; |
---|
891 | int hand; |
---|
892 | } shell_component_handlers[] = { |
---|
893 | { "owner_set", owner_set_cb, }, |
---|
894 | { "owner_unset", owner_unset_cb, }, |
---|
895 | { "debug", debug_cb, }, |
---|
896 | { "interactive", interactive_cb }, |
---|
897 | { "destroy", owner_unset_cb, }, |
---|
898 | { "handle_external_uri", handle_external_uri_cb, }, |
---|
899 | { "user_create_new_item", user_create_new_item_cb } |
---|
900 | }; |
---|
901 | |
---|
902 | static void |
---|
903 | owner_unset_cb (EvolutionShellComponent *shell_component, gpointer user_data) |
---|
904 | { |
---|
905 | int i; |
---|
906 | |
---|
907 | for (i=0;i<sizeof(shell_component_handlers)/sizeof(shell_component_handlers[0]);i++) |
---|
908 | gtk_signal_disconnect((GtkObject *)shell_component, shell_component_handlers[i].hand); |
---|
909 | |
---|
910 | if (mail_config_get_empty_trash_on_exit ()) |
---|
911 | empty_trash (NULL, NULL, NULL); |
---|
912 | |
---|
913 | unref_standard_folders (); |
---|
914 | mail_importer_uninit (); |
---|
915 | |
---|
916 | global_shell_client = NULL; |
---|
917 | mail_session_enable_interaction (FALSE); |
---|
918 | |
---|
919 | gtk_object_unref (GTK_OBJECT (search_context)); |
---|
920 | search_context = NULL; |
---|
921 | |
---|
922 | g_timeout_add(100, idle_quit, NULL); |
---|
923 | } |
---|
924 | |
---|
925 | static BonoboObject * |
---|
926 | create_component (void) |
---|
927 | { |
---|
928 | EvolutionShellComponentDndDestinationFolder *destination_interface; |
---|
929 | MailOfflineHandler *offline_handler; |
---|
930 | int i; |
---|
931 | |
---|
932 | shell_component = evolution_shell_component_new (folder_types, |
---|
933 | schema_types, |
---|
934 | create_view, |
---|
935 | create_folder, |
---|
936 | remove_folder, |
---|
937 | xfer_folder, |
---|
938 | /*populate_folder_context_menu*/NULL, |
---|
939 | get_dnd_selection, |
---|
940 | NULL); |
---|
941 | |
---|
942 | destination_interface = evolution_shell_component_dnd_destination_folder_new (destination_folder_handle_motion, |
---|
943 | destination_folder_handle_drop, |
---|
944 | shell_component); |
---|
945 | |
---|
946 | bonobo_object_add_interface (BONOBO_OBJECT (shell_component), |
---|
947 | BONOBO_OBJECT (destination_interface)); |
---|
948 | |
---|
949 | evolution_mail_config_wizard_init (); |
---|
950 | |
---|
951 | evolution_shell_component_add_user_creatable_item (shell_component, "message", _("New Mail Message"), _("New _Mail Message"), 'm'); |
---|
952 | |
---|
953 | for (i=0;i<sizeof(shell_component_handlers)/sizeof(shell_component_handlers[0]);i++) { |
---|
954 | shell_component_handlers[i].hand = gtk_signal_connect(GTK_OBJECT(shell_component), |
---|
955 | shell_component_handlers[i].sig, |
---|
956 | shell_component_handlers[i].func, NULL); |
---|
957 | } |
---|
958 | |
---|
959 | offline_handler = mail_offline_handler_new (); |
---|
960 | bonobo_object_add_interface (BONOBO_OBJECT (shell_component), BONOBO_OBJECT (offline_handler)); |
---|
961 | |
---|
962 | return BONOBO_OBJECT (shell_component); |
---|
963 | } |
---|
964 | |
---|
965 | void |
---|
966 | component_factory_init (void) |
---|
967 | { |
---|
968 | BonoboObject *shell_component; |
---|
969 | int result; |
---|
970 | |
---|
971 | shell_component = create_component (); |
---|
972 | result = oaf_active_server_register (COMPONENT_ID, bonobo_object_corba_objref (shell_component)); |
---|
973 | if (result == OAF_REG_ERROR) { |
---|
974 | e_notice (NULL, GNOME_MESSAGE_BOX_ERROR, |
---|
975 | _("Cannot initialize Evolution's mail component.")); |
---|
976 | exit (1); |
---|
977 | } else if (result == OAF_REG_ALREADY_ACTIVE) { |
---|
978 | g_warning ("evolution-mail is already running"); |
---|
979 | exit (1); |
---|
980 | } |
---|
981 | |
---|
982 | if (evolution_mail_config_factory_init () == FALSE) { |
---|
983 | e_notice (NULL, GNOME_MESSAGE_BOX_ERROR, |
---|
984 | _("Cannot initialize Evolution's mail config component.")); |
---|
985 | exit (1); |
---|
986 | } |
---|
987 | |
---|
988 | if (evolution_folder_info_factory_init () == FALSE) { |
---|
989 | e_notice (NULL, GNOME_MESSAGE_BOX_ERROR, |
---|
990 | _("Cannot initialize Evolution's folder info component.")); |
---|
991 | exit (1); |
---|
992 | } |
---|
993 | } |
---|
994 | |
---|
995 | static void |
---|
996 | notify_listener (const Bonobo_Listener listener, |
---|
997 | GNOME_Evolution_Storage_Result corba_result) |
---|
998 | { |
---|
999 | CORBA_any any; |
---|
1000 | CORBA_Environment ev; |
---|
1001 | |
---|
1002 | CORBA_exception_init (&ev); |
---|
1003 | |
---|
1004 | any._type = TC_GNOME_Evolution_Storage_Result; |
---|
1005 | any._value = &corba_result; |
---|
1006 | |
---|
1007 | Bonobo_Listener_event (listener, "result", &any, &ev); |
---|
1008 | |
---|
1009 | CORBA_exception_free (&ev); |
---|
1010 | } |
---|
1011 | |
---|
1012 | static void |
---|
1013 | storage_create_folder (EvolutionStorage *storage, |
---|
1014 | const Bonobo_Listener listener, |
---|
1015 | const char *path, |
---|
1016 | const char *type, |
---|
1017 | const char *description, |
---|
1018 | const char *parent_physical_uri, |
---|
1019 | gpointer user_data) |
---|
1020 | { |
---|
1021 | CamelStore *store = user_data; |
---|
1022 | CamelFolderInfo *root, *fi; |
---|
1023 | char *name; |
---|
1024 | CamelURL *url; |
---|
1025 | CamelException ex; |
---|
1026 | |
---|
1027 | /* We could just use 'path' always here? */ |
---|
1028 | |
---|
1029 | if (strcmp (type, "mail") != 0) { |
---|
1030 | notify_listener (listener, GNOME_Evolution_Storage_UNSUPPORTED_TYPE); |
---|
1031 | return; |
---|
1032 | } |
---|
1033 | |
---|
1034 | name = strrchr (path, '/'); |
---|
1035 | if (!name) { |
---|
1036 | notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI); |
---|
1037 | return; |
---|
1038 | } |
---|
1039 | name++; |
---|
1040 | |
---|
1041 | camel_exception_init (&ex); |
---|
1042 | if (*parent_physical_uri) { |
---|
1043 | url = camel_url_new (parent_physical_uri, NULL); |
---|
1044 | if (!url) { |
---|
1045 | notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI); |
---|
1046 | return; |
---|
1047 | } |
---|
1048 | |
---|
1049 | root = camel_store_create_folder (store, url->fragment?url->fragment:url->path + 1, name, &ex); |
---|
1050 | camel_url_free (url); |
---|
1051 | } else |
---|
1052 | root = camel_store_create_folder (store, NULL, name, &ex); |
---|
1053 | |
---|
1054 | if (camel_exception_is_set (&ex)) { |
---|
1055 | /* FIXME: do better than this */ |
---|
1056 | camel_exception_clear (&ex); |
---|
1057 | notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI); |
---|
1058 | return; |
---|
1059 | } |
---|
1060 | |
---|
1061 | if (camel_store_supports_subscriptions (store)) { |
---|
1062 | for (fi = root; fi; fi = fi->child) |
---|
1063 | camel_store_subscribe_folder (store, fi->full_name, NULL); |
---|
1064 | } |
---|
1065 | |
---|
1066 | camel_store_free_folder_info (store, root); |
---|
1067 | |
---|
1068 | notify_listener (listener, GNOME_Evolution_Storage_OK); |
---|
1069 | } |
---|
1070 | |
---|
1071 | static void |
---|
1072 | storage_remove_folder (EvolutionStorage *storage, |
---|
1073 | const Bonobo_Listener listener, |
---|
1074 | const char *path, |
---|
1075 | const char *physical_uri, |
---|
1076 | gpointer user_data) |
---|
1077 | { |
---|
1078 | CamelStore *store = user_data; |
---|
1079 | CamelURL *url = NULL; |
---|
1080 | char *name; |
---|
1081 | CamelException ex; |
---|
1082 | |
---|
1083 | g_warning ("storage_remove_folder: path=\"%s\"; uri=\"%s\"", path, physical_uri); |
---|
1084 | |
---|
1085 | if (!path || !physical_uri || !strncmp (physical_uri, "vtrash:", 7)) { |
---|
1086 | notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI); |
---|
1087 | return; |
---|
1088 | } |
---|
1089 | |
---|
1090 | url = camel_url_new (physical_uri, NULL); |
---|
1091 | if (!url) { |
---|
1092 | notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI); |
---|
1093 | return; |
---|
1094 | } |
---|
1095 | |
---|
1096 | if (!*path) { |
---|
1097 | camel_url_free (url); |
---|
1098 | notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI); |
---|
1099 | return; |
---|
1100 | } |
---|
1101 | |
---|
1102 | camel_exception_init (&ex); |
---|
1103 | |
---|
1104 | if (url->fragment) |
---|
1105 | name = url->fragment; |
---|
1106 | else if (url->path && url->path[0]) |
---|
1107 | name = url->path+1; |
---|
1108 | else |
---|
1109 | name = ""; |
---|
1110 | |
---|
1111 | if (camel_store_supports_subscriptions (store)) |
---|
1112 | camel_store_unsubscribe_folder (store, name, NULL); |
---|
1113 | |
---|
1114 | camel_store_delete_folder (store, name, &ex); |
---|
1115 | |
---|
1116 | camel_url_free (url); |
---|
1117 | if (camel_exception_is_set (&ex)) |
---|
1118 | goto exception; |
---|
1119 | |
---|
1120 | evolution_storage_removed_folder (storage, path); |
---|
1121 | |
---|
1122 | notify_listener (listener, GNOME_Evolution_Storage_OK); |
---|
1123 | return; |
---|
1124 | |
---|
1125 | exception: |
---|
1126 | /* FIXME: do better than this... */ |
---|
1127 | camel_exception_clear (&ex); |
---|
1128 | notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI); |
---|
1129 | } |
---|
1130 | |
---|
1131 | static void |
---|
1132 | storage_xfer_folder (EvolutionStorage *storage, |
---|
1133 | const Bonobo_Listener listener, |
---|
1134 | const char *source_path, |
---|
1135 | const char *destination_path, |
---|
1136 | gboolean remove_source, |
---|
1137 | CamelStore *store) |
---|
1138 | { |
---|
1139 | CamelException ex; |
---|
1140 | char *src, *dst; |
---|
1141 | char *p, c, sep; |
---|
1142 | |
---|
1143 | d(printf("Transfer folder on store source = '%s' dest = '%s'\n", source_path, destination_path)); |
---|
1144 | |
---|
1145 | /* Remap the 'path' to the camel friendly name based on the store dir separator */ |
---|
1146 | sep = store->dir_sep; |
---|
1147 | src = g_strdup(source_path[0]=='/'?source_path+1:source_path); |
---|
1148 | dst = g_strdup(destination_path[0]=='/'?destination_path+1:destination_path); |
---|
1149 | if (sep != '/') { |
---|
1150 | p = src; |
---|
1151 | while ((c = *p++)) |
---|
1152 | if (c == '/') |
---|
1153 | p[-1] = sep; |
---|
1154 | |
---|
1155 | p = dst; |
---|
1156 | while ((c = *p++)) |
---|
1157 | if (c == '/') |
---|
1158 | p[-1] = sep; |
---|
1159 | } |
---|
1160 | |
---|
1161 | camel_exception_init (&ex); |
---|
1162 | if (remove_source) { |
---|
1163 | d(printf("trying to rename\n")); |
---|
1164 | camel_store_rename_folder(store, src, dst, &ex); |
---|
1165 | if (camel_exception_is_set(&ex)) |
---|
1166 | notify_listener (listener, GNOME_Evolution_Storage_GENERIC_ERROR); |
---|
1167 | else |
---|
1168 | notify_listener (listener, GNOME_Evolution_Storage_OK); |
---|
1169 | } else { |
---|
1170 | d(printf("No remove, can't rename\n")); |
---|
1171 | /* FIXME: Implement folder 'copy' for remote stores */ |
---|
1172 | /* This exception never goes anywhere, so it doesn't need translating or using */ |
---|
1173 | notify_listener (listener, GNOME_Evolution_Storage_UNSUPPORTED_OPERATION); |
---|
1174 | } |
---|
1175 | |
---|
1176 | g_free(src); |
---|
1177 | g_free(dst); |
---|
1178 | |
---|
1179 | camel_exception_clear (&ex); |
---|
1180 | } |
---|
1181 | |
---|
1182 | static void |
---|
1183 | add_storage (const char *name, const char *uri, CamelService *store, |
---|
1184 | GNOME_Evolution_Shell corba_shell, CamelException *ex) |
---|
1185 | { |
---|
1186 | EvolutionStorage *storage; |
---|
1187 | EvolutionStorageResult res; |
---|
1188 | |
---|
1189 | storage = evolution_storage_new (name, uri, "mailstorage"); |
---|
1190 | gtk_signal_connect (GTK_OBJECT (storage), "create_folder", storage_create_folder, store); |
---|
1191 | gtk_signal_connect (GTK_OBJECT (storage), "remove_folder", storage_remove_folder, store); |
---|
1192 | gtk_signal_connect ((GtkObject *)storage, "xfer_folder", storage_xfer_folder, store); |
---|
1193 | |
---|
1194 | res = evolution_storage_register_on_shell (storage, corba_shell); |
---|
1195 | |
---|
1196 | switch (res) { |
---|
1197 | case EVOLUTION_STORAGE_OK: |
---|
1198 | mail_hash_storage (store, storage); |
---|
1199 | mail_note_store((CamelStore *)store, storage, CORBA_OBJECT_NIL, NULL, NULL); |
---|
1200 | /* falllll */ |
---|
1201 | case EVOLUTION_STORAGE_ERROR_ALREADYREGISTERED: |
---|
1202 | case EVOLUTION_STORAGE_ERROR_EXISTS: |
---|
1203 | return; |
---|
1204 | default: |
---|
1205 | camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, |
---|
1206 | _("Cannot register storage with shell")); |
---|
1207 | break; |
---|
1208 | } |
---|
1209 | } |
---|
1210 | |
---|
1211 | void |
---|
1212 | mail_load_storage_by_uri (GNOME_Evolution_Shell shell, const char *uri, const char *name) |
---|
1213 | { |
---|
1214 | CamelException ex; |
---|
1215 | CamelService *store; |
---|
1216 | CamelProvider *prov; |
---|
1217 | |
---|
1218 | camel_exception_init (&ex); |
---|
1219 | |
---|
1220 | /* Load the service (don't connect!). Check its provider and |
---|
1221 | * see if this belongs in the shell's folder list. If so, add |
---|
1222 | * it. |
---|
1223 | */ |
---|
1224 | |
---|
1225 | prov = camel_session_get_provider (session, uri, &ex); |
---|
1226 | if (prov == NULL) { |
---|
1227 | /* FIXME: real error dialog */ |
---|
1228 | g_warning ("couldn't get service %s: %s\n", uri, |
---|
1229 | camel_exception_get_description (&ex)); |
---|
1230 | camel_exception_clear (&ex); |
---|
1231 | return; |
---|
1232 | } |
---|
1233 | |
---|
1234 | if (!(prov->flags & CAMEL_PROVIDER_IS_STORAGE) || |
---|
1235 | (prov->flags & CAMEL_PROVIDER_IS_EXTERNAL)) |
---|
1236 | return; |
---|
1237 | |
---|
1238 | store = camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex); |
---|
1239 | if (store == NULL) { |
---|
1240 | /* FIXME: real error dialog */ |
---|
1241 | g_warning ("couldn't get service %s: %s\n", uri, |
---|
1242 | camel_exception_get_description (&ex)); |
---|
1243 | camel_exception_clear (&ex); |
---|
1244 | return; |
---|
1245 | } |
---|
1246 | |
---|
1247 | if (name == NULL) { |
---|
1248 | char *service_name; |
---|
1249 | |
---|
1250 | service_name = camel_service_get_name (store, TRUE); |
---|
1251 | add_storage (service_name, uri, store, shell, &ex); |
---|
1252 | g_free (service_name); |
---|
1253 | } else |
---|
1254 | add_storage (name, uri, store, shell, &ex); |
---|
1255 | |
---|
1256 | if (camel_exception_is_set (&ex)) { |
---|
1257 | /* FIXME: real error dialog */ |
---|
1258 | g_warning ("Cannot load storage: %s", |
---|
1259 | camel_exception_get_description (&ex)); |
---|
1260 | camel_exception_clear (&ex); |
---|
1261 | } |
---|
1262 | |
---|
1263 | camel_object_unref (CAMEL_OBJECT (store)); |
---|
1264 | } |
---|
1265 | |
---|
1266 | /* FIXME: 'is_account_data' is an ugly hack, if we remove support for NNTP we can take it out -- fejj */ |
---|
1267 | void |
---|
1268 | mail_load_storages (GNOME_Evolution_Shell shell, const GSList *sources, gboolean is_account_data) |
---|
1269 | { |
---|
1270 | CamelException ex; |
---|
1271 | const GSList *iter; |
---|
1272 | |
---|
1273 | camel_exception_init (&ex); |
---|
1274 | |
---|
1275 | /* Load each service (don't connect!). Check its provider and |
---|
1276 | * see if this belongs in the shell's folder list. If so, add |
---|
1277 | * it. |
---|
1278 | */ |
---|
1279 | |
---|
1280 | for (iter = sources; iter; iter = iter->next) { |
---|
1281 | const MailConfigAccount *account = NULL; |
---|
1282 | const MailConfigService *service = NULL; |
---|
1283 | char *name; |
---|
1284 | |
---|
1285 | if (is_account_data) { |
---|
1286 | account = iter->data; |
---|
1287 | service = account->source; |
---|
1288 | name = account->name; |
---|
1289 | } else { |
---|
1290 | service = iter->data; |
---|
1291 | name = NULL; |
---|
1292 | } |
---|
1293 | |
---|
1294 | if (service == NULL || service->url == NULL || service->url[0] == '\0' || !service->enabled) |
---|
1295 | continue; |
---|
1296 | |
---|
1297 | mail_load_storage_by_uri (shell, service->url, name); |
---|
1298 | } |
---|
1299 | } |
---|
1300 | |
---|
1301 | void |
---|
1302 | mail_hash_storage (CamelService *store, EvolutionStorage *storage) |
---|
1303 | { |
---|
1304 | camel_object_ref (CAMEL_OBJECT (store)); |
---|
1305 | g_hash_table_insert (storages_hash, store, storage); |
---|
1306 | } |
---|
1307 | |
---|
1308 | EvolutionStorage* |
---|
1309 | mail_lookup_storage (CamelStore *store) |
---|
1310 | { |
---|
1311 | EvolutionStorage *storage; |
---|
1312 | |
---|
1313 | /* Because the storages_hash holds a reference to each store |
---|
1314 | * used as a key in it, none of them will ever be gc'ed, meaning |
---|
1315 | * any call to camel_session_get_{service,store} with the same |
---|
1316 | * URL will always return the same object. So this works. |
---|
1317 | */ |
---|
1318 | |
---|
1319 | storage = g_hash_table_lookup (storages_hash, store); |
---|
1320 | if (storage) |
---|
1321 | bonobo_object_ref (BONOBO_OBJECT (storage)); |
---|
1322 | |
---|
1323 | return storage; |
---|
1324 | } |
---|
1325 | |
---|
1326 | static void |
---|
1327 | store_disconnect(CamelStore *store, void *event_data, void *data) |
---|
1328 | { |
---|
1329 | camel_service_disconnect (CAMEL_SERVICE (store), TRUE, NULL); |
---|
1330 | camel_object_unref (CAMEL_OBJECT (store)); |
---|
1331 | } |
---|
1332 | |
---|
1333 | void |
---|
1334 | mail_remove_storage (CamelStore *store) |
---|
1335 | { |
---|
1336 | EvolutionStorage *storage; |
---|
1337 | EvolutionShellClient *shell_client; |
---|
1338 | GNOME_Evolution_Shell corba_shell; |
---|
1339 | |
---|
1340 | /* Because the storages_hash holds a reference to each store |
---|
1341 | * used as a key in it, none of them will ever be gc'ed, meaning |
---|
1342 | * any call to camel_session_get_{service,store} with the same |
---|
1343 | * URL will always return the same object. So this works. |
---|
1344 | */ |
---|
1345 | |
---|
1346 | storage = g_hash_table_lookup (storages_hash, store); |
---|
1347 | g_hash_table_remove (storages_hash, store); |
---|
1348 | |
---|
1349 | /* so i guess potentially we could have a race, add a store while one |
---|
1350 | being removed. ?? */ |
---|
1351 | mail_note_store_remove(store); |
---|
1352 | |
---|
1353 | shell_client = evolution_shell_component_get_owner (shell_component); |
---|
1354 | corba_shell = bonobo_object_corba_objref (BONOBO_OBJECT (shell_client)); |
---|
1355 | |
---|
1356 | evolution_storage_deregister_on_shell (storage, corba_shell); |
---|
1357 | |
---|
1358 | mail_async_event_emit(async_event, MAIL_ASYNC_THREAD, (MailAsyncFunc)store_disconnect, store, NULL, NULL); |
---|
1359 | } |
---|
1360 | |
---|
1361 | void |
---|
1362 | mail_remove_storage_by_uri (const char *uri) |
---|
1363 | { |
---|
1364 | CamelProvider *prov; |
---|
1365 | CamelService *store; |
---|
1366 | |
---|
1367 | prov = camel_session_get_provider (session, uri, NULL); |
---|
1368 | if (!prov) |
---|
1369 | return; |
---|
1370 | if (!(prov->flags & CAMEL_PROVIDER_IS_STORAGE) || |
---|
1371 | (prov->flags & CAMEL_PROVIDER_IS_EXTERNAL)) |
---|
1372 | return; |
---|
1373 | |
---|
1374 | store = camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, NULL); |
---|
1375 | if (store != NULL) { |
---|
1376 | mail_remove_storage (CAMEL_STORE (store)); |
---|
1377 | camel_object_unref (CAMEL_OBJECT (store)); |
---|
1378 | } |
---|
1379 | } |
---|
1380 | |
---|
1381 | int |
---|
1382 | mail_storages_count (void) |
---|
1383 | { |
---|
1384 | return g_hash_table_size (storages_hash); |
---|
1385 | } |
---|
1386 | |
---|
1387 | void |
---|
1388 | mail_storages_foreach (GHFunc func, gpointer data) |
---|
1389 | { |
---|
1390 | g_hash_table_foreach (storages_hash, func, data); |
---|
1391 | } |
---|