aboutsummaryrefslogtreecommitdiffstats
path: root/mail
diff options
context:
space:
mode:
Diffstat (limited to 'mail')
-rw-r--r--mail/ChangeLog645
-rw-r--r--mail/Makefile.am270
-rw-r--r--mail/component-factory.c1668
-rw-r--r--mail/em-folder-view.c101
-rw-r--r--mail/em-junk-filter.c327
-rw-r--r--mail/em-junk-filter.h30
-rw-r--r--mail/em-junk-plugin.c24
-rw-r--r--mail/em-junk-plugin.h47
-rw-r--r--mail/em-popup.c50
-rw-r--r--mail/em-popup.h15
-rw-r--r--mail/mail-local.c1571
-rw-r--r--mail/mail-ops.c159
-rw-r--r--mail/mail-ops.h4
-rw-r--r--mail/mail-session.c18
-rw-r--r--mail/mail-tools.c29
-rw-r--r--mail/mail-vfolder.c45
-rw-r--r--mail/message-list.c129
-rw-r--r--mail/message-list.h3
18 files changed, 4146 insertions, 989 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index 14c0682cd2..b4c757d5b8 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,366 +1,13 @@
-2003-11-10 Not Zed <NotZed@Ximian.com>
+2003-10-23 Radek Doulik <rodo@ximian.com>
- * em-format-html.c (em_format_html_multipart_signed_sign): changed
- for cipher context api changes.
- * em-format.c (emf_multipart_signed): ditto.
-
-2003-11-07 Not Zed <NotZed@Ximian.com>
-
- * mail-config.glade: added security_information_dialog (probably
- temporarily in this file).
-
- * em-format.c (em_format_is_attachment): also treat pkcs7-mime as
- non-attachment.
- (emf_application_xpkcs7mime): no longer need to worry about
- scanning the part.
-
-2003-11-07 Dan Winship <danw@ximian.com>
-
- * message-list.c: Don't #include e-name-western.h, since the code
- that uses it is commented out, and we want to remove the local
- copy, but we don't want to make the mailer depend on the e-d-s
- copy if it's not even going to be using it.
-
-2003-11-07 JP Rosevear <jpr@ximian.com>
-
- * Makefile.am: build the marshall files right at the beginning
-
-2003-11-07 JP Rosevear <jpr@ximian.com>
-
- * Makefile.am: Make sure the marshal files are listed above other
- sources
-
-2003-11-06 Jeffrey Stedfast <fejj@ximian.com>
-
- * em-migrate.c (em_migrate_filter_file): Call em_migrate_uri()
- instead of em_uri_from_camel().
- (em_migrate_uri): Special-case file: uri's by converting them into
- email://local@local/ uri's since these folders will have been
- migrated to the newer mbox tree structure.
-
-2003-11-06 Jeffrey Stedfast <fejj@ximian.com>
-
- * mail-vfolder.c (mail_vfolder_delete_uri): User vfolder rules
- should be in ${evolution_dir}/mail/vfolders.xml rather than
- ${evolution_dir}/vfolders.xml
- (mail_vfolder_rename_uri): Same.
- (store_folder_deleted): Here too.
- (store_folder_renamed): And here.
- (vfolder_load_storage): Again here.
- (vfolder_editor_response): Same.
- (edit_rule_response): And here.
- (new_rule_clicked): Here too.
-
- * mail-session.c (main_get_filter_driver): User filter rules
- should be in ${evolution_dir}/mail/filters.xml rather than
- ${evolution_dir}/filters.xml
-
- * mail-autofilter.c (filter_gui_add_from_message): Same.
- (mail_filter_rename_uri): And here.
- (mail_filter_delete_uri): Here too.
-
- * em-utils.c (filter_editor_response): Again here.
- (em_utils_edit_filters): Same.
-
- * em-migrate.c (em_migrate_filter_file): Same (also for
- vfolders.xml)
-
-2003-11-05 Jeffrey Stedfast <fejj@ximian.com>
-
- * em-migrate.[c,h]: New source files to migrate from the old mail
- directory to the new mail directory.
-
- * mail-component.c (mail_component_init): Changed to use
- ~/.evolution and added code to migrate the old mail folders over
- if ~/.evolution/mail does not yet exist.
-
-2003-11-03 Ettore Perazzoli <ettore@ximian.com>
-
- * GNOME_Evolution_Mail.server.in.in: Use "evolution2:config_item"
- properties for the config item instead of "evolution:config_item"
- ones.
-
-2003-11-01 Jeffrey Stedfast <fejj@ximian.com>
-
- * em-folder-view.c: setup filter-on-thread and vfolder-on-thread.
-
- * mail-autofilter.c (rule_from_message): handle AUTO_THREAD
- (rule_match_thread): new function to setup a filter on a msgid
-
-2003-10-31 Not Zed <NotZed@Ximian.com>
-
- * mail-config.glade: Rearranged smime config slightly, and added
- encrypt key preference.
-
- * mail-account-gui.c (mail_account_gui_save,
- mail_account_gui_new): enable smime always if have_nss. Added new
- options in glade file and handle changed names.
- (smime_changed, smime_sign_key_select, smime_sign_key_clear)
- (smime_encrypt_key_select, smime_encrypt_key_clear): Add a bunch
- of mostly dummy UI behaviour management stuff.
-
-2003-10-30 Not Zed <NotZed@Ximian.com>
-
- * em-format.c (em_format_is_inline): show application/x-pkcs7-mime
- inline always by default.
-
-2003-10-30 Not Zed <NotZed@Ximian.com>
-
- * em-format.c (emf_multipart_signed): handle
- application/x-pkcs7-signature.
-
-2003-10-29 Not Zed <NotZed@Ximian.com>
-
- * em-format-html.c (em_format_html_multipart_signed_sign): handle
- application/x-pkcs7-signature.
-
- * em-format.c (emf_application_xpkcs7mime): Handle
- application/x-pkcs7-mime.
-
-2003-10-29 Jeffrey Stedfast <fejj@ximian.com>
-
- * em-account-prefs.h: Changed the OAFIID.
-
- * em-composer-prefs.h: Changed the OAFIID.
-
- * em-mailer-prefs.h: Changed the OAFIID.
-
- * GNOME_Evolution_Mail.server.in.in: Changed OAFIIDs for the prefs
- controls.
-
-2003-10-29 Jeffrey Stedfast <fejj@ximian.com>
-
- * GNOME_Evolution_Mail.server.in.in: Nuked the MailConfig
- interface stuff.
-
- * Mailer.idl: Removed. None of the interfaces are needed/used
- anymore.
-
- * folder-info.[c,h]: Removed. The summary was the only thing that
- needed/used this code and it has been nuked into oblivion, so
- these interfaces are no longer needed.
-
- * mail-config.c: Removed old crufty CORBA interface snot that is
- no longer needed or used.
-
-2003-10-27 Jeffrey Stedfast <fejj@ximian.com>
-
- * Fixes bug #49816
-
- * em-popup.c (emp_part_popup_reply_sender): No need to pass a
- parent window arg anymore.
- (emp_part_popup_reply_list): Same.
- (emp_part_popup_reply_all): Here too.
- (emp_part_popup_forward): Same.
- (emp_uri_popup_address_send): Here too.
-
- * em-folder-browser.c (emfb_mail_compose): No need to pass a
- parent window arg anymore.
- (emfb_mail_post): Same.
-
- * em-folder-view.c (emfv_message_reply): Don't pass a parent
- window argument anymore.
- (emfv_popup_forward): Same.
- (emfv_popup_resend): Same here.
- (em_folder_view_open_selected): Same.
- (emfv_message_forward_attached): Here too.
- (emfv_message_forward_inline): And here.
- (emfv_message_forward_quoted): Same.
- (emfv_message_redirect): Here too.
- (emfv_message_post_reply): And here.
- (emfv_format_link_clicked): ANd finally here.
-
- * em-utils.c (create_new_composer): Don't set_transient_for()
- anymore.
- (em_utils_compose_new_message): No longer takes a parent window
- argument.
- (em_utils_forward_attached): No longer takes a parent window arg.
- (em_utils_forward_inline): Same.
- (em_utils_forward_quoted): Same.
- (em_utils_forward_message): Same.
- (em_utils_forward_messages): Here too.
- (redirect_get_composer): Don't set_transient_for() here either.
- (em_utils_redirect_message): No longer takes a parent window arg.
- (em_utils_redirect_message_by_uid): Same.
- (reply_get_composer): Don't set_transient_for() here.
- (em_utils_reply_to_message): No longer takes a parent window arg.
- (em_utils_reply_to_message_by_uid): Same.
- (post_reply_to_message): Don't set_transient_for() here.
- (em_utils_post_reply_to_message_by_uid): No longer takes a parent
- window arg.
- (em_utils_compose_new_message_with_mailto): Don't
- set_transient_for() here.
- (em_utils_post_to_url): Same.
- (em_utils_edit_message): No longer takes a parent window arg.
- (em_utils_edit_messages): Same.
-
-2003-10-24 Jeffrey Stedfast <fejj@ximian.com>
-
- * em-account-prefs.[c,h]: Re-Namespaced mail-accounts.c
-
- * em-composer-prefs.[c,h]: Re-Namespaced mail-composer-prefs.c
-
- * em-mailer-prefs.[c,h]: Re-Namespaced mail-preferences.c
-
- * mail-accounts.[c,h]: Removed.
-
- * mail-composer-prefs.[c,h]: Removed.
-
- * mail-preferences.[c,h]: Removed.
-
- * mail-account-editor.c: Updated.
-
- * mail-account-gui.c: Updated.
-
- * mail-config-factory.c: Updated.
-
- * mail-component-factory.c: Updated.
-
-2003-10-22 Ettore Perazzoli <ettore@ximian.com>
-
- * GNOME_Evolution_Mail.server.in.in: Add an
- "evolution:button_icon" attribute.
-
-2003-10-22 Ettore Perazzoli <ettore@ximian.com>
-
- * GNOME_Evolution_Mail.server.in.in: Add an
- "evolution:button_sort_order" attribute.
-
-2003-10-22 Jeffrey Stedfast <fejj@ximian.com>
-
- * mail-component.c (parse_uid_list): Removed, use
- em_utils_selection_get_uidlist() instead.
- (drop_uid_list): Use em_utils_selection_get_uidlist() to parse the
- x-uid-list selection data and use mail_tool_uri_to_folder()
- directly since we have the uri (originally we expected the first
- component of the selection data to be the e-storage-set-view
- folder path rather than the uri).
- (folder_receive_drop_cb): Call gtk_drag_finish() here.
-
- * message-list.c: s/x-evolution-message/x-uid-list/
-
- * em-utils.c: Same.
-
-2003-10-22 Ettore Perazzoli <ettore@ximian.com>
-
- * mail-component.c (impl_createControls): Use
- e_storage_browser_peek_widget_scrolled() to retrieve the scrolled
- window that the EStorageSetView is contained in.
-
-2003-10-22 Ettore Perazzoli <ettore@ximian.com>
-
- * GNOME_Evolution_Mail.server.in.in: Add an
- "evolution:button_label" attribute to the Component for use in the
- shell.
-
-2003-10-22 Not Zed <NotZed@Ximian.com>
-
- * mail-component.c (em_copy_folders): handle destination of ""
- properly.
- (emc_popup_copy_folder_selected): handle url->path properly, strip
- leading /.
- (em_copy_folders): if we just created a new folder on a
- subscribable store, subscribe to it.
- (em_copy_folders): handle nonselectable folders specially.
-
-2003-10-21 Jeffrey Stedfast <fejj@ximian.com>
-
- * mail-component.c (drag_text_uri_list, folder_dragged_cb)
- (drop_uid_list, drop_folder, import_message_rfc822)
- (drop_message_rfc822, drop_text_uri_list, folder_receive_drop_cb):
- New functions to handle drag & drop to/from the folder tree.
- (impl_createControls): Setup drag & drop support.
-
- * em-format.c (emf_multipart_mixed): Put an <hr> between parts of
- a multipart.
-
-2003-10-21 Not Zed <NotZed@Ximian.com>
-
- * mail-component.c (emc_popup_properties): implement.
- (emc_popup_properties_got_folder): builds dynamic
- folder-properties dialogue.
- (emc_popup_properties_response): set the properties on the folder
- on an ok response.
- (emc_popup_properties_free): free the properties working data.
-
- * mail-folder-cache.c (unset_folder_info): unhook from the right
- function for message_changed.
-
-2003-10-20 Not Zed <NotZed@Ximian.com>
-
- * mail-component.c (emc_popup_new_folder): pass the right object
- to set_selected(). Fixes a new real bug. Undid reformatting.
-
-2003-10-17 Jeffrey Stedfast <fejj@ximian.com>
-
- * mail-component.c: General compile fixes.
- (emc_popup_new_folder): Fixed to not shadow a parameter. Fixes a
- real bug.
-
- * mail-component.h: Added some prototypes.
-
-2003-10-13 Not Zed <NotZed@Ximian.com>
-
- * em-popup.c (em_popup_create_menu_once): only hookup target free
- if we have a target set.
-
- * mail-component.c (load_accounts): removed debug i accidentally
- left in.
- (emc_tree_right_click): handle right-click context menu, using an
- EMPopup table.
- (emc_popup_*): setup empty popup handlers.
-
-2003-10-13 Not Zed <NotZed@Ximian.com>
-
- * em-folder-selection.c (em_select_folder): asynchornous folder
- selection call.
- (emfs_folder_selected): callback for folder selected.
-
- * em-folder-view.c (emfv_popup_move): implement.
- (emfv_popup_copy): "
- (emfv_popup_move_cb): async folder select callback to run it.
-
-2003-10-10 Not Zed <NotZed@Ximian.com>
-
- * mail-account-gui.c
- (mail_account_gui_folder_selector_button_new): use
- em_folder_selection_button.
- (mail_account_gui_new): "
- (folder_selected): "
-
- * em-folder-selection-button.c: Make this use camel uri's rather
- than camelfolders.
- (set_selection): removed, redundant.
- (impl_dispose): removed, not needed.
-
- * em-folder-selection-button.h: change the selected signal not to
- actually return the selection, which must get retrieved later.
-
- * mail-component.c (em_uri_from_camel): create an evo mail uri
- from a camel one.
- (em_uri_to_camel): the reverse.
-
- * mail-signature-editor.c (mail_signature_editor): up the version
- of the gtkhtml editor.
-
-2003-10-09 Not Zed <NotZed@Ximian.com>
-
- * em-folder-selection-button.c (set_selection): always set
- selected_folder, otherwise we don't unset it properly.
-
- * em-folder-selection.c (em_folder_selection_run_dialog): fix a
- small memleak.
- (em_folder_selection_run_dialog_uri): do the same as run_dialog
- but take, and return physical uri's.
-
- * mail-component-factory.c (factory): removed some fixme's, and
- re-hookedup the composer.
+ * em-spam-filter.c (em_spam_sa_check_spam): lock spamd test
+ between threads
2003-10-09 Frederic Crozat <fcrozat@mandrakesoft.com>
- * em-icon-stream.c (emis_sync_close): Use
- gnome-thumbnail_scale_down_pixbuf if available, for better
- performance.
+ * em-icon-stream.c: (emis_sync_close):
+ Use gnome-thumbnail_scale_down_pixbuf if available,
+ for better performance.
2003-10-08 Jeffrey Stedfast <fejj@ximian.com>
@@ -368,38 +15,6 @@
create-rule-from-message bars so that we don't segfault when we
right click with a multi-selection.
-2003-10-08 Chris Toshok <toshok@ximian.com>
-
- * em-utils.c (em_utils_camel_address_to_destination): EDestination
- => EABDestination, and e_destination => eab_destination.
- (reply_get_composer): same.
- (post_reply_to_message): same.
-
- * em-composer-utils.c (ask_confirm_for_unwanted_html_mail)
- EDestination => EABDestination, and e_destination =>
- eab_destination.
- (composer_get_message):same.
-
-2003-10-08 Not Zed <NotZed@Ximian.com>
-
- * mail-component.c (mail_component_peek): setup vfolders once we
- hve the component, since its setup will call mail_component_peek,
- fun recursion.
-
-2003-10-08 Not Zed <NotZed@Ximian.com>
-
- * mail-component.c (setup_local_folder): removed.
- (setup_local_store): setup various needed globals properly.
- (setup_account_storages): renamed to load_accounts.
- (go_online): turn on interactivity as well as onlinedness.
-
- * GNOME_Evolution_Mail.server.in.in: point the preferences pages
- to the right factory.
-
-2003-10-07 Not Zed <NotZed@Ximian.com>
-
- * mail-component.[ch]: Fix copyrights.
-
2003-10-06 Jeffrey Stedfast <fejj@ximian.com>
* mail-config-druid.c (identity_prepare): Fixed.
@@ -418,22 +33,6 @@
the first unread message for now. This is actually annoying the
fuck out of me, Radek, and a few other people.
-2003-10-02 Not Zed <NotZed@Ximian.com>
-
- * mail-component.c (add_storage): Add the storage to the hash
- after we've initialised it.
- (mail_component_evomail_uri_from_folder): hardcode "local" account
- pseudo-id for local folders.
- (mail_component_get_folder_from_evomail_uri): handle the "local"
- account case.
-
-2003-10-02 Not Zed <NotZed@Ximian.com>
-
- * mail-component.c (setup_local_store): use mbox:/path rather than
- mbox:///path - the mbox code is 'wrong', but this is easier to
- fix. fixes local unread counts. maybe the provider url-compare
- should address this too.
-
2003-10-02 Suresh Chandrasekharan <suresh.chandrasekharan@sun.com>
* mail-config-druid.c: Fix for 40917 "Backspace shouldn't
@@ -507,27 +106,6 @@
* em-format.c (emf_init): Oops, put the arguments in the right order.
-2003-09-29 Ettore Perazzoli <ettore@ximian.com>
-
- * mail-component.c: New member local_store in
- MailComponentPrivate.
- (impl_dispose): Unref.
- (mail_component_load_storage_by_uri): Return the CamelStore.
- (setup_local_folder): New.
- (setup_local_store): New.
- (mail_component_init): Call it.
- (mail_component_peek_storage_set): New.
- (mail_component_get_folder_from_evomail_uri): New.
- (mail_component_evomail_uri_from_folder): New.
-
- * em-folder-selection-button.c: New.
- * em-folder-selection-button.h: New.
-
- * em-folder-selection.c: New.
- * em-folder-selection.h: New.
-
- * em-marshal.list: Add NONE:POINTER.
-
2003-09-25 Jeffrey Stedfast <fejj@ximian.com>
* mail-account-gui.c (mail_account_gui_save): Allow any file: uri
@@ -547,33 +125,6 @@
charset string is empty, default the charset to the user's locale
charset. Partial fix for bug #47638.
-2003-09-23 Ettore Perazzoli <ettore@ximian.com>
-
- * mail-component.c (add_storage): Remove unused arg "uri".
- (mail_component_add_store): Likewise.
- (add_storage): Don't set the "Connecting..." node.
- (mail_component_init): Set up local store at
- ~/.evolution/mail/local.
-
- * evolution-mbox-upgrade.c (get_local_store): Remove a double
- xmlFree() that was causing it to crash.
-
-
-2003-09-23 Ettore Perazzoli <ettore@ximian.com>
-
- * mail-component.c (add_storage): Note the new store.
-
- * mail-component-factory.c: Don't include "mail-callbacks.h"
- anymore.
-
- * em-format-html.c (em_format_html_get_type): Get the base
- directory with mail_component_peek_base_directory().
- * em-utils.c (filter_editor_response): Likewise.
- (em_utils_edit_filters): Likewise.
-
- * em-folder-browser.c (emfb_init): Get the search context through
- mail_component_peek_search_context().
-
2003-09-23 Jeffrey Stedfast <fejj@ximian.com>
* evolution-mbox-upgrade.c (get_local_store): Don't xmlFree (name)
@@ -727,14 +278,6 @@
* evolution-mbox-upgrade.c: New source file to migrate from the
old mbox structure to the new mbox structure.
-2003-09-08 Ettore Perazzoli <ettore@ximian.com>
-
- * mail-folder-cache.c (mail_note_store): Allow NULL storage in
- precondition.
-
- * mail-component.c (mail_component_init): Remove debugging
- message.
-
2003-08-22 Not Zed <NotZed@Ximian.com>
* mail-format.c (write_date): translate the local time format.
@@ -746,13 +289,14 @@
day names, and the autoconf magic which made Not Zed dislike the
inclusion of the timezone name.
-2003-08-18 Ettore Perazzoli <ettore@ximian.com>
+2003-08-14 Jeffrey Stedfast <fejj@ximian.com>
- * GNOME_Evolution_Mail.server.in.in: Rename
- GNOME_Evolution_Mail_Component2 to
- GNOME_Evolution_Mail_Component_2 and GNOME_Evolution_Mail_Factory2
- to GNOME_Evolution_Mail_Factory_2.
- * mail-component-factory.c: Update accordingly.
+ * mail-ops.c (mail_send_message): Don't abort at the first failure
+ after sending (filtering, appending to Sent, syncing). Instead,
+ keep a running tab of exceptions and then set a culmulative
+ exception at the end to report to our caller. Also, if we fail to
+ append to the account Sent folder, try again with the local Sent
+ folder. Fixes bug #46512.
2003-08-18 Jeffrey Stedfast <fejj@ximian.com>
@@ -797,15 +341,6 @@
* mail-display.c (mail_display_render): Change "%P" to "%p" so
that strftime() can work under solaris.
-2003-08-14 Jeffrey Stedfast <fejj@ximian.com>
-
- * mail-ops.c (mail_send_message): Don't abort at the first failure
- after sending (filtering, appending to Sent, syncing). Instead,
- keep a running tab of exceptions and then set a culmulative
- exception at the end to report to our caller. Also, if we fail to
- append to the account Sent folder, try again with the local Sent
- folder. Fixes bug #46512.
-
2003-08-13 Suresh Chandrasekharan <suresh.chandrasekharan@sun.com>
* e-searching-tokenizer.c (searcher_next_token): Fix for 45818 (
@@ -823,12 +358,6 @@
* mail-session.c (remove_timeout): Removed.
(register_timeout): Removed.
-2003-08-09 Ettore Perazzoli <ettore@ximian.com>
-
- * mail-component.c (storage_go_online): Pass NULL for the
- operation pointer to mail_note_store(), to sync with Michael's
- changes.
-
2003-08-05 Jeffrey Stedfast <fejj@ximian.com>
* mail-format.c (handle_multipart_encrypted): Updated for
@@ -1784,154 +1313,6 @@
* message-browser.c (message_browser_new): Handle our own Delete
key presses. Fixes bug #45597.
-2003-07-25 Ettore Perazzoli <ettore@ximian.com>
-
- * mail-callbacks.c (do_view_message): No need to pass a shell
- argument to message_browser_new() anymore.
-
- * message-browser.c (message_browser_new): Removed arg shell. No
- need to pass it to folder_browser_new() either.
-
- * mail-component.c (create_view_callback): No need to pass a shell
- arg to folder_browser_factory_new_control() anymore.
-
- * folder-browser-factory.c (folder_browser_factory_new_control):
- Removed arg shell; folder_browser_browser_new() doesn't need it
- anymore.
-
- * folder-browser.c (folder_browser_destroy): No need to unref
- ->shell anymore.
- (folder_browser_new): Removed shell arg.
- (folder_browser_gui_init): Removed a const qualifier that was not
- supposed to be there.
-
- * folder-browser.h: Removed member shell from struct
- FolderBrowser.
-
-2003-07-25 Ettore Perazzoli <ettore@ximian.com>
-
- * folder-browser.c (folder_browser_gui_init): Get the search
- context through mail_component_peek_search_context(), since it's
- no longer a global variable.
- (folder_browser_gui_init): Cleaned up an extra unneeded if()
- statement.
-
- * mail-component.c: New member search_context in struct
- MailComponentPrivate.
- (mail_component_peek_search_context): New.
- (setup_search_context): New function to initialize the
- search_context, based on the old code in component-factory.c.
- (mail_component_init): Call it here.
- (impl_dispose): Unref the rule_context.
-
- * mail-component-factory.c: Removed global variable
- search_context.
-
-2003-07-25 Ettore Perazzoli <ettore@ximian.com>
-
- * mail-component.c (browser_page_switched_callback): New callback
- for the "page_switched" signal on EStorageBrowser; deactivate the
- previous page, activate the new one.
- (impl_createControls): Connect.
-
-2003-07-24 Ettore Perazzoli <ettore@ximian.com>
-
- * mail-mt.c (do_op_status): Pass "evolution-mail" as the ID to
- evolution_activity_client_new(). [This is just a temporary thing
- to avoid the fact that we don't have component-factory.h anymore.
- Eventually we'll just get rid of the activity client stuff.]
-
- * mail-component-factory.c: Added to the build. Also, finished
- implementing and moving the factory over from component-factory.c.
-
- * component-factory.c: Removed from the build.
- * component-factory.h: Removed from the build.
-
- * mail-component.c: Removed some debugging messages.
-
-2003-07-23 Ettore Perazzoli <ettore@ximian.com>
-
- * subscribe-dialog.c: Converted to use EStorages instead of
- EvolutionStorages and the new MailComponent object.
-
- * mail.h: Nuked a bunch of stuff. This will go away when I am
- done refactoring.
-
- * mail-offline-handler.c: Use the new MailComponent object.
-
- * mail-folder-cache.c, mail-folder-cache.h: Converted to use
- EStorages instead of EvolutionStorages.
-
- * mail-display.c: Use g_timeout and g_source functions instead of
- gtk_timeout functions.
-
- * mail-send-recv.c: Use g_timeout and g_source functions instead
- of gtk_timeout functions.
- (receive_update_got_store): Updated for the new mail_note_store().
-
- * mail-session.c: Use g_timeout and g_source functions instead of
- gtk_timeout functions.
-
- * mail-config-factory.c (factory): Removed.
-
- * folder-browser.c (folder_browser_destroy): Use GLib
- timeout/source functions instead of the deprecated GTK ones.
- (done_message_selected): Likewise.
- (folder_browser_gui_init): Protect against fb->search being NULL.
-
- * mail-account-gui.c (add_new_store): Use new MailComponent object
- and EStorages instead of EvolutionStorages.
- (mail_account_gui_save): Likewise.
-
- * mail-accounts.c (account_delete_clicked): Use new MailComponent
- object and EStorages instead of EvolutionStorages.
- (account_able_clicked): Likewise.
- (account_able_toggled): Likewise.
-
- * mail-autofilter.c: Use mail_component_peek_base_directory()
- instead of the evolution_dir global.
- * mail-callbacks.c: Likewise.
- * mail-config.c (uri_to_evname): Likewise.
- (mail_config_get_signature_list): Likewise.
- (delete_unused_signature_file): Likewise.
- * mail-display.c (mail_display_class_init): Likewise.
- * mail-importer.c (mail_importer_make_local_folder): Likewise.
- * mail-local.c (mlf_getv): Likewise.
- * mail-ops.c (uid_cachename_hack): Likewise.
- * mail-summary.c (generate_folder_summaries): Likewise.
- * mail-tools.c (mail_tool_get_local_inbox): Likewise.
- (mail_tools_folder_to_url): Likewise.
- * mail-vfolder.c (mail_vfolder_delete_uri): Likewise.
- (mail_vfolder_rename_uri): Likewise.
- (context_rule_removed): Likewise.
- (store_folder_deleted): Likewise.
- (store_folder_renamed): Likewise.
- (vfolder_load_storage): Likewise.
- (vfolder_editor_response): Likewise.
- (edit_rule_response): Likewise.
- (new_rule_clicked): Likewise.
- (vfolder_gui_add_rule): Likewise.
- * mail-session.c (main_get_filter_driver): Likewise.
- (mail_session_forget_password): Likewise.
- (mail_session_init): Get a base_directory arg.
-
- * component-factory.c, component-factory.h: Disabled a bunch of
- stuff to get it to compile in the new configuration. These files
- will eventually go away when I am done refactoring this.
-
- * Makefile.am: Do not build importers, compile generate
- skels/stubs for Evolution.
-
- * GNOME_Evolution_Mail.server.in.in: Rename control factory to
- OAFIID:GNOME_Evolution_Mail_Factory2. Add new component
- GNOME_Evolution_Mail_Component2.
-
- * mail-component-factory.c: New file implementing the Bonobo
- factory.
-
- * mail-component.c, mail-component.h: New files implementing the
- new mail component, using the new Evolution::Component IDL.
-
2003-07-23 Jeffrey Stedfast <fejj@ximian.com>
* mail-format.c (mail_format_data_wrapper_write_to_stream): Revert
diff --git a/mail/Makefile.am b/mail/Makefile.am
index 41757c704f..ed63d84526 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = # importers FIXME
+SUBDIRS = importers
libexec_PROGRAMS = \
evolution-mbox-upgrade
@@ -17,6 +17,8 @@ INCLUDES = \
-I$(top_srcdir)/shell \
-I$(top_srcdir)/shell/importer \
-I$(top_builddir)/shell/importer \
+ -I$(top_srcdir)/addressbook/backend \
+ -I$(top_builddir)/addressbook/backend \
$(EVOLUTION_MAIL_CFLAGS) \
-DEVOLUTION_DATADIR=\""$(datadir)"\" \
-DEVOLUTION_PRIVDATADIR=\""$(privdatadir)"\" \
@@ -37,133 +39,132 @@ INCLUDES = \
component_LTLIBRARIES = libevolution-mail.la
-# Code generation for Spell.idl
+EVOLUTION_MAIL_CORBA_GENERATED_H = \
+ Mailer.h
+EVOLUTION_MAIL_CORBA_GENERATED_C = \
+ Mailer-common.c \
+ Mailer-skels.c \
+ Mailer-stubs.c
+EVOLUTION_MAIL_CORBA_GENERATED = $(EVOLUTION_MAIL_CORBA_GENERATED_C) $(EVOLUTION_MAIL_CORBA_GENERATED_H)
SPELL_IDL = Spell.idl
-SPELL_IDL_GENERATED_H = \
+IDL_GENERATED_H = \
Spell.h
-SPELL_IDL_GENERATED_C = \
+IDL_GENERATED_C = \
Spell-common.c \
Spell-skels.c \
Spell-stubs.c
-SPELL_IDL_GENERATED = $(SPELL_IDL_GENERATED_C) $(SPELL_IDL_GENERATED_H)
+IDL_GENERATED = $(IDL_GENERATED_C) $(IDL_GENERATED_H)
-$(SPELL_IDL_GENERATED_H): $(SPELL_IDL)
+$(IDL_GENERATED_H): $(SPELL_IDL)
$(ORBIT_IDL) -I $(srcdir) -I $(datadir)/idl $(IDL_INCLUDES) $(srcdir)/Spell.idl
-$(SPELL_IDL_GENERATED_C): $(SPELL_IDL_GENERATED_H)
+$(IDL_GENERATED_C): $(IDL_GENERATED_H)
Spell-impl.o: Spell.h
-
-# libevolution-mail
-
-libevolution_mail_la_SOURCES = \
- $(SPELL_IDL_GENERATED) \
- $(MARSHAL_GENERATED) \
- e-searching-tokenizer.c \
- e-searching-tokenizer.h \
- em-account-prefs.c \
- em-account-prefs.h \
- em-composer-prefs.c \
- em-composer-prefs.h \
- em-mailer-prefs.c \
- em-mailer-prefs.h \
- em-inline-filter.c \
- em-inline-filter.h \
- em-folder-selection.c \
- em-folder-selection.h \
- em-folder-selection-button.c \
- em-folder-selection-button.h \
- em-folder-selector.c \
- em-folder-selector.h \
- em-folder-view.c \
- em-folder-view.h \
- em-folder-browser.c \
- em-folder-browser.h \
- em-format.c \
- em-format.h \
- em-format-html.c \
- em-format-html.h \
- em-format-html-display.c \
- em-format-html-display.h \
- em-format-html-print.c \
- em-format-html-print.h \
- em-format-html-quote.c \
- em-format-html-quote.h \
- em-format-quote.c \
- em-format-quote.h \
- em-message-browser.c \
- em-message-browser.h \
- em-migrate.c \
- em-migrate.h \
- em-composer-utils.c \
- em-composer-utils.h \
- em-popup.c \
- em-popup.h \
- em-utils.c \
- em-utils.h \
- em-subscribe-editor.c \
- em-subscribe-editor.h \
- em-sync-stream.c \
- em-sync-stream.h \
- em-icon-stream.c \
- em-icon-stream.h \
- em-html-stream.c \
- em-html-stream.h \
- folder-browser-factory.c \
- folder-browser-factory.h \
- mail-account-editor.c \
- mail-account-editor.h \
- mail-account-gui.c \
- mail-account-gui.h \
- mail-autofilter.c \
- mail-autofilter.h \
- mail-component-factory.c \
- mail-component.c \
- mail-component.h \
- mail-config.c \
- mail-config.h \
- mail-config-druid.c \
- mail-config-druid.h \
- mail-crypto.c \
- mail-crypto.h \
- mail-config-factory.c \
- mail-config-factory.h \
- mail-folder-cache.c \
- mail-folder-cache.h \
- mail-importer.c \
- mail-importer.h \
- mail-mt.c \
- mail-mt.h \
- mail-offline-handler.c \
- mail-offline-handler.h \
- mail-ops.c \
- mail-ops.h \
- mail-send-recv.c \
- mail-send-recv.h \
- mail-session.c \
- mail-session.h \
- mail-signature-editor.c \
- mail-signature-editor.h \
- mail-tools.c \
- mail-tools.h \
- mail-types.h \
- mail-vfolder.c \
- mail-vfolder.h \
- message-list.c \
- message-list.h \
- message-tag-editor.c \
- message-tag-editor.h \
- message-tag-followup.c \
- message-tag-followup.h \
+libevolution_mail_la_SOURCES = \
+ $(EVOLUTION_MAIL_CORBA_GENERATED) \
+ $(IDL_GENERATED) \
+ component-factory.c \
+ component-factory.h \
+ e-searching-tokenizer.c \
+ e-searching-tokenizer.h \
+ em-inline-filter.c \
+ em-inline-filter.h \
+ em-folder-view.c \
+ em-folder-view.h \
+ em-folder-browser.c \
+ em-folder-browser.h \
+ em-format.c \
+ em-format.h \
+ em-format-html.c \
+ em-format-html.h \
+ em-format-html-display.c \
+ em-format-html-display.h \
+ em-format-html-print.c \
+ em-format-html-print.h \
+ em-format-html-quote.c \
+ em-format-html-quote.h \
+ em-format-quote.c \
+ em-format-quote.h \
+ em-marshal.c \
+ em-marshal.h \
+ em-message-browser.c \
+ em-message-browser.h \
+ em-composer-utils.c \
+ em-composer-utils.h \
+ em-popup.c \
+ em-popup.h \
+ em-utils.c \
+ em-utils.h \
+ em-subscribe-editor.c \
+ em-subscribe-editor.h \
+ em-sync-stream.c \
+ em-sync-stream.h \
+ em-icon-stream.c \
+ em-icon-stream.h \
+ em-html-stream.c \
+ em-html-stream.h \
+ em-junk-filter.c \
+ em-junk-filter.h \
+ em-junk-plugin.c \
+ em-junk-plugin.h \
+ folder-browser-factory.c \
+ folder-browser-factory.h \
+ folder-info.c \
+ folder-info.h \
+ mail-account-editor.c \
+ mail-account-editor.h \
+ mail-account-gui.c \
+ mail-account-gui.h \
+ mail-accounts.c \
+ mail-accounts.h \
+ mail-autofilter.c \
+ mail-autofilter.h \
+ mail-composer-prefs.c \
+ mail-composer-prefs.h \
+ mail-config.c \
+ mail-config.h \
+ mail-config-druid.c \
+ mail-config-druid.h \
+ mail-crypto.c \
+ mail-crypto.h \
+ mail-config-factory.c \
+ mail-config-factory.h \
+ mail-preferences.c \
+ mail-preferences.h \
+ mail-folder-cache.c \
+ mail-folder-cache.h \
+ mail-importer.c \
+ mail-importer.h \
+ mail-local.c \
+ mail-local.h \
+ mail-mt.c \
+ mail-mt.h \
+ mail-offline-handler.c \
+ mail-offline-handler.h \
+ mail-ops.c \
+ mail-ops.h \
+ mail-send-recv.c \
+ mail-send-recv.h \
+ mail-session.c \
+ mail-session.h \
+ mail-signature-editor.c \
+ mail-signature-editor.h \
+ mail-tools.c \
+ mail-tools.h \
+ mail-types.h \
+ mail-vfolder.c \
+ mail-vfolder.h \
+ message-list.c \
+ message-list.h \
+ message-tag-editor.c \
+ message-tag-editor.h \
+ message-tag-followup.c \
+ message-tag-followup.h \
mail.h
-# EPFIXME: Functionality to be brought back to life.
-#
-# mail-local.c
-# mail-local.h
-
libevolution_mail_la_LIBADD = \
$(top_builddir)/shell/importer/libevolution-importer.la \
$(top_builddir)/camel/libcamel.la \
@@ -172,6 +173,7 @@ libevolution_mail_la_LIBADD = \
$(top_builddir)/composer/libcomposer.la \
$(top_builddir)/widgets/misc/libemiscwidgets.la \
$(top_builddir)/widgets/misc/libefilterbar.la \
+ $(top_builddir)/addressbook/backend/ebook/libebook.la \
$(top_builddir)/filter/libfilter.la \
$(top_builddir)/widgets/menus/libmenus.la \
$(EVOLUTION_MAIL_LIBS)
@@ -179,9 +181,6 @@ libevolution_mail_la_LIBADD = \
libevolution_mail_la_LDFLAGS = \
-avoid-version -module
-
-# .server files
-
evolution_mbox_upgrade_SOURCES = evolution-mbox-upgrade.c
evolution_mbox_upgrade_LDADD = \
$(top_builddir)/camel/libcamel.la \
@@ -189,31 +188,39 @@ evolution_mbox_upgrade_LDADD = \
$(EVOLUTION_MAIL_LIBS)
server_in_files = GNOME_Evolution_Mail.server.in.in
-server_DATA = $(server_in_files:.server.in.in=_$(BASE_VERSION).server)
-@EVO_SUBST_SERVER_RULE@
-@EVO_NAME_SERVER_RULE@
-@INTLTOOL_SERVER_RULE@
-# Misc data to install
+server_DATA = $(server_in_files:.server.in.in=.server)
+%.server.in: %.server.in.in
+ sed -e "s|\@COMPONENTDIR\@|$(componentdir)|" $< > $@
+@INTLTOOL_SERVER_RULE@
-glade_DATA = mail-config.glade local-config.glade subscribe-dialog.glade message-tags.glade mail-search.glade
MARSHAL_GENERATED = em-marshal.c em-marshal.h
@EVO_MARSHAL_RULE@
+glade_DATA = mail-config.glade local-config.glade subscribe-dialog.glade message-tags.glade mail-search.glade
+
etspec_DATA = message-list.etspec
+schemadir = $(GCONF_SCHEMA_FILE_DIR)
+schema_DATA = evolution-mail.schemas
+
+idl_DATA = Mailer.idl
+
+$(EVOLUTION_MAIL_CORBA_GENERATED_H): Mailer.idl
+ $(ORBIT_IDL) -I $(srcdir) -I $(datadir)/idl $(IDL_INCLUDES) $(srcdir)/Mailer.idl
+$(EVOLUTION_MAIL_CORBA_GENERATED_C): $(EVOLUTION_MAIL_CORBA_GENERATED_H)
+
EXTRA_DIST = \
ChangeLog.pre-1-4 \
em-marshal.list \
+ Mailer.idl \
$(SPELL_IDL) \
$(glade_DATA) \
$(schema_DATA) \
$(server_in_files) \
+ $(server_DATA) \
$(etspec_DATA)
-
-# Purify support
-
if ENABLE_PURIFY
PLINK = $(LIBTOOL) --mode=link $(PURIFY) $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
@@ -225,12 +232,6 @@ evolution-mail.pure: evolution-mail
endif
-
-# GConf
-
-schemadir = $(GCONF_SCHEMA_FILE_DIR)
-schema_DATA = evolution-mail.schemas
-
install-data-local:
if test -z "$(DESTDIR)" ; then \
for p in $(schema_DATA) ; do \
@@ -238,11 +239,8 @@ install-data-local:
done \
fi
-
-# Prologue
-
dist-hook:
cd $(distdir); rm -f $(BUILT_SOURCES)
-BUILT_SOURCES = $(SPELL_IDL_GENERATED) $(MARSHAL_GENERATED) $(server_DATA)
+BUILT_SOURCES = $(EVOLUTION_MAIL_CORBA_GENERATED) $(IDL_GENERATED) $(MARSHAL_GENERATED) $(server_DATA)
CLEANFILES = $(BUILT_SOURCES)
diff --git a/mail/component-factory.c b/mail/component-factory.c
new file mode 100644
index 0000000000..f578cd13d5
--- /dev/null
+++ b/mail/component-factory.c
@@ -0,0 +1,1668 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* component-factory.c
+ *
+ * Authors: Ettore Perazzoli <ettore@ximian.com>
+ *
+ * Copyright (C) 2000 Ximian, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <signal.h>
+
+#include <gconf/gconf.h>
+#include <gconf/gconf-client.h>
+
+#include <camel/camel.h>
+#include <camel/camel-vee-store.h>
+
+#include <bonobo/bonobo-generic-factory.h>
+#include <bonobo/bonobo-shlib-factory.h>
+
+#include <gal/widgets/e-gui-utils.h>
+
+#include "e-util/e-dialog-utils.h"
+
+#include "Evolution.h"
+#include "evolution-storage.h"
+#include "evolution-wizard.h"
+#include "evolution-composer.h"
+
+#include "folder-browser-factory.h"
+#include "evolution-shell-component.h"
+#include "evolution-shell-component-dnd.h"
+#include "folder-info.h"
+#include "mail.h"
+#include "mail-config.h"
+#include "mail-config-factory.h"
+#include "mail-preferences.h"
+#include "mail-composer-prefs.h"
+#include "mail-tools.h"
+#include "mail-ops.h"
+#include "mail-offline-handler.h"
+#include "mail-local.h"
+#include "mail-session.h"
+#include "mail-mt.h"
+#include "mail-importer.h"
+#include "mail-folder-cache.h"
+#include "em-utils.h"
+#include "component-factory.h"
+
+#include "mail-send-recv.h"
+
+#include "mail-vfolder.h"
+#include "mail-autofilter.h"
+
+#define d(x)
+
+char *default_drafts_folder_uri;
+CamelFolder *drafts_folder = NULL;
+char *default_sent_folder_uri;
+CamelFolder *sent_folder = NULL;
+char *default_outbox_folder_uri;
+CamelFolder *outbox_folder = NULL;
+char *evolution_dir;
+
+EvolutionShellClient *global_shell_client = NULL;
+
+RuleContext *search_context = NULL;
+
+static MailAsyncEvent *async_event = NULL;
+
+static GHashTable *storages_hash;
+static EvolutionShellComponent *shell_component;
+
+enum {
+ ACCEPTED_DND_TYPE_MESSAGE_RFC822,
+ ACCEPTED_DND_TYPE_X_EVOLUTION_MESSAGE,
+ ACCEPTED_DND_TYPE_TEXT_URI_LIST,
+};
+
+static char *accepted_dnd_types[] = {
+ "message/rfc822",
+ "x-evolution-message", /* ...from an evolution message list... */
+ "text/uri-list", /* ...from nautilus... */
+ NULL
+};
+
+enum {
+ EXPORTED_DND_TYPE_TEXT_URI_LIST,
+};
+
+static char *exported_dnd_types[] = {
+ "text/uri-list", /* we have to export to nautilus as text/uri-list */
+ NULL
+};
+
+static const EvolutionShellComponentFolderType folder_types[] = {
+ { "mail", "evolution-inbox.png", N_("Mail"), N_("Folder containing mail"), TRUE, accepted_dnd_types, exported_dnd_types },
+ { "mail/public", "evolution-inbox.png", N_("Public Mail"), N_("Public folder containing mail"), FALSE, accepted_dnd_types, exported_dnd_types },
+ { "vtrash", "evolution-trash.png", N_("Virtual Trash"), N_("Virtual Trash folder"), FALSE, accepted_dnd_types, exported_dnd_types },
+ { "vjunk", "evolution-junk.png", N_("Virtual Junk"), N_("Virtual Junk folder"), FALSE, accepted_dnd_types, exported_dnd_types },
+ { NULL, NULL, NULL, NULL, FALSE, NULL, NULL }
+};
+
+static const char *schema_types[] = {
+ "mailto",
+ NULL
+};
+
+static inline gboolean
+type_is_mail (const char *type)
+{
+ return !strcmp (type, "mail") || !strcmp (type, "mail/public");
+}
+
+static inline gboolean
+type_is_vtrash (const char *type)
+{
+ return !strcmp (type, "vtrash");
+}
+
+static inline gboolean
+type_is_vjunk (const char *type)
+{
+ return !strcmp (type, "vjunk");
+}
+
+/* EvolutionShellComponent methods and signals. */
+
+static BonoboControl *
+create_noselect_control (void)
+{
+ GtkWidget *label;
+
+ label = gtk_label_new (_("This folder cannot contain messages."));
+ gtk_widget_show (label);
+ return bonobo_control_new (label);
+}
+
+static EvolutionShellComponentResult
+create_view (EvolutionShellComponent *shell_component,
+ const char *physical_uri,
+ const char *folder_type,
+ const char *view_info,
+ BonoboControl **control_return,
+ void *closure)
+{
+ EvolutionShellClient *shell_client;
+ GNOME_Evolution_Shell corba_shell;
+ BonoboControl *control;
+
+ shell_client = evolution_shell_component_get_owner (shell_component);
+ corba_shell = evolution_shell_client_corba_objref(shell_client);
+
+ if (type_is_mail (folder_type)) {
+ const char *noselect;
+ CamelURL *url;
+
+ url = camel_url_new (physical_uri, NULL);
+ noselect = url ? camel_url_get_param (url, "noselect") : NULL;
+ if (noselect && !strcasecmp (noselect, "yes"))
+ control = create_noselect_control ();
+ else
+ control = folder_browser_factory_new_control (physical_uri,
+ corba_shell);
+ camel_url_free (url);
+ } else if (type_is_vtrash (folder_type)) {
+ if (!strncasecmp (physical_uri, "file:", 5))
+ control = folder_browser_factory_new_control ("vtrash:file:/", corba_shell);
+ else
+ control = folder_browser_factory_new_control (physical_uri, corba_shell);
+ } else if (type_is_vjunk (folder_type))
+ if (!strncasecmp (physical_uri, "file:", 5))
+ control = folder_browser_factory_new_control ("vjunk:file:/", corba_shell);
+ else
+ control = folder_browser_factory_new_control (physical_uri, corba_shell);
+ else
+ return EVOLUTION_SHELL_COMPONENT_UNSUPPORTEDTYPE;
+
+ if (!control)
+ return EVOLUTION_SHELL_COMPONENT_NOTFOUND;
+
+ *control_return = control;
+ return EVOLUTION_SHELL_COMPONENT_OK;
+}
+
+static void
+create_folder_done (char *uri, CamelFolder *folder, void *data)
+{
+ GNOME_Evolution_ShellComponentListener listener = data;
+ GNOME_Evolution_ShellComponentListener_Result result;
+ CORBA_Environment ev;
+
+ if (folder) {
+ result = GNOME_Evolution_ShellComponentListener_OK;
+ } else {
+ result = GNOME_Evolution_ShellComponentListener_INVALID_URI;
+ }
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_ShellComponentListener_notifyResult (listener, result, &ev);
+ CORBA_Object_release (listener, &ev);
+ CORBA_exception_free (&ev);
+}
+
+static void
+create_folder (EvolutionShellComponent *shell_component,
+ const char *physical_uri,
+ const char *type,
+ const GNOME_Evolution_ShellComponentListener listener,
+ void *closure)
+{
+ CORBA_Environment ev;
+
+ CORBA_exception_init (&ev);
+
+ if (type_is_mail (type)) {
+ mail_get_folder (physical_uri, CAMEL_STORE_FOLDER_CREATE, create_folder_done,
+ CORBA_Object_duplicate (listener, &ev), mail_thread_new);
+ } else {
+ GNOME_Evolution_ShellComponentListener_notifyResult (
+ listener, GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, &ev);
+ }
+
+ CORBA_exception_free (&ev);
+}
+
+static void
+remove_folder_done (char *uri, gboolean removed, void *data)
+{
+ GNOME_Evolution_ShellComponentListener listener = data;
+ GNOME_Evolution_ShellComponentListener_Result result;
+ CORBA_Environment ev;
+
+ if (removed)
+ result = GNOME_Evolution_ShellComponentListener_OK;
+ else
+ result = GNOME_Evolution_ShellComponentListener_INVALID_URI;
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_ShellComponentListener_notifyResult (listener, result, &ev);
+ CORBA_Object_release (listener, &ev);
+ CORBA_exception_free (&ev);
+}
+
+static void
+remove_folder (EvolutionShellComponent *shell_component,
+ const char *physical_uri,
+ const char *type,
+ const GNOME_Evolution_ShellComponentListener listener,
+ void *closure)
+{
+ CORBA_Environment ev;
+
+ CORBA_exception_init (&ev);
+
+ if (!type_is_mail (type)) {
+ GNOME_Evolution_ShellComponentListener_notifyResult (listener,
+ GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, &ev);
+ CORBA_exception_free (&ev);
+ return;
+ }
+
+ mail_remove_folder (physical_uri, remove_folder_done, CORBA_Object_duplicate (listener, &ev));
+ CORBA_exception_free (&ev);
+}
+
+typedef struct _xfer_folder_data {
+ GNOME_Evolution_ShellComponentListener listener;
+ gboolean remove_source;
+ char *source_uri;
+} xfer_folder_data;
+
+static void
+xfer_folder_done (gboolean ok, void *data)
+{
+ xfer_folder_data *xfd = (xfer_folder_data *)data;
+ GNOME_Evolution_ShellComponentListener listener = xfd->listener;
+ GNOME_Evolution_ShellComponentListener_Result result;
+ CORBA_Environment ev;
+
+ if (xfd->remove_source && ok) {
+ mail_remove_folder (xfd->source_uri, remove_folder_done, xfd->listener);
+ } else {
+ if (ok)
+ result = GNOME_Evolution_ShellComponentListener_OK;
+ else
+ result = GNOME_Evolution_ShellComponentListener_INVALID_URI;
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_ShellComponentListener_notifyResult (listener, result, &ev);
+ CORBA_Object_release (listener, &ev);
+ CORBA_exception_free (&ev);
+ }
+
+ g_free (xfd->source_uri);
+ g_free (xfd);
+}
+
+static void
+xfer_folder (EvolutionShellComponent *shell_component,
+ const char *source_physical_uri,
+ const char *destination_physical_uri,
+ const char *type,
+ gboolean remove_source,
+ const GNOME_Evolution_ShellComponentListener listener,
+ void *closure)
+{
+ CORBA_Environment ev;
+ CamelFolder *source;
+ CamelException ex;
+ GPtrArray *uids;
+ CamelURL *src, *dst;
+
+ d(printf("Renaming folder '%s' to dest '%s' type '%s'\n", source_physical_uri, destination_physical_uri, type));
+
+ CORBA_exception_init (&ev);
+
+ if (!type_is_mail (type)) {
+ GNOME_Evolution_ShellComponentListener_notifyResult (listener,
+ GNOME_Evolution_ShellComponentListener_UNSUPPORTED_TYPE, &ev);
+ return;
+ }
+
+ src = camel_url_new(source_physical_uri, NULL);
+ if (src == NULL) {
+ GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev);
+ return;
+ }
+
+ dst = camel_url_new(destination_physical_uri, NULL);
+ if (dst == NULL) {
+ camel_url_free(src);
+ GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev);
+ return;
+ }
+
+ if (camel_url_get_param(dst, "noselect") != NULL) {
+ camel_url_free(src);
+ camel_url_free(dst);
+ GNOME_Evolution_ShellComponentListener_notifyResult (listener,
+ GNOME_Evolution_ShellComponentListener_UNSUPPORTED_OPERATION, &ev);
+ return;
+ }
+
+ camel_exception_init (&ex);
+
+ /* If we are really doing a rename, implement it as a rename */
+ if (remove && strcmp(src->protocol, dst->protocol) == 0) {
+ char *sname, *dname;
+ CamelStore *store;
+
+ if (src->fragment)
+ sname = src->fragment;
+ else {
+ if (src->path && *src->path)
+ sname = src->path+1;
+ else
+ sname = "";
+ }
+
+ if (dst->fragment)
+ dname = dst->fragment;
+ else {
+ if (dst->path && *dst->path)
+ dname = dst->path+1;
+ else
+ dname = "";
+ }
+
+ store = camel_session_get_store(session, source_physical_uri, &ex);
+ if (store != NULL)
+ camel_store_rename_folder(store, sname, dname, &ex);
+
+ if (camel_exception_is_set(&ex))
+ GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev);
+ else {
+ /* Since the shell doesn't play nice with local folders, we have to do this manually */
+ mail_vfolder_rename_uri(store, source_physical_uri, destination_physical_uri);
+ mail_filter_rename_uri(store, source_physical_uri, destination_physical_uri);
+ GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_OK, &ev);
+ }
+ camel_object_unref((CamelObject *)store);
+ } else {
+ source = mail_tool_uri_to_folder (source_physical_uri, 0, &ex);
+
+ if (source) {
+ xfer_folder_data *xfd;
+
+ xfd = g_new0 (xfer_folder_data, 1);
+ xfd->remove_source = remove_source;
+ xfd->source_uri = g_strdup (source_physical_uri);
+ xfd->listener = CORBA_Object_duplicate (listener, &ev);
+
+ uids = camel_folder_get_uids (source);
+ mail_transfer_messages (source, uids, remove_source, destination_physical_uri, CAMEL_STORE_FOLDER_CREATE, xfer_folder_done, xfd);
+ camel_object_unref (CAMEL_OBJECT (source));
+ } else
+ GNOME_Evolution_ShellComponentListener_notifyResult (listener, GNOME_Evolution_ShellComponentListener_INVALID_URI, &ev);
+ }
+
+ CORBA_exception_free (&ev);
+ camel_exception_clear (&ex);
+
+ camel_url_free(src);
+ camel_url_free(dst);
+}
+
+static void
+configure_folder_popup(BonoboUIComponent *component, void *user_data, const char *cname)
+{
+ char *uri = user_data;
+
+ /* FIXME: re-implement */
+
+ if (strncmp(uri, "vfolder:", 8) == 0)
+ vfolder_edit_rule(uri);
+#if 0
+ else {
+ struct _EMFolderBrowser *fb = folder_browser_factory_get_browser(uri);
+
+ if (fb)
+ configure_folder(component, fb, cname);
+ else
+ mail_local_reconfigure_folder(uri, NULL, NULL);
+ }
+#endif
+}
+
+static void
+populate_folder_context_menu (EvolutionShellComponent *shell_component,
+ BonoboUIComponent *uic,
+ const char *physical_uri,
+ const char *type,
+ void *closure)
+{
+#ifdef TRANSLATORS_ONLY
+ static char popup_xml_i18n[] = {N_("Properties..."), N_("Change this folder's properties")};
+#endif
+ static char popup_xml[] =
+ "<menuitem name=\"ChangeFolderPropertiesPopUp\" verb=\"ChangeFolderPropertiesPopUp\""
+ " _label=\"Properties...\" _tip=\"Change this folder's properties\"/>";
+
+ if (!type_is_mail (type))
+ return;
+
+ /* FIXME: handle other types */
+
+ /* the unmatched test is a bit of a hack but it works */
+ if ((strncmp(physical_uri, "vfolder:", 8) == 0
+ && strstr(physical_uri, "#" CAMEL_UNMATCHED_NAME) == NULL)
+ || strncmp(physical_uri, "file:", 5) == 0) {
+ bonobo_ui_component_add_verb_full(uic, "ChangeFolderPropertiesPopUp",
+ g_cclosure_new(G_CALLBACK(configure_folder_popup),
+ g_strdup(physical_uri), (GClosureNotify)g_free));
+ bonobo_ui_component_set_translate (uic, EVOLUTION_SHELL_COMPONENT_POPUP_PLACEHOLDER, popup_xml, NULL);
+ }
+}
+
+static void
+unpopulate_folder_context_menu (EvolutionShellComponent *shell_component,
+ BonoboUIComponent *uic,
+ const char *physical_uri,
+ const char *type,
+ void *closure)
+{
+ if (!type_is_mail (type))
+ return;
+
+ /* FIXME: handle other types */
+
+ /* the unmatched test is a bit of a hack but it works */
+ if ((strncmp(physical_uri, "vfolder:", 8) == 0
+ && strstr(physical_uri, "#" CAMEL_UNMATCHED_NAME) == NULL)
+ || strncmp(physical_uri, "file:", 5) == 0) {
+ bonobo_ui_component_rm (uic, EVOLUTION_SHELL_COMPONENT_POPUP_PLACEHOLDER "/ChangeFolderPropertiesPopUp", NULL);
+ }
+}
+
+static char *
+get_dnd_selection (EvolutionShellComponent *shell_component,
+ const char *physical_uri,
+ int type,
+ int *format_return,
+ const char **selection_return,
+ int *selection_length_return,
+ void *closure)
+{
+ d(printf ("should get dnd selection for %s\n", physical_uri));
+
+ return NULL;
+}
+
+/* Destination side DnD */
+static CORBA_boolean
+destination_folder_handle_motion (EvolutionShellComponentDndDestinationFolder *folder,
+ const char *physical_uri,
+ const char *folder_type,
+ const GNOME_Evolution_ShellComponentDnd_DestinationFolder_Context *destination_context,
+ GNOME_Evolution_ShellComponentDnd_Action *suggested_action_return,
+ gpointer user_data)
+{
+ const char *noselect;
+ CamelURL *url;
+
+ url = camel_url_new (physical_uri, NULL);
+ noselect = url ? camel_url_get_param (url, "noselect") : NULL;
+
+ if (noselect && !strcasecmp (noselect, "yes"))
+ /* uh, no way to say "illegal" */
+ *suggested_action_return = GNOME_Evolution_ShellComponentDnd_ACTION_DEFAULT;
+ else
+ *suggested_action_return = GNOME_Evolution_ShellComponentDnd_ACTION_MOVE;
+
+ if (url)
+ camel_url_free (url);
+
+ return TRUE;
+}
+
+static gboolean
+message_rfc822_dnd (CamelFolder *dest, CamelStream *stream, CamelException *ex)
+{
+ CamelMimeParser *mp;
+ gboolean handled = FALSE;
+
+ mp = camel_mime_parser_new ();
+ camel_mime_parser_scan_from (mp, TRUE);
+ camel_mime_parser_init_with_stream (mp, stream);
+
+ while (camel_mime_parser_step (mp, 0, 0) == CAMEL_MIME_PARSER_STATE_FROM) {
+ CamelMessageInfo *info;
+ CamelMimeMessage *msg;
+
+ handled = TRUE;
+
+ msg = camel_mime_message_new ();
+ if (camel_mime_part_construct_from_parser (CAMEL_MIME_PART (msg), mp) == -1) {
+ camel_object_unref (msg);
+ handled = FALSE;
+ break;
+ }
+
+ /* append the message to the folder... */
+ info = g_new0 (CamelMessageInfo, 1);
+ camel_folder_append_message (dest, msg, info, NULL, ex);
+ camel_object_unref (msg);
+
+ if (camel_exception_is_set (ex)) {
+ handled = FALSE;
+ break;
+ }
+
+ /* skip over the FROM_END state */
+ camel_mime_parser_step (mp, 0, 0);
+ }
+
+ camel_object_unref (mp);
+
+ return handled;
+}
+
+static CORBA_boolean
+destination_folder_handle_drop (EvolutionShellComponentDndDestinationFolder *dest_folder,
+ const char *physical_uri,
+ const char *folder_type,
+ const GNOME_Evolution_ShellComponentDnd_DestinationFolder_Context *destination_context,
+ const GNOME_Evolution_ShellComponentDnd_Action action,
+ const GNOME_Evolution_ShellComponentDnd_Data *data,
+ gpointer user_data)
+{
+ char *tmp, *url, **urls;
+ gboolean retval = FALSE;
+ const char *noselect;
+ CamelFolder *folder;
+ CamelStream *stream;
+ CamelException ex;
+ GPtrArray *uids;
+ CamelURL *uri;
+ int i, type, fd;
+
+ if (action == GNOME_Evolution_ShellComponentDnd_ACTION_LINK)
+ return FALSE; /* we can't create links */
+
+ /* this means the drag was cancelled */
+ if (!data->bytes._buffer || data->bytes._length == -1)
+ return FALSE;
+
+ uri = camel_url_new (physical_uri, NULL);
+ noselect = uri ? camel_url_get_param (uri, "noselect") : NULL;
+ if (noselect && !strcasecmp (noselect, "yes")) {
+ camel_url_free (uri);
+ return FALSE;
+ }
+
+ if (uri)
+ camel_url_free (uri);
+
+ d(printf ("in destination_folder_handle_drop (%s)\n", physical_uri));
+
+ for (type = 0; accepted_dnd_types[type]; type++)
+ if (!strcmp (destination_context->dndType, accepted_dnd_types[type]))
+ break;
+
+ camel_exception_init (&ex);
+
+ /* if this is a local vtrash folder, then it's uri is vtrash:file:/ */
+ if (type_is_vtrash (folder_type) && !strncmp (physical_uri, "file:", 5))
+ physical_uri = "vtrash:file:/";
+
+ /* if this is a local vjunk folder, then it's uri is vjunk:file:/ */
+ if (type_is_vjunk (folder_type) && !strncmp (physical_uri, "file:", 5))
+ physical_uri = "vjunk:file:/";
+
+ switch (type) {
+ case ACCEPTED_DND_TYPE_TEXT_URI_LIST:
+ folder = mail_tool_uri_to_folder (physical_uri, 0, &ex);
+ if (!folder) {
+ camel_exception_clear (&ex);
+ return FALSE;
+ }
+
+ tmp = g_strndup (data->bytes._buffer, data->bytes._length);
+ urls = g_strsplit (tmp, "\n", 0);
+ g_free (tmp);
+
+ retval = TRUE;
+ for (i = 0; urls[i] != NULL && retval; i++) {
+ /* get the path component */
+ url = g_strstrip (urls[i]);
+
+ uri = camel_url_new (url, NULL);
+ g_free (url);
+
+ if (!uri)
+ continue;
+
+ url = uri->path;
+ uri->path = NULL;
+ camel_url_free (uri);
+
+ fd = open (url, O_RDONLY);
+ if (fd == -1) {
+ g_free (url);
+ /* FIXME: okay, so what do we do in this case? */
+ continue;
+ }
+
+ stream = camel_stream_fs_new_with_fd (fd);
+ retval = message_rfc822_dnd (folder, stream, &ex);
+ camel_object_unref (stream);
+ camel_object_unref (folder);
+
+ if (action == GNOME_Evolution_ShellComponentDnd_ACTION_MOVE && retval)
+ unlink (url);
+
+ g_free (url);
+ }
+
+ g_free (urls);
+ break;
+ case ACCEPTED_DND_TYPE_MESSAGE_RFC822:
+ folder = mail_tool_uri_to_folder (physical_uri, 0, &ex);
+ if (!folder) {
+ camel_exception_clear (&ex);
+ return FALSE;
+ }
+
+ /* write the message(s) out to a CamelStream so we can use it */
+ stream = camel_stream_mem_new ();
+ camel_stream_write (stream, data->bytes._buffer, data->bytes._length);
+ camel_stream_reset (stream);
+
+ retval = message_rfc822_dnd (folder, stream, &ex);
+ camel_object_unref (stream);
+ camel_object_unref (folder);
+ break;
+ case ACCEPTED_DND_TYPE_X_EVOLUTION_MESSAGE:
+ folder = mail_tools_x_evolution_message_parse (data->bytes._buffer,
+ data->bytes._length,
+ &uids);
+
+ if (!folder)
+ return FALSE;
+
+ mail_transfer_messages (folder, uids,
+ action == GNOME_Evolution_ShellComponentDnd_ACTION_MOVE,
+ physical_uri, 0, NULL, NULL);
+
+ camel_object_unref (folder);
+ break;
+ default:
+ break;
+ }
+
+ camel_exception_clear (&ex);
+
+ return retval;
+}
+
+
+static struct {
+ char *name, **uri;
+ CamelFolder **folder;
+} standard_folders[] = {
+ { "Drafts", &default_drafts_folder_uri, &drafts_folder },
+ { "Outbox", &default_outbox_folder_uri, &outbox_folder },
+ { "Sent", &default_sent_folder_uri, &sent_folder },
+};
+
+static void
+unref_standard_folders (void)
+{
+ int i;
+
+ for (i = 0; i < sizeof (standard_folders) / sizeof (standard_folders[0]); i++) {
+ if (standard_folders[i].folder) {
+ CamelFolder *folder = *standard_folders[i].folder;
+
+ *standard_folders[i].folder = NULL;
+
+ if (CAMEL_OBJECT (folder)->ref_count == 1)
+ d(printf ("About to finalise folder %s\n", folder->full_name));
+ else
+ d(printf ("Folder %s still has %d extra ref%s on it\n", folder->full_name,
+ CAMEL_OBJECT (folder)->ref_count - 1,
+ CAMEL_OBJECT (folder)->ref_count - 1 == 1 ? "" : "s"));
+
+ camel_object_unref (CAMEL_OBJECT (folder));
+ }
+ }
+}
+
+static void
+got_folder (char *uri, CamelFolder *folder, void *data)
+{
+ CamelFolder **fp = data;
+
+ *fp = folder;
+
+ if (folder) {
+ camel_object_ref (CAMEL_OBJECT (folder));
+
+ /* emit a changed event, this is a little hack so that the folderinfo cache
+ will update knowing whether this is the outbox_folder or not, etc */
+ if (folder == outbox_folder) {
+ CamelFolderChangeInfo *changes = camel_folder_change_info_new();
+
+ camel_object_trigger_event((CamelObject *)folder, "folder_changed", changes);
+ camel_folder_change_info_free(changes);
+ }
+ }
+}
+
+static void
+shell_client_destroy (GtkObject *object)
+{
+ global_shell_client = NULL;
+}
+
+static void
+owner_set_cb (EvolutionShellComponent *shell_component,
+ EvolutionShellClient *shell_client,
+ const char *evolution_homedir,
+ gpointer user_data)
+{
+ GNOME_Evolution_Shell corba_shell;
+ EAccountList *accounts;
+ int i;
+
+ /* FIXME: should we ref this? */
+ global_shell_client = shell_client;
+ g_object_weak_ref ((GObject *) shell_client, (GWeakNotify) shell_client_destroy, NULL);
+
+ evolution_dir = g_strdup (evolution_homedir);
+ mail_session_init ();
+
+ async_event = mail_async_event_new();
+
+ storages_hash = g_hash_table_new (NULL, NULL);
+
+ corba_shell = evolution_shell_client_corba_objref (shell_client);
+
+ for (i = 0; i < sizeof (standard_folders) / sizeof (standard_folders[0]); i++)
+ *standard_folders[i].uri = g_strdup_printf ("file://%s/local/%s", evolution_dir, standard_folders[i].name);
+
+ vfolder_load_storage(corba_shell);
+
+ accounts = mail_config_get_accounts ();
+ mail_load_storages (corba_shell, accounts);
+
+ mail_local_storage_startup (shell_client, evolution_dir);
+ mail_importer_init (shell_client);
+
+ for (i = 0; i < sizeof (standard_folders) / sizeof (standard_folders[0]); i++) {
+ mail_msg_wait (mail_get_folder (*standard_folders[i].uri, CAMEL_STORE_FOLDER_CREATE,
+ got_folder, standard_folders[i].folder, mail_thread_new));
+ }
+
+ mail_autoreceive_setup ();
+
+ {
+ /* setup the global quick-search context */
+ char *user = g_strdup_printf ("%s/searches.xml", evolution_dir);
+ char *system = g_strdup (EVOLUTION_PRIVDATADIR "/searchtypes.xml");
+
+ search_context = rule_context_new ();
+ g_object_set_data_full(G_OBJECT(search_context), "user", user, g_free);
+ g_object_set_data_full(G_OBJECT(search_context), "system", system, g_free);
+
+ rule_context_add_part_set (search_context, "partset", filter_part_get_type (),
+ rule_context_add_part, rule_context_next_part);
+
+ rule_context_add_rule_set (search_context, "ruleset", filter_rule_get_type (),
+ rule_context_add_rule, rule_context_next_rule);
+
+ rule_context_load (search_context, system, user);
+ }
+
+ if (mail_config_is_corrupt ()) {
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE,
+ _("Some of your mail settings seem corrupt, "
+ "please check that everything is in order."));
+ g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog);
+ gtk_widget_show (dialog);
+ }
+
+ /* Everything should be ready now */
+ evolution_folder_info_notify_ready ();
+}
+
+static void
+free_storage (gpointer service, gpointer storage, gpointer data)
+{
+ if (service) {
+ mail_note_store_remove((CamelStore *)service);
+ camel_service_disconnect (CAMEL_SERVICE (service), TRUE, NULL);
+ camel_object_unref (CAMEL_OBJECT (service));
+ }
+
+ if (storage)
+ bonobo_object_unref (BONOBO_OBJECT (storage));
+}
+
+static void
+debug_cb (EvolutionShellComponent *shell_component, gpointer user_data)
+{
+ extern gboolean camel_verbose_debug;
+
+ camel_verbose_debug = 1;
+}
+
+static void
+interactive_cb (EvolutionShellComponent *shell_component, gboolean on,
+ gulong new_view_xid, gpointer user_data)
+{
+ mail_session_set_interactive (on);
+
+ if (on)
+ /* how do we get the parent window? */
+ e_msg_composer_check_autosave(NULL);
+}
+
+static void
+handle_external_uri_cb (EvolutionShellComponent *shell_component,
+ const char *uri,
+ void *data)
+{
+ if (strncmp (uri, "mailto:", 7) != 0) {
+ /* FIXME: Exception? The EvolutionShellComponent object should
+ give me a chance to do so, but currently it doesn't. */
+ g_warning ("Invalid URI requested to mail component -- %s", uri);
+ return;
+ }
+
+ /* FIXME: Sigh. This shouldn't be here. But the code is messy, so
+ I'll just put it here anyway. */
+ em_utils_compose_new_message_with_mailto(NULL, uri);
+}
+
+static void
+user_create_new_item_cb (EvolutionShellComponent *shell_component,
+ const char *id,
+ const char *parent_folder_physical_uri,
+ const char *parent_folder_type,
+ gpointer data)
+{
+ if (!strcmp (id, "message")) {
+ em_utils_compose_new_message_with_mailto(NULL, NULL);
+ /*send_to_url (NULL, parent_folder_physical_uri);*/
+ return;
+ } else if (!strcmp (id, "post")) {
+ em_utils_post_to_url (NULL, parent_folder_physical_uri);
+ return;
+ }
+
+ g_warning ("Don't know how to create item of type \"%s\"", id);
+}
+
+static void owner_unset_cb (EvolutionShellComponent *shell_component, gpointer user_data);
+
+/* Table for signal handler setup/cleanup */
+static struct {
+ char *sig;
+ GCallback func;
+ int hand;
+} shell_component_handlers[] = {
+ { "owner_set", G_CALLBACK(owner_set_cb), },
+ { "owner_unset", G_CALLBACK(owner_unset_cb), },
+ { "debug", G_CALLBACK(debug_cb), },
+ { "interactive", G_CALLBACK(interactive_cb) },
+ { "destroy", G_CALLBACK(owner_unset_cb), },
+ { "handle_external_uri", G_CALLBACK(handle_external_uri_cb), },
+ { "user_create_new_item", G_CALLBACK(user_create_new_item_cb) }
+};
+
+static void
+owner_unset_cb (EvolutionShellComponent *shell_component, gpointer user_data)
+{
+ CORBA_Environment ev;
+ GConfClient *gconf;
+ int i;
+ EIterator *it;
+
+ gconf = mail_config_get_gconf_client ();
+
+ for (i=0;i<sizeof(shell_component_handlers)/sizeof(shell_component_handlers[0]);i++)
+ g_signal_handler_disconnect((GtkObject *)shell_component, shell_component_handlers[i].hand);
+
+ if (gconf_client_get_bool (gconf, "/apps/evolution/mail/trash/empty_on_exit", NULL))
+ em_utils_empty_trash(NULL);
+
+ unref_standard_folders ();
+ mail_local_storage_shutdown ();
+ mail_importer_uninit ();
+
+ global_shell_client = NULL;
+ mail_session_set_interactive (FALSE);
+
+ g_object_unref (search_context);
+ search_context = NULL;
+
+ /* force de-activate of all controls, tho only one should be active anyway? */
+ CORBA_exception_init(&ev);
+ for (it = e_list_get_iterator(folder_browser_factory_get_control_list());
+ e_iterator_is_valid(it);
+ e_iterator_next(it)) {
+ Bonobo_Control_activate(bonobo_object_corba_objref((BonoboObject *)e_iterator_get(it)),
+ FALSE, &ev);
+ }
+ CORBA_exception_free(&ev);
+
+ for (i= 0;i<3;i++) {
+ /* need to flush any outstanding tasks before proceeding */
+
+ /* NOTE!! This may cause a deadlock situation, if we were
+ called from a deeper main loop than the top level
+ - is there a way to detect this?
+ - is this a very big problem?
+ FIXME: should use semaphores or something to wait rather than polling */
+ while (e_thread_busy(NULL) || mail_msg_active(-1)) {
+ if (g_main_context_pending(NULL))
+ g_main_context_iteration(NULL, TRUE);
+ else
+ usleep(100000);
+ }
+
+ switch(i) {
+ case 0:
+ mail_vfolder_shutdown();
+ break;
+ case 1:
+ if (mail_async_event_destroy(async_event) == -1) {
+ g_warning("Cannot destroy async event: would deadlock");
+ g_warning(" system may be unstable at exit");
+ }
+ break;
+ case 2:
+ g_hash_table_foreach (storages_hash, free_storage, NULL);
+ g_hash_table_destroy (storages_hash);
+ storages_hash = NULL;
+ break;
+ }
+ }
+}
+
+static void
+send_receive_cb (EvolutionShellComponent *shell_component,
+ gboolean show_dialog,
+ void *data)
+{
+ EAccount *account;
+ GtkWidget *dialog;
+
+ /* FIXME: configure_mail() should be changed to work without a
+ FolderBrowser, and then we will be able to call configure_mail from
+ here properly. */
+ if (!mail_config_is_configured () /* && !configure_mail (fb) */)
+ return;
+
+ account = mail_config_get_default_account ();
+ if (!account || !account->transport->url) {
+ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ _("You have not set a mail transport method"));
+ g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog);
+ gtk_widget_show (dialog);
+ } else {
+ dialog = mail_send_receive ();
+ e_dialog_set_transient_for_xid((GtkWindow *)dialog, evolution_shell_component_get_parent_view_xid(shell_component));
+ }
+}
+
+static gboolean
+request_quit (EvolutionShellComponent *shell_component,
+ void *closure)
+{
+ GtkWidget *dialog;
+ int resp;
+
+ if (!e_msg_composer_request_close_all ())
+ return FALSE;
+
+ if (!outbox_folder || !camel_folder_get_message_count (outbox_folder))
+ return TRUE;
+
+ dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_YES_NO,
+ _("You have unsent messages, do you wish to quit anyway?"));
+ gtk_dialog_set_default_response((GtkDialog *)dialog, GTK_RESPONSE_NO);
+ resp = gtk_dialog_run((GtkDialog *)dialog);
+ gtk_widget_destroy(dialog);
+
+ return resp == GTK_RESPONSE_YES;
+}
+
+static BonoboObject *
+create_component (void)
+{
+ EvolutionShellComponentDndDestinationFolder *destination_interface;
+ MailOfflineHandler *offline_handler;
+ GdkPixbuf *icon;
+ int i;
+
+ shell_component = evolution_shell_component_new (folder_types,
+ schema_types,
+ create_view,
+ create_folder,
+ remove_folder,
+ xfer_folder,
+ populate_folder_context_menu,
+ unpopulate_folder_context_menu,
+ get_dnd_selection,
+ request_quit,
+ NULL);
+
+ g_signal_connect((shell_component), "send_receive",
+ G_CALLBACK (send_receive_cb), NULL);
+
+ destination_interface = evolution_shell_component_dnd_destination_folder_new (destination_folder_handle_motion,
+ destination_folder_handle_drop,
+ shell_component);
+
+ bonobo_object_add_interface (BONOBO_OBJECT (shell_component),
+ BONOBO_OBJECT (destination_interface));
+
+ icon = gdk_pixbuf_new_from_file (EVOLUTION_ICONSDIR "/new-message.xpm", NULL);
+ evolution_shell_component_add_user_creatable_item (shell_component, "message",
+ _("New Mail Message"), _("_Mail Message"),
+ _("Compose a new mail message"),
+ "mail", 'm',
+ icon);
+ if (icon != NULL)
+ g_object_unref (icon);
+
+ icon = gdk_pixbuf_new_from_file (EVOLUTION_ICONSDIR "/post-message-16.png", NULL);
+ evolution_shell_component_add_user_creatable_item (shell_component, "post",
+ _("New Message Post"), _("_Post Message"),
+ _("Post a new mail message"),
+ "mail/public", 'p',
+ icon);
+ if (icon != NULL)
+ g_object_unref (icon);
+
+ for (i=0;i<sizeof(shell_component_handlers)/sizeof(shell_component_handlers[0]);i++) {
+ shell_component_handlers[i].hand = g_signal_connect((shell_component),
+ shell_component_handlers[i].sig,
+ shell_component_handlers[i].func, NULL);
+ }
+
+ offline_handler = mail_offline_handler_new ();
+ bonobo_object_add_interface (BONOBO_OBJECT (shell_component), BONOBO_OBJECT (offline_handler));
+
+ return BONOBO_OBJECT (shell_component);
+}
+
+static void
+notify_listener (const Bonobo_Listener listener,
+ GNOME_Evolution_Storage_Result corba_result)
+{
+ CORBA_any any;
+ CORBA_Environment ev;
+
+ CORBA_exception_init (&ev);
+
+ any._type = TC_GNOME_Evolution_Storage_Result;
+ any._value = &corba_result;
+
+ Bonobo_Listener_event (listener, "result", &any, &ev);
+
+ CORBA_exception_free (&ev);
+}
+
+static void
+notify_listener_exception(const Bonobo_Listener listener, CamelException *ex)
+{
+ GNOME_Evolution_Storage_Result result;
+
+ switch(camel_exception_get_id(ex)) {
+ case CAMEL_EXCEPTION_SERVICE_UNAVAILABLE:
+ result = GNOME_Evolution_Storage_NOT_ONLINE;
+ break;
+ case CAMEL_EXCEPTION_NONE:
+ result = GNOME_Evolution_Storage_OK;
+ break;
+ case CAMEL_EXCEPTION_FOLDER_INVALID_PATH:
+ case CAMEL_EXCEPTION_SERVICE_URL_INVALID:
+ result = GNOME_Evolution_Storage_INVALID_URI;
+ break;
+ default:
+ result = GNOME_Evolution_Storage_GENERIC_ERROR;
+ break;
+ }
+
+ notify_listener(listener, result);
+}
+
+static void
+storage_create_folder (EvolutionStorage *storage,
+ const Bonobo_Listener listener,
+ const char *path,
+ const char *type,
+ const char *description,
+ const char *parent_physical_uri,
+ gpointer user_data)
+{
+ CamelStore *store = user_data;
+ CamelFolderInfo *root, *fi;
+ char *name;
+ CamelURL *url;
+ CamelException ex;
+
+ /* We could just use 'path' always here? */
+
+ if (!type_is_mail (type)) {
+ notify_listener (listener, GNOME_Evolution_Storage_UNSUPPORTED_TYPE);
+ return;
+ }
+
+ name = strrchr (path, '/');
+ if (!name) {
+ notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI);
+ return;
+ }
+ name++;
+
+ /* we can not directly create folders on a vfolder store, so fudge it */
+ if (CAMEL_IS_VEE_STORE(store)) {
+ VfolderRule *rule;
+ rule = vfolder_rule_new();
+
+ filter_rule_set_name((FilterRule *)rule, path+1);
+ vfolder_gui_add_rule(rule);
+ } else {
+ camel_exception_init (&ex);
+ if (*parent_physical_uri) {
+ url = camel_url_new (parent_physical_uri, NULL);
+ if (!url) {
+ notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI);
+ return;
+ }
+
+ root = camel_store_create_folder (store, url->fragment?url->fragment:url->path + 1, name, &ex);
+ camel_url_free (url);
+ } else
+ root = camel_store_create_folder (store, NULL, name, &ex);
+
+ if (camel_exception_is_set (&ex)) {
+ notify_listener_exception(listener, &ex);
+ camel_exception_clear (&ex);
+ return;
+ }
+
+ if (camel_store_supports_subscriptions (store)) {
+ for (fi = root; fi; fi = fi->child)
+ camel_store_subscribe_folder (store, fi->full_name, NULL);
+ }
+
+ camel_store_free_folder_info (store, root);
+ }
+
+ notify_listener (listener, GNOME_Evolution_Storage_OK);
+}
+
+static void
+storage_remove_folder_recursive (EvolutionStorage *storage, CamelStore *store, CamelFolderInfo *root, CamelException *ex)
+{
+ CamelFolderInfo *fi;
+
+ /* delete all children */
+ fi = root->child;
+ while (fi && !camel_exception_is_set (ex)) {
+ storage_remove_folder_recursive (storage, store, fi, ex);
+ fi = fi->sibling;
+ }
+
+ if (!camel_exception_is_set (ex)) {
+ if (camel_store_supports_subscriptions (store))
+ camel_store_unsubscribe_folder (store, root->full_name, NULL);
+
+ camel_store_delete_folder (store, root->full_name, ex);
+
+ if (!camel_exception_is_set (ex))
+ evolution_storage_removed_folder (storage, root->path);
+ }
+}
+
+static void
+storage_remove_folder (EvolutionStorage *storage,
+ const Bonobo_Listener listener,
+ const char *path,
+ const char *physical_uri,
+ gpointer user_data)
+{
+ CamelStore *store = user_data;
+ CamelFolderInfo *root, *fi;
+ CamelURL *url = NULL;
+ CamelException ex;
+ char *name;
+
+ g_warning ("storage_remove_folder: path=\"%s\"; uri=\"%s\"", path, physical_uri);
+
+ if (!path || !*path || !physical_uri || !strncmp (physical_uri, "vtrash:", 7) || !strncmp (physical_uri, "vjunk:", 6)) {
+ notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI);
+ return;
+ }
+
+ url = camel_url_new (physical_uri, NULL);
+ if (!url) {
+ notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI);
+ return;
+ }
+
+ if (url->fragment)
+ name = url->fragment;
+ else if (url->path && url->path[0])
+ name = url->path+1;
+ else
+ name = "";
+
+ camel_exception_init (&ex);
+
+ root = camel_store_get_folder_info (store, name, CAMEL_STORE_FOLDER_INFO_FAST |
+ CAMEL_STORE_FOLDER_INFO_RECURSIVE, &ex);
+
+ if (!root || camel_exception_is_set (&ex)) {
+ notify_listener_exception (listener, &ex);
+ camel_exception_clear (&ex);
+ camel_url_free (url);
+ return;
+ }
+
+ /* walk the tree until we find the particular child folder we want to delete */
+ fi = root;
+ while (fi) {
+ if (!strcmp (fi->full_name, name))
+ break;
+ fi = fi->child;
+ }
+
+ camel_url_free (url);
+
+ if (!fi) {
+ notify_listener (listener, GNOME_Evolution_Storage_INVALID_URI);
+ camel_store_free_folder_info (store, root);
+ return;
+ }
+
+ storage_remove_folder_recursive (storage, store, fi, &ex);
+ camel_store_free_folder_info (store, root);
+ if (camel_exception_is_set (&ex)) {
+ notify_listener_exception (listener, &ex);
+ camel_exception_clear (&ex);
+ } else {
+ notify_listener (listener, GNOME_Evolution_Storage_OK);
+ }
+}
+
+static void
+storage_xfer_folder (EvolutionStorage *storage,
+ const Bonobo_Listener listener,
+ const char *source_path,
+ const char *destination_path,
+ gboolean remove_source,
+ CamelStore *store)
+{
+ CamelException ex;
+ char *src, *dst;
+ char sep;
+
+ d(printf("Transfer folder on store source = '%s' dest = '%s'\n", source_path, destination_path));
+
+ /* FIXME: this is totally not gonna work once we have namespaces */
+
+ /* Remap the 'path' to the camel friendly name based on the store dir separator */
+ sep = store->dir_sep;
+ src = g_strdup(source_path[0]=='/'?source_path+1:source_path);
+ dst = g_strdup(destination_path[0]=='/'?destination_path+1:destination_path);
+ camel_exception_init (&ex);
+ if (remove_source) {
+ d(printf("trying to rename\n"));
+ camel_store_rename_folder(store, src, dst, &ex);
+ notify_listener_exception(listener, &ex);
+ } else {
+ d(printf("No remove, can't rename\n"));
+ /* FIXME: Implement folder 'copy' for remote stores */
+ /* This exception never goes anywhere, so it doesn't need translating or using */
+ notify_listener (listener, GNOME_Evolution_Storage_UNSUPPORTED_OPERATION);
+ }
+
+ g_free(src);
+ g_free(dst);
+
+ camel_exception_clear (&ex);
+}
+
+static void
+storage_connected (CamelStore *store, CamelFolderInfo *info, void *listener)
+{
+ notify_listener (listener, (info ? GNOME_Evolution_Storage_OK :
+ GNOME_Evolution_Storage_GENERIC_ERROR));
+}
+
+static void
+storage_connect (EvolutionStorage *storage,
+ const Bonobo_Listener listener,
+ const char *path,
+ CamelStore *store)
+{
+ mail_note_store (CAMEL_STORE (store), NULL, storage, CORBA_OBJECT_NIL,
+ storage_connected, listener);
+}
+
+static void
+add_storage (const char *name, const char *uri, CamelService *store,
+ GNOME_Evolution_Shell corba_shell, CamelException *ex)
+{
+ EvolutionStorage *storage;
+ EvolutionStorageResult res;
+
+ storage = evolution_storage_new (name, FALSE);
+ g_signal_connect(storage, "open_folder", G_CALLBACK(storage_connect), store);
+ g_signal_connect(storage, "create_folder", G_CALLBACK(storage_create_folder), store);
+ g_signal_connect(storage, "remove_folder", G_CALLBACK(storage_remove_folder), store);
+ g_signal_connect(storage, "xfer_folder", G_CALLBACK(storage_xfer_folder), store);
+
+ res = evolution_storage_register_on_shell (storage, corba_shell);
+
+ switch (res) {
+ case EVOLUTION_STORAGE_OK:
+ evolution_storage_has_subfolders (storage, "/", _("Connecting..."));
+ mail_hash_storage (store, storage);
+ /*if (auto_connect)*/
+ mail_note_store ((CamelStore *) store, NULL, storage, CORBA_OBJECT_NIL, NULL, NULL);
+ /* falllll */
+ case EVOLUTION_STORAGE_ERROR_ALREADYREGISTERED:
+ case EVOLUTION_STORAGE_ERROR_EXISTS:
+ bonobo_object_unref (BONOBO_OBJECT (storage));
+ return;
+ default:
+ camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Cannot register storage with shell"));
+ break;
+ }
+}
+
+void
+mail_add_storage (CamelStore *store, const char *name, const char *uri)
+{
+ EvolutionShellClient *shell_client;
+ GNOME_Evolution_Shell shell;
+ CamelException ex;
+
+ g_return_if_fail (CAMEL_IS_STORE (store));
+
+ shell_client = evolution_shell_component_get_owner (shell_component);
+ shell = evolution_shell_client_corba_objref (shell_client);
+
+ camel_exception_init (&ex);
+
+ if (name == NULL) {
+ char *service_name;
+
+ service_name = camel_service_get_name ((CamelService *) store, TRUE);
+ add_storage (service_name, uri, (CamelService *) store, shell, &ex);
+ g_free (service_name);
+ } else {
+ add_storage (name, uri, (CamelService *) store, shell, &ex);
+ }
+
+ camel_exception_clear (&ex);
+}
+
+void
+mail_load_storage_by_uri (GNOME_Evolution_Shell shell, const char *uri, const char *name)
+{
+ CamelException ex;
+ CamelService *store;
+ CamelProvider *prov;
+
+ camel_exception_init (&ex);
+
+ /* Load the service (don't connect!). Check its provider and
+ * see if this belongs in the shell's folder list. If so, add
+ * it.
+ */
+
+ prov = camel_session_get_provider (session, uri, &ex);
+ if (prov == NULL) {
+ /* FIXME: real error dialog */
+ g_warning ("couldn't get service %s: %s\n", uri,
+ camel_exception_get_description (&ex));
+ camel_exception_clear (&ex);
+ return;
+ }
+
+ if (!(prov->flags & CAMEL_PROVIDER_IS_STORAGE) ||
+ (prov->flags & CAMEL_PROVIDER_IS_EXTERNAL))
+ return;
+
+ store = camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, &ex);
+ if (store == NULL) {
+ /* FIXME: real error dialog */
+ g_warning ("couldn't get service %s: %s\n", uri,
+ camel_exception_get_description (&ex));
+ camel_exception_clear (&ex);
+ return;
+ }
+
+ if (name == NULL) {
+ char *service_name;
+
+ service_name = camel_service_get_name (store, TRUE);
+ add_storage (service_name, uri, store, shell, &ex);
+ g_free (service_name);
+ } else
+ add_storage (name, uri, store, shell, &ex);
+
+ if (camel_exception_is_set (&ex)) {
+ /* FIXME: real error dialog */
+ g_warning ("Cannot load storage: %s",
+ camel_exception_get_description (&ex));
+ camel_exception_clear (&ex);
+ }
+
+ camel_object_unref (CAMEL_OBJECT (store));
+}
+
+void
+mail_load_storages (GNOME_Evolution_Shell shell, EAccountList *accounts)
+{
+ CamelException ex;
+ EIterator *iter;
+
+ camel_exception_init (&ex);
+
+ /* Load each service (don't connect!). Check its provider and
+ * see if this belongs in the shell's folder list. If so, add
+ * it.
+ */
+
+ iter = e_list_get_iterator ((EList *) accounts);
+ while (e_iterator_is_valid (iter)) {
+ EAccountService *service;
+ EAccount *account;
+ const char *name;
+
+ account = (EAccount *) e_iterator_get (iter);
+ service = account->source;
+ name = account->name;
+
+ if (account->enabled && service->url != NULL)
+ mail_load_storage_by_uri (shell, service->url, name);
+
+ e_iterator_next (iter);
+ }
+
+ g_object_unref (iter);
+}
+
+void
+mail_hash_storage (CamelService *store, EvolutionStorage *storage)
+{
+ camel_object_ref (CAMEL_OBJECT (store));
+ g_hash_table_insert (storages_hash, store, storage);
+}
+
+EvolutionStorage *
+mail_lookup_storage (CamelStore *store)
+{
+ EvolutionStorage *storage;
+
+ /* Because the storages_hash holds a reference to each store
+ * used as a key in it, none of them will ever be gc'ed, meaning
+ * any call to camel_session_get_{service,store} with the same
+ * URL will always return the same object. So this works.
+ */
+
+ storage = g_hash_table_lookup (storages_hash, store);
+ if (storage)
+ bonobo_object_ref (BONOBO_OBJECT (storage));
+
+ return storage;
+}
+
+static void
+store_disconnect(CamelStore *store, void *event_data, void *data)
+{
+ camel_service_disconnect (CAMEL_SERVICE (store), TRUE, NULL);
+ camel_object_unref (CAMEL_OBJECT (store));
+}
+
+void
+mail_remove_storage (CamelStore *store)
+{
+ EvolutionStorage *storage;
+ EvolutionShellClient *shell_client;
+ GNOME_Evolution_Shell corba_shell;
+
+ /* Because the storages_hash holds a reference to each store
+ * used as a key in it, none of them will ever be gc'ed, meaning
+ * any call to camel_session_get_{service,store} with the same
+ * URL will always return the same object. So this works.
+ */
+
+ storage = g_hash_table_lookup (storages_hash, store);
+ if (!storage)
+ return;
+
+ g_hash_table_remove (storages_hash, store);
+
+ /* so i guess potentially we could have a race, add a store while one
+ being removed. ?? */
+ mail_note_store_remove(store);
+
+ shell_client = evolution_shell_component_get_owner (shell_component);
+ corba_shell = evolution_shell_client_corba_objref(shell_client);
+
+ evolution_storage_deregister_on_shell (storage, corba_shell);
+
+ mail_async_event_emit(async_event, MAIL_ASYNC_THREAD, (MailAsyncFunc)store_disconnect, store, NULL, NULL);
+}
+
+void
+mail_remove_storage_by_uri (const char *uri)
+{
+ CamelProvider *prov;
+ CamelService *store;
+
+ prov = camel_session_get_provider (session, uri, NULL);
+ if (!prov)
+ return;
+ if (!(prov->flags & CAMEL_PROVIDER_IS_STORAGE) ||
+ (prov->flags & CAMEL_PROVIDER_IS_EXTERNAL))
+ return;
+
+ store = camel_session_get_service (session, uri, CAMEL_PROVIDER_STORE, NULL);
+ if (store != NULL) {
+ mail_remove_storage (CAMEL_STORE (store));
+ camel_object_unref (CAMEL_OBJECT (store));
+ }
+}
+
+int
+mail_storages_count (void)
+{
+ return g_hash_table_size (storages_hash);
+}
+
+void
+mail_storages_foreach (GHFunc func, gpointer data)
+{
+ g_hash_table_foreach (storages_hash, func, data);
+}
+
+
+#define FACTORY_ID "OAFIID:GNOME_Evolution_Mail_ControlFactory"
+
+#define MAIL_CONFIG_IID "OAFIID:GNOME_Evolution_MailConfig"
+#define WIZARD_IID "OAFIID:GNOME_Evolution_Mail_Wizard"
+#define FOLDER_INFO_IID "OAFIID:GNOME_Evolution_FolderInfo"
+#define COMPOSER_IID "OAFIID:GNOME_Evolution_Mail_Composer"
+
+static BonoboObject *
+factory (BonoboGenericFactory *factory,
+ const char *component_id,
+ void *closure)
+{
+ if (strcmp (component_id, COMPONENT_ID) == 0)
+ return create_component();
+ else if (strcmp(component_id, MAIL_CONFIG_IID) == 0)
+ return (BonoboObject *)g_object_new (evolution_mail_config_get_type (), NULL);
+ else if (strcmp(component_id, FOLDER_INFO_IID) == 0)
+ return evolution_folder_info_new();
+ else if (strcmp(component_id, WIZARD_IID) == 0)
+ return evolution_mail_config_wizard_new();
+ else if (strcmp (component_id, MAIL_ACCOUNTS_CONTROL_ID) == 0
+ || strcmp (component_id, MAIL_PREFERENCES_CONTROL_ID) == 0
+ || strcmp (component_id, MAIL_COMPOSER_PREFS_CONTROL_ID) == 0)
+ return mail_config_control_factory_cb (factory, component_id, evolution_shell_client_corba_objref (global_shell_client));
+ else if (strcmp(component_id, COMPOSER_IID) == 0)
+ return (BonoboObject *)evolution_composer_new(em_utils_composer_send_cb, em_utils_composer_save_draft_cb);
+
+ g_warning (FACTORY_ID ": Don't know what to do with %s", component_id);
+ return NULL;
+}
+
+static Bonobo_Unknown
+make_factory (PortableServer_POA poa, const char *iid, gpointer impl_ptr, CORBA_Environment *ev)
+{
+ static int init = 0;
+
+ if (!init) {
+ /* init ? */
+ mail_config_init ();
+ mail_msg_init ();
+ init = 1;
+ }
+
+ return bonobo_shlib_factory_std (FACTORY_ID, poa, impl_ptr, factory, NULL, ev);
+}
+
+static BonoboActivationPluginObject plugin_list[] = {
+ {FACTORY_ID, make_factory},
+ { NULL }
+};
+const BonoboActivationPlugin Bonobo_Plugin_info = {
+ plugin_list, "Evolution Mail component factory"
+};
+
diff --git a/mail/em-folder-view.c b/mail/em-folder-view.c
index 0c52a49fe1..2b61169518 100644
--- a/mail/em-folder-view.c
+++ b/mail/em-folder-view.c
@@ -60,7 +60,6 @@
#include "em-format-html-display.h"
#include "em-format-html-print.h"
-#include "em-folder-selection.h"
#include "em-folder-view.h"
#include "em-message-browser.h"
#include "message-list.h"
@@ -294,7 +293,7 @@ em_folder_view_open_selected(EMFolderView *emfv)
if (em_utils_folder_is_drafts(emfv->folder, emfv->folder_uri)
|| em_utils_folder_is_outbox(emfv->folder, emfv->folder_uri)) {
- em_utils_edit_messages (emfv->folder, uids);
+ em_utils_edit_messages((GtkWidget *)emfv, emfv->folder, uids);
} else {
/* TODO: have an em_utils_open_messages call? */
@@ -421,7 +420,7 @@ emfv_popup_resend(GtkWidget *w, EMFolderView *emfv)
return;
uids = message_list_get_selected(emfv->list);
- em_utils_edit_messages (emfv->folder, uids);
+ em_utils_edit_messages((GtkWidget *)emfv, emfv->folder, uids);
}
static void
@@ -466,7 +465,7 @@ emfv_popup_forward(GtkWidget *w, EMFolderView *emfv)
return;
uids = message_list_get_selected(emfv->list);
- em_utils_forward_messages (emfv->folder, uids);
+ em_utils_forward_messages((GtkWidget *)emfv, emfv->folder, uids);
}
static void
@@ -524,6 +523,18 @@ emfv_popup_mark_unimportant(GtkWidget *w, EMFolderView *emfv)
}
static void
+emfv_popup_mark_junk (GtkWidget *w, EMFolderView *emfv)
+{
+ mail_mark_junk (emfv->folder, emfv->list, TRUE);
+}
+
+static void
+emfv_popup_mark_nojunk (GtkWidget *w, EMFolderView *emfv)
+{
+ mail_mark_junk (emfv->folder, emfv->list, FALSE);
+}
+
+static void
emfv_popup_delete(GtkWidget *w, EMFolderView *emfv)
{
GPtrArray *uids;
@@ -543,52 +554,16 @@ emfv_popup_undelete(GtkWidget *w, EMFolderView *emfv)
em_folder_view_mark_selected(emfv, CAMEL_MESSAGE_DELETED, 0);
}
-struct _move_data {
- EMFolderView *emfv;
- GPtrArray *uids;
- int delete;
-};
-
-static void
-emfv_popup_move_cb(const char *uri, void *data)
-{
- struct _move_data *d = data;
-
- if (uri)
- mail_transfer_messages(d->emfv->folder, d->uids, d->delete, uri, 0, NULL, NULL);
- else
- em_utils_uids_free(d->uids);
-
- g_object_unref(d->emfv);
- g_free(d);
-}
-
static void
emfv_popup_move(GtkWidget *w, EMFolderView *emfv)
{
- struct _move_data *d;
-
- d = g_malloc(sizeof(*d));
- d->emfv = emfv;
- g_object_ref(emfv);
- d->uids = message_list_get_selected(emfv->list);
- d->delete = TRUE;
-
- em_select_folder ((GtkWindow *) emfv, _("Select folder"), NULL, NULL, emfv_popup_move_cb, d);
+ /* FIXME */
}
static void
emfv_popup_copy(GtkWidget *w, EMFolderView *emfv)
{
- struct _move_data *d;
-
- d = g_malloc(sizeof(*d));
- d->emfv = emfv;
- g_object_ref(emfv);
- d->uids = message_list_get_selected(emfv->list);
- d->delete = FALSE;
-
- em_select_folder ((GtkWindow *) emfv, _("Select folder"), NULL, NULL, emfv_popup_move_cb, d);
+ /* FIXME */
}
static void
@@ -644,13 +619,11 @@ EMFV_POPUP_AUTO_TYPE(vfolder_type_current, emfv_popup_vfolder_subject, AUTO_SUBJ
EMFV_POPUP_AUTO_TYPE(vfolder_type_current, emfv_popup_vfolder_sender, AUTO_FROM)
EMFV_POPUP_AUTO_TYPE(vfolder_type_current, emfv_popup_vfolder_recipients, AUTO_TO)
EMFV_POPUP_AUTO_TYPE(vfolder_type_current, emfv_popup_vfolder_mlist, AUTO_MLIST)
-EMFV_POPUP_AUTO_TYPE(vfolder_type_current, emfv_popup_vfolder_thread, AUTO_THREAD)
EMFV_POPUP_AUTO_TYPE(filter_type_current, emfv_popup_filter_subject, AUTO_SUBJECT)
EMFV_POPUP_AUTO_TYPE(filter_type_current, emfv_popup_filter_sender, AUTO_FROM)
EMFV_POPUP_AUTO_TYPE(filter_type_current, emfv_popup_filter_recipients, AUTO_TO)
EMFV_POPUP_AUTO_TYPE(filter_type_current, emfv_popup_filter_mlist, AUTO_MLIST)
-EMFV_POPUP_AUTO_TYPE(filter_type_current, emfv_popup_filter_thread, AUTO_THREAD)
/* TODO: Move some of these to be 'standard' menu's */
@@ -676,6 +649,8 @@ static EMPopupItem emfv_popup_menu[] = {
{ EM_POPUP_ITEM, "30.emfv.01", N_("Mark as _Unread"), G_CALLBACK(emfv_popup_mark_unread), NULL, "mail-new.xpm", EM_POPUP_SELECT_MARK_UNREAD },
{ EM_POPUP_ITEM, "30.emfv.02", N_("Mark as _Important"), G_CALLBACK(emfv_popup_mark_important), NULL, "priority-high.xpm", EM_POPUP_SELECT_MARK_IMPORTANT },
{ EM_POPUP_ITEM, "30.emfv.03", N_("_Mark as Unimportant"), G_CALLBACK(emfv_popup_mark_unimportant), NULL, NULL, EM_POPUP_SELECT_MARK_UNIMPORTANT },
+ { EM_POPUP_ITEM, "30.emfv.04", N_("Mark as _Junk"), G_CALLBACK(emfv_popup_mark_junk), NULL, NULL, EM_POPUP_SELECT_MARK_JUNK },
+ { EM_POPUP_ITEM, "30.emfv.05", N_("Mark as _Not Junk"), G_CALLBACK(emfv_popup_mark_nojunk), NULL, NULL, EM_POPUP_SELECT_MARK_NOJUNK },
{ EM_POPUP_BAR, "40.emfv" },
{ EM_POPUP_ITEM, "40.emfv.00", N_("_Delete"), G_CALLBACK(emfv_popup_delete), NULL, "evolution-trash-mini.png", EM_POPUP_SELECT_DELETE },
@@ -703,17 +678,13 @@ static EMPopupItem emfv_popup_menu[] = {
{ EM_POPUP_ITEM, "90.filter.00/00.02", N_("VFolder on _Recipients"), G_CALLBACK(emfv_popup_vfolder_recipients), NULL, NULL, EM_POPUP_SELECT_ONE },
{ EM_POPUP_ITEM, "90.filter.00/00.03", N_("VFolder on Mailing _List"),
G_CALLBACK(emfv_popup_vfolder_mlist), NULL, NULL, EM_POPUP_SELECT_ONE|EM_POPUP_SELECT_MAILING_LIST },
- { EM_POPUP_ITEM, "90.filter.00/00.04", N_("VFolder on Thread"),
- G_CALLBACK(emfv_popup_vfolder_thread), NULL, NULL, EM_POPUP_SELECT_ONE },
-
+
{ EM_POPUP_BAR, "90.filter.00/10", NULL, NULL, NULL, NULL, EM_POPUP_SELECT_ONE },
{ EM_POPUP_ITEM, "90.filter.00/10.00", N_("Filter on Sub_ject"), G_CALLBACK(emfv_popup_filter_subject), NULL, NULL, EM_POPUP_SELECT_ONE },
{ EM_POPUP_ITEM, "90.filter.00/10.01", N_("Filter on Sen_der"), G_CALLBACK(emfv_popup_filter_sender), NULL, NULL, EM_POPUP_SELECT_ONE },
{ EM_POPUP_ITEM, "90.filter.00/10.02", N_("Filter on Re_cipients"), G_CALLBACK(emfv_popup_filter_recipients), NULL, NULL, EM_POPUP_SELECT_ONE },
{ EM_POPUP_ITEM, "90.filter.00/10.03", N_("Filter on _Mailing List"),
G_CALLBACK(emfv_popup_filter_mlist), NULL, NULL, EM_POPUP_SELECT_ONE|EM_POPUP_SELECT_MAILING_LIST },
- { EM_POPUP_ITEM, "90.filter.00/10.04", N_("Filter on Thread"),
- G_CALLBACK(emfv_popup_filter_thread), NULL, NULL, EM_POPUP_SELECT_ONE },
};
static void
@@ -821,6 +792,8 @@ EMFV_MAP_CALLBACK(emfv_message_mark_read, emfv_popup_mark_read)
EMFV_MAP_CALLBACK(emfv_message_mark_unread, emfv_popup_mark_unread)
EMFV_MAP_CALLBACK(emfv_message_mark_important, emfv_popup_mark_important)
EMFV_MAP_CALLBACK(emfv_message_mark_unimportant, emfv_popup_mark_unimportant)
+EMFV_MAP_CALLBACK(emfv_message_mark_junk, emfv_popup_mark_junk)
+EMFV_MAP_CALLBACK(emfv_message_mark_nojunk, emfv_popup_mark_nojunk)
EMFV_MAP_CALLBACK(emfv_message_delete, emfv_popup_delete)
EMFV_MAP_CALLBACK(emfv_message_undelete, emfv_popup_undelete)
EMFV_MAP_CALLBACK(emfv_message_followup_flag, emfv_popup_flag_followup)
@@ -936,7 +909,7 @@ emfv_message_forward_attached (BonoboUIComponent *uic, void *data, const char *p
return;
uids = message_list_get_selected (emfv->list);
- em_utils_forward_attached (emfv->folder, uids);
+ em_utils_forward_attached ((GtkWidget *) emfv, emfv->folder, uids);
}
static void
@@ -949,7 +922,7 @@ emfv_message_forward_inline (BonoboUIComponent *uic, void *data, const char *pat
return;
uids = message_list_get_selected (emfv->list);
- em_utils_forward_inline (emfv->folder, uids);
+ em_utils_forward_inline ((GtkWidget *) emfv, emfv->folder, uids);
}
static void
@@ -962,7 +935,7 @@ emfv_message_forward_quoted (BonoboUIComponent *uic, void *data, const char *pat
return;
uids = message_list_get_selected (emfv->list);
- em_utils_forward_quoted (emfv->folder, uids);
+ em_utils_forward_quoted ((GtkWidget *) emfv, emfv->folder, uids);
}
static void
@@ -976,7 +949,7 @@ emfv_message_redirect (BonoboUIComponent *uic, void *data, const char *path)
if (!em_utils_check_user_can_send_mail ((GtkWidget *) emfv))
return;
- em_utils_redirect_message_by_uid (emfv->folder, emfv->list->cursor_uid);
+ em_utils_redirect_message_by_uid ((GtkWidget *) emfv, emfv->folder, emfv->list->cursor_uid);
}
static void
@@ -990,7 +963,7 @@ emfv_message_post_reply (BonoboUIComponent *uic, void *data, const char *path)
if (!em_utils_check_user_can_send_mail ((GtkWidget *) emfv))
return;
- em_utils_post_reply_to_message_by_uid (emfv->folder, emfv->list->cursor_uid);
+ em_utils_post_reply_to_message_by_uid ((GtkWidget *) emfv, emfv->folder, emfv->list->cursor_uid);
}
static void
@@ -1041,10 +1014,10 @@ emfv_message_reply(EMFolderView *emfv, int mode)
html_engine_save_buffer_free(state);
- em_utils_reply_to_message (msg, mode);
+ em_utils_reply_to_message((GtkWidget *)emfv, msg, mode);
camel_object_unref(msg);
} else {
- em_utils_reply_to_message_by_uid (emfv->folder, emfv->list->cursor_uid, mode);
+ em_utils_reply_to_message_by_uid ((GtkWidget *) emfv, emfv->folder, emfv->list->cursor_uid, mode);
}
/*g_object_unref(clip);*/
@@ -1102,7 +1075,6 @@ struct _filter_data {
int type;
char *uri;
char *mlist;
- char *references;
};
static void
@@ -1113,7 +1085,6 @@ filter_data_free (struct _filter_data *fdata)
if (fdata->folder)
camel_object_unref (fdata->folder);
g_free (fdata->mlist);
- g_free (fdata->references);
g_free (fdata);
}
@@ -1164,7 +1135,6 @@ EMFV_MAP_CALLBACK(emfv_tools_filter_subject, emfv_popup_filter_subject)
EMFV_MAP_CALLBACK(emfv_tools_filter_sender, emfv_popup_filter_sender)
EMFV_MAP_CALLBACK(emfv_tools_filter_recipient, emfv_popup_filter_recipients)
EMFV_MAP_CALLBACK(emfv_tools_filter_mlist, emfv_popup_filter_mlist)
-EMFV_MAP_CALLBACK(emfv_tools_filter_thread, emfv_popup_filter_thread)
static void
vfolder_type_got_message (CamelFolder *folder, const char *uid, CamelMimeMessage *msg, void *user_data)
@@ -1206,7 +1176,6 @@ EMFV_MAP_CALLBACK(emfv_tools_vfolder_subject, emfv_popup_vfolder_subject)
EMFV_MAP_CALLBACK(emfv_tools_vfolder_sender, emfv_popup_vfolder_sender)
EMFV_MAP_CALLBACK(emfv_tools_vfolder_recipient, emfv_popup_vfolder_recipients)
EMFV_MAP_CALLBACK(emfv_tools_vfolder_mlist, emfv_popup_vfolder_mlist)
-EMFV_MAP_CALLBACK(emfv_tools_vfolder_thread, emfv_popup_vfolder_thread)
/* ********************************************************************** */
@@ -1246,6 +1215,8 @@ static BonoboUIVerb emfv_message_verbs[] = {
BONOBO_UI_UNSAFE_VERB ("MessageMarkAsUnRead", emfv_message_mark_unread),
BONOBO_UI_UNSAFE_VERB ("MessageMarkAsImportant", emfv_message_mark_important),
BONOBO_UI_UNSAFE_VERB ("MessageMarkAsUnimportant", emfv_message_mark_unimportant),
+ BONOBO_UI_UNSAFE_VERB ("MessageMarkAsJunk", emfv_message_mark_junk),
+ BONOBO_UI_UNSAFE_VERB ("MessageMarkAsNojunk", emfv_message_mark_nojunk),
BONOBO_UI_UNSAFE_VERB ("MessageFollowUpFlag", emfv_message_followup_flag),
BONOBO_UI_UNSAFE_VERB ("MessageMove", emfv_message_move),
BONOBO_UI_UNSAFE_VERB ("MessageOpen", emfv_message_open),
@@ -1270,12 +1241,10 @@ static BonoboUIVerb emfv_message_verbs[] = {
BONOBO_UI_UNSAFE_VERB ("ToolsFilterRecipient", emfv_tools_filter_recipient),
BONOBO_UI_UNSAFE_VERB ("ToolsFilterSender", emfv_tools_filter_sender),
BONOBO_UI_UNSAFE_VERB ("ToolsFilterSubject", emfv_tools_filter_subject),
- BONOBO_UI_UNSAFE_VERB ("ToolsFilterThread", emfv_tools_filter_thread),
BONOBO_UI_UNSAFE_VERB ("ToolsVFolderMailingList", emfv_tools_vfolder_mlist),
BONOBO_UI_UNSAFE_VERB ("ToolsVFolderRecipient", emfv_tools_vfolder_recipient),
BONOBO_UI_UNSAFE_VERB ("ToolsVFolderSender", emfv_tools_vfolder_sender),
BONOBO_UI_UNSAFE_VERB ("ToolsVFolderSubject", emfv_tools_vfolder_subject),
- BONOBO_UI_UNSAFE_VERB ("ToolsVFolderThread", emfv_tools_vfolder_thread),
BONOBO_UI_UNSAFE_VERB ("ViewLoadImages", emfv_view_load_images),
/* ViewHeaders stuff is a radio */
@@ -1348,6 +1317,8 @@ static const EMFolderViewEnable emfv_enable_map[] = {
{ "MessageMarkAsUnRead", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_UNREAD },
{ "MessageMarkAsImportant", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_IMPORTANT },
{ "MessageMarkAsUnimportant", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_UNIMPORTANT },
+ { "MessageMarkAsJunk", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_JUNK },
+ { "MessageMarkAsNojunk", EM_POPUP_SELECT_MANY|EM_POPUP_SELECT_MARK_NOJUNK },
{ "MessageFollowUpFlag", EM_POPUP_SELECT_MANY },
{ "MessageMove", EM_POPUP_SELECT_MANY },
{ "MessageOpen", EM_POPUP_SELECT_MANY },
@@ -1369,13 +1340,11 @@ static const EMFolderViewEnable emfv_enable_map[] = {
{ "ToolsFilterMailingList", EM_POPUP_SELECT_ONE },
{ "ToolsFilterRecipient", EM_POPUP_SELECT_ONE },
{ "ToolsFilterSender", EM_POPUP_SELECT_ONE },
- { "ToolsFilterSubject", EM_POPUP_SELECT_ONE },
- { "ToolsFilterThread", EM_POPUP_SELECT_ONE },
+ { "ToolsFilterSubject", EM_POPUP_SELECT_ONE },
{ "ToolsVFolderMailingList", EM_POPUP_SELECT_ONE },
{ "ToolsVFolderRecipient", EM_POPUP_SELECT_ONE },
{ "ToolsVFolderSender", EM_POPUP_SELECT_ONE },
{ "ToolsVFolderSubject", EM_POPUP_SELECT_ONE },
- { "ToolsVFolderThread", EM_POPUP_SELECT_ONE },
{ "ViewLoadImages", EM_POPUP_SELECT_ONE },
@@ -1758,7 +1727,7 @@ static void
emfv_format_link_clicked(EMFormatHTMLDisplay *efhd, const char *uri, EMFolderView *emfv)
{
if (!strncasecmp (uri, "mailto:", 7)) {
- em_utils_compose_new_message_with_mailto (uri);
+ em_utils_compose_new_message_with_mailto ((GtkWidget *) efhd, uri);
} else if (*uri == '#') {
gtk_html_jump_to_anchor (((EMFormatHTML *) efhd)->html, uri + 1);
} else if (!strncasecmp (uri, "thismessage:", 12)) {
diff --git a/mail/em-junk-filter.c b/mail/em-junk-filter.c
new file mode 100644
index 0000000000..04bbadc2ba
--- /dev/null
+++ b/mail/em-junk-filter.c
@@ -0,0 +1,327 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Author:
+ * Radek Doulik <rodo@ximian.com>
+ *
+ * Copyright 2003 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <pthread.h>
+
+#include <camel/camel-data-wrapper.h>
+#include <camel/camel-stream-fs.h>
+
+#include "em-junk-filter.h"
+
+#define LOCK(x) pthread_mutex_lock(&x)
+#define UNLOCK(x) pthread_mutex_unlock(&x)
+
+static pthread_mutex_t em_junk_sa_test_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static const char * em_junk_sa_get_name (void);
+static gboolean em_junk_sa_check_junk (CamelMimeMessage *msg);
+static void em_junk_sa_report_junk (CamelMimeMessage *msg);
+static void em_junk_sa_report_notjunk (CamelMimeMessage *msg);
+static void em_junk_sa_commit_reports (void);
+
+static EMJunkPlugin spam_assassin_plugin =
+{
+ {
+ em_junk_sa_get_name,
+ 1,
+ em_junk_sa_check_junk,
+ em_junk_sa_report_junk,
+ em_junk_sa_report_notjunk,
+ em_junk_sa_commit_reports,
+ },
+ NULL,
+ NULL
+};
+
+static gboolean em_junk_sa_spamd_tested = FALSE;
+static gboolean em_junk_sa_use_spamc = FALSE;
+static gint em_junk_sa_spamd_port = -1;
+
+#define d(x) x
+
+static const char *
+em_junk_sa_get_name (void)
+{
+ return _("Spamassassin (built-in)");
+}
+
+static int
+pipe_to_sa (CamelMimeMessage *msg, gchar *in, int argc, gchar **argv)
+{
+ CamelStream *stream;
+ int result, status;
+ int in_fds[2];
+ pid_t pid;
+
+ if (argc < 1 || argv[0] == '\0')
+ return 0;
+
+ if (pipe (in_fds) == -1) {
+ /* camel_exception_setv (fms->ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Failed to create pipe to '%s': %s"),
+ argv[0]->value.string, g_strerror (errno)); */
+ return -1;
+ }
+
+ if (!(pid = fork ())) {
+ /* child process */
+ int maxfd, fd;
+
+ fd = open ("/dev/null", O_WRONLY);
+
+ if (dup2 (in_fds[0], STDIN_FILENO) < 0 ||
+ dup2 (fd, STDOUT_FILENO) < 0 ||
+ dup2 (fd, STDERR_FILENO) < 0)
+ _exit (255);
+
+ setsid ();
+
+ maxfd = sysconf (_SC_OPEN_MAX);
+ if (maxfd > 0) {
+ for (fd = 0; fd < maxfd; fd++) {
+ if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO)
+ close (fd);
+ }
+ }
+
+ execvp (argv [0], argv);
+
+ d(printf ("Could not execute %s: %s\n", argv [0], g_strerror (errno)));
+ _exit (255);
+ } else if (pid < 0) {
+ /* camel_exception_setv (fms->ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Failed to create create child process '%s': %s"),
+ argv[0]->value.string, g_strerror (errno)); */
+ return -1;
+ }
+
+ /* parent process */
+ close (in_fds[0]);
+ fcntl (in_fds[1], F_SETFL, O_NONBLOCK);
+
+ if (msg) {
+ stream = camel_stream_fs_new_with_fd (in_fds[1]);
+
+ camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (msg), stream);
+ camel_stream_flush (stream);
+ camel_object_unref (CAMEL_OBJECT (stream));
+ } else if (in) {
+ write (in_fds [1], in, strlen (in));
+ close (in_fds [1]);
+ }
+
+ result = waitpid (pid, &status, 0);
+
+ if (result == -1 && errno == EINTR) {
+ /* child process is hanging... */
+ kill (pid, SIGTERM);
+ sleep (1);
+ result = waitpid (pid, &status, WNOHANG);
+ if (result == 0) {
+ /* ...still hanging, set phasers to KILL */
+ kill (pid, SIGKILL);
+ sleep (1);
+ result = waitpid (pid, &status, WNOHANG);
+ }
+ }
+
+ if (result != -1 && WIFEXITED (status))
+ return WEXITSTATUS (status);
+ else
+ return -1;
+}
+
+
+#define NPORTS 1
+
+static int
+em_junk_sa_test_spamd_running (gint port)
+{
+ static gchar *sac_args [3] = {
+ "/bin/sh",
+ "-c",
+ NULL
+ };
+ int retval;
+
+ d(fprintf (stderr, "test if spamd is running (port %d)\n", port);)
+ sac_args [2] = port > 0 ? g_strdup_printf ("spamc -x -p %d", port) : g_strdup_printf ("spamc -x");
+
+ retval = pipe_to_sa (NULL, "From test@127.0.0.1", 3, sac_args) == 0;
+ g_free (sac_args [2]);
+
+ return retval;
+}
+
+static void
+em_junk_sa_test_spamd ()
+{
+ gint i, port = 7830;
+
+ em_junk_sa_use_spamc = FALSE;
+
+ /* if (em_junk_sa_test_spamd_running (-1)) {
+ em_junk_sa_use_spamc = TRUE;
+ em_junk_sa_spamd_port = -1;
+ } else { */
+ for (i = 0; i < NPORTS; i ++) {
+ if (em_junk_sa_test_spamd_running (port)) {
+ em_junk_sa_use_spamc = TRUE;
+ em_junk_sa_spamd_port = port;
+ break;
+ }
+ port ++;
+ }
+ /* } */
+
+ if (!em_junk_sa_use_spamc) {
+ static gchar *sad_args [3] = {
+ "/bin/sh",
+ "-c",
+ NULL
+ };
+ gint i, port = 7830;
+
+ d(fprintf (stderr, "looks like spamd is not running\n");)
+
+ for (i = 0; i < NPORTS; i ++) {
+ d(fprintf (stderr, "trying to run spamd at port %d\n", port));
+
+ sad_args [2] = g_strdup_printf ("spamd --port %d --local --daemonize", port);
+ if (!pipe_to_sa (NULL, NULL, 3, sad_args)) {
+ g_free (sad_args [2]);
+ em_junk_sa_use_spamc = TRUE;
+ em_junk_sa_spamd_port = port;
+ d(fprintf (stderr, "success at port %d\n", port));
+ break;
+ }
+ g_free (sad_args [2]);
+ port ++;
+ }
+ }
+
+ d(fprintf (stderr, "use spamd %d at port %d\n", em_junk_sa_use_spamc, em_junk_sa_spamd_port);)
+
+ em_junk_sa_spamd_tested = TRUE;
+}
+
+static gboolean
+em_junk_sa_check_junk (CamelMimeMessage *msg)
+{
+ static gchar *args [3] = {
+ "/bin/sh",
+ "-c",
+ NULL
+ };
+ gint retval;
+
+ d(fprintf (stderr, "em_junk_sa_check_junk\n"));
+
+ LOCK (em_junk_sa_test_lock);
+ if (!em_junk_sa_spamd_tested)
+ em_junk_sa_test_spamd ();
+ UNLOCK (em_junk_sa_test_lock);
+
+ args [2] = em_junk_sa_use_spamc
+ ? (em_junk_sa_spamd_port == -1
+ ? g_strdup ("spamc -c") /* Exit with a non-zero exit code if the
+ tested message was junk */
+ : g_strdup_printf ("spamc"
+ " -c" /* Exit with a non-zero exit code if the
+ tested message was junk */
+ " -p %d", em_junk_sa_spamd_port))
+ : g_strdup ("spamassassin"
+ " --exit-code" /* Exit with a non-zero exit code if the
+ tested message was junk */
+ " --local"); /* Local tests only (no online tests) */
+
+ retval = pipe_to_sa (msg, NULL, 3, args);
+
+ g_free (args [2]);
+
+ return retval;
+}
+
+static void
+em_junk_sa_report_junk (CamelMimeMessage *msg)
+{
+ static gchar *args [3] = {
+ "/bin/sh",
+ "-c",
+ "sa-learn"
+ " --no-rebuild" /* do not rebuild db */
+ " --spam" /* report junk */
+ " --single" /* single message */
+ " --local" /* local only */
+ };
+
+ d(fprintf (stderr, "em_junk_sa_report_junk\n");)
+
+ pipe_to_sa (msg, NULL, 3, args) > 0;
+}
+
+static void
+em_junk_sa_report_notjunk (CamelMimeMessage *msg)
+{
+ static gchar *args [3] = {
+ "/bin/sh",
+ "-c",
+ "sa-learn"
+ " --no-rebuild" /* do not rebuild db */
+ " --ham" /* report notjunk */
+ " --single" /* single message */
+ " --local" /* local only */
+ };
+
+ d(fprintf (stderr, "em_junk_sa_report_notjunk\n");)
+
+ pipe_to_sa (msg, NULL, 3, args) > 0;
+}
+
+static void
+em_junk_sa_commit_reports (void)
+{
+ static gchar *args [3] = {
+ "/bin/sh",
+ "-c",
+ "sa-learn"
+ " --rebuild" /* do not rebuild db */
+ " --local" /* local only */
+ };
+
+ d(fprintf (stderr, "em_junk_sa_commit_reports\n");)
+
+ pipe_to_sa (NULL, NULL, 3, args) > 0;
+}
+
+const EMJunkPlugin *
+em_junk_filter_get_plugin (void)
+{
+ return &spam_assassin_plugin;
+}
diff --git a/mail/em-junk-filter.h b/mail/em-junk-filter.h
new file mode 100644
index 0000000000..f62ca7bfad
--- /dev/null
+++ b/mail/em-junk-filter.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Author:
+ * Radek Doulik <rodo@ximian.com>
+ *
+ * Copyright 2003 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef _EM_JUNK_FILTER_H
+#define _EM_JUNK_FILTER_H
+
+#include "em-junk-plugin.h"
+
+const EMJunkPlugin * em_junk_filter_get_plugin (void);
+
+#endif
diff --git a/mail/em-junk-plugin.c b/mail/em-junk-plugin.c
new file mode 100644
index 0000000000..5ea2a40119
--- /dev/null
+++ b/mail/em-junk-plugin.c
@@ -0,0 +1,24 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Author:
+ * Radek Doulik <rodo@ximian.com>
+ *
+ * Copyright 2003 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include "em-junk-plugin.h"
+
diff --git a/mail/em-junk-plugin.h b/mail/em-junk-plugin.h
new file mode 100644
index 0000000000..0c7eacd165
--- /dev/null
+++ b/mail/em-junk-plugin.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Author:
+ * Radek Doulik <rodo@ximian.com>
+ *
+ * Copyright 2003 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef _EM_JUNK_PLUGIN_H
+#define _EM_JUNK_PLUGIN_H
+
+#include <camel/camel-junk-plugin.h>
+#include <gtk/gtkwidget.h>
+
+#define EM_JUNK_PLUGIN(x) ((EMJunkPlugin *) x)
+
+typedef struct _EMJunkPlugin EMJunkPlugin;
+
+struct _EMJunkPlugin
+{
+ CamelJunkPlugin csp;
+
+ /* when called, it should insert own GUI configuration into supplied.
+ container. returns data pointer which is later passed to apply,
+ plugin has to call (*changed_cb) (); whenever configuration
+ is changed to notify settings dialog about a change.
+ if setup_config_ui is NULL, it means there are no options */
+
+ gpointer (*setup_config_ui) (GtkWidget *container, void (*changed_cb) ());
+ void (*apply) (gpointer data);
+};
+
+#endif
diff --git a/mail/em-popup.c b/mail/em-popup.c
index 63159848bf..e9f7932921 100644
--- a/mail/em-popup.c
+++ b/mail/em-popup.c
@@ -245,7 +245,8 @@ em_popup_create_menu(EMPopup *emp, guint32 hide_mask, guint32 disable_mask)
if (tmp) {
g_string_append_len(ppath, item->path, tmp-item->path);
thismenu = g_hash_table_lookup(menu_hash, ppath->str);
- g_assert(thismenu != NULL);
+ if (thismenu == NULL)
+ continue;
} else {
thismenu = topmenu;
}
@@ -353,8 +354,7 @@ em_popup_create_menu_once(EMPopup *emp, EMPopupTarget *target, guint32 hide_mask
menu = em_popup_create_menu(emp, hide_mask, disable_mask);
- if (target)
- g_signal_connect_swapped(menu, "selection_done", G_CALLBACK(em_popup_target_free), target);
+ g_signal_connect_swapped(menu, "selection_done", G_CALLBACK(em_popup_target_free), target);
g_signal_connect(menu, "selection_done", G_CALLBACK(emp_popup_done), emp);
return menu;
@@ -459,6 +459,11 @@ em_popup_target_new_select(struct _CamelFolder *folder, const char *folder_uri,
mask &= ~EM_POPUP_SELECT_MARK_UNIMPORTANT;
else
mask &= ~EM_POPUP_SELECT_MARK_IMPORTANT;
+
+ if (info->flags & CAMEL_MESSAGE_JUNK)
+ mask &= ~EM_POPUP_SELECT_MARK_NOJUNK;
+ else
+ mask &= ~EM_POPUP_SELECT_MARK_JUNK;
tmp = camel_tag_get (&info->user_tags, "follow-up");
if (tmp && *tmp) {
@@ -601,39 +606,34 @@ emp_part_popup_set_background(GtkWidget *w, EMPopupTarget *t)
}
static void
-emp_part_popup_reply_sender (GtkWidget *w, EMPopupTarget *t)
+emp_part_popup_reply_sender(GtkWidget *w, EMPopupTarget *t)
{
- CamelMimeMessage *message;
-
- message = (CamelMimeMessage *) camel_medium_get_content_object ((CamelMedium *) t->data.part.part);
- em_utils_reply_to_message (message, REPLY_MODE_SENDER);
+ em_utils_reply_to_message(t->widget,
+ (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)t->data.part.part),
+ REPLY_MODE_SENDER);
}
static void
-emp_part_popup_reply_list (GtkWidget *w, EMPopupTarget *t)
+emp_part_popup_reply_list(GtkWidget *w, EMPopupTarget *t)
{
- CamelMimeMessage *message;
-
- message = (CamelMimeMessage *) camel_medium_get_content_object ((CamelMedium *) t->data.part.part);
- em_utils_reply_to_message (message, REPLY_MODE_LIST);
+ em_utils_reply_to_message(t->widget,
+ (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)t->data.part.part),
+ REPLY_MODE_LIST);
}
static void
-emp_part_popup_reply_all (GtkWidget *w, EMPopupTarget *t)
+emp_part_popup_reply_all(GtkWidget *w, EMPopupTarget *t)
{
- CamelMimeMessage *message;
-
- message = (CamelMimeMessage *) camel_medium_get_content_object ((CamelMedium *) t->data.part.part);
- em_utils_reply_to_message (message, REPLY_MODE_ALL);
+ em_utils_reply_to_message(t->widget,
+ (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)t->data.part.part),
+ REPLY_MODE_ALL);
}
static void
-emp_part_popup_forward (GtkWidget *w, EMPopupTarget *t)
+emp_part_popup_forward(GtkWidget *w, EMPopupTarget *t)
{
- CamelMimeMessage *message;
-
- message = (CamelMimeMessage *) camel_medium_get_content_object ((CamelMedium *) t->data.part.part);
- em_utils_forward_message (message);
+ em_utils_forward_message(t->widget,
+ (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)t->data.part.part));
}
static EMPopupItem emp_standard_object_popups[] = {
@@ -665,9 +665,9 @@ emp_uri_popup_link_open(GtkWidget *w, EMPopupTarget *t)
}
static void
-emp_uri_popup_address_send (GtkWidget *w, EMPopupTarget *t)
+emp_uri_popup_address_send(GtkWidget *w, EMPopupTarget *t)
{
- em_utils_compose_new_message_with_mailto (t->data.uri);
+ em_utils_compose_new_message_with_mailto(t->widget, t->data.uri);
}
static void
diff --git a/mail/em-popup.h b/mail/em-popup.h
index 0ad1d0015c..7d19dea6bc 100644
--- a/mail/em-popup.h
+++ b/mail/em-popup.h
@@ -69,7 +69,6 @@ enum _em_popup_target_t {
EM_POPUP_TARGET_SELECT,
EM_POPUP_TARGET_URI,
EM_POPUP_TARGET_PART,
- EM_POPUP_TARGET_FOLDER,
};
/* Flags that describe a TARGET_SELECT */
@@ -88,7 +87,9 @@ enum {
EM_POPUP_SELECT_FLAG_COMPLETED = 1<<12,
EM_POPUP_SELECT_FLAG_CLEAR = 1<<13,
EM_POPUP_SELECT_ADD_SENDER = 1<<14,
- EM_POPUP_SELECT_LAST = 1<<16 /* reserve 2 slots */
+ EM_POPUP_SELECT_MARK_JUNK = 1<<15,
+ EM_POPUP_SELECT_MARK_NOJUNK = 1<<16,
+ EM_POPUP_SELECT_LAST = 1<<18 /* reserve 2 slots */
};
/* Flags that describe a TARGET_URI */
@@ -104,13 +105,6 @@ enum {
EM_POPUP_PART_IMAGE = 1<<1,
};
-/* Flags that describe TARGET_FOLDER */
-enum {
- EM_POPUP_FOLDER_LOCAL = 1<<0,
- EM_POPUP_FOLDER_REMOTE = 1<<1,
- EM_POPUP_FOLDER_VFOLDER = 1<<2,
-};
-
struct _EMPopupTarget {
enum _em_popup_target_t type;
guint32 mask; /* depends on type, see above */
@@ -126,9 +120,6 @@ struct _EMPopupTarget {
char *mime_type;
struct _CamelMimePart *part;
} part;
- struct {
- char *folder_uri;
- } folder;
} data;
};
diff --git a/mail/mail-local.c b/mail/mail-local.c
new file mode 100644
index 0000000000..12c87c2819
--- /dev/null
+++ b/mail/mail-local.c
@@ -0,0 +1,1571 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* mail-local.c: Local mailbox support. */
+
+/*
+ * Authors:
+ * Michael Zucchi <NotZed@ximian.com>
+ * Peter Williams <peterw@ximian.com>
+ * Ettore Perazzoli <ettore@ximian.com>
+ * Dan Winship <danw@ximian.com>
+ *
+ * Copyright 2000 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <libxml/xmlmemory.h>
+#include <glade/glade.h>
+
+#include "e-util/e-path.h"
+#include "e-util/e-dialog-utils.h"
+#include <gal/util/e-xml-utils.h>
+
+#include "Evolution.h"
+#include "evolution-storage.h"
+#include "evolution-shell-component.h"
+#include "evolution-storage-listener.h"
+
+#include "camel/camel.h"
+#include "camel/camel-vtrash-folder.h"
+
+#include "mail.h"
+#include "mail-local.h"
+#include "mail-tools.h"
+#include "mail-mt.h"
+#include "mail-folder-cache.h"
+#include "mail-vfolder.h"
+#include "mail-ops.h"
+
+#define d(x)
+
+/* sigh, required for passing around to some functions */
+static GNOME_Evolution_Storage local_corba_storage = CORBA_OBJECT_NIL;
+
+/* ** MailLocalStore ** (protos) ************************************************** */
+
+#define MAIL_LOCAL_STORE_TYPE (mail_local_store_get_type ())
+#define MAIL_LOCAL_STORE(obj) (CAMEL_CHECK_CAST((obj), MAIL_LOCAL_STORE_TYPE, MailLocalStore))
+#define MAIL_LOCAL_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), MAIL_LOCAL_STORE_TYPE, MailLocalStoreClass))
+#define MAIL_IS_LOCAL_STORE(o) (CAMEL_CHECK_TYPE((o), MAIL_LOCAL_STORE_TYPE))
+
+typedef struct {
+ CamelStore parent_object;
+
+ /* stores CamelFolderInfo's of the folders we're supposed to know about, by uri */
+ GHashTable *folder_infos;
+ GMutex *folder_info_lock;
+
+} MailLocalStore;
+
+typedef struct {
+ CamelStoreClass parent_class;
+} MailLocalStoreClass;
+
+static CamelType mail_local_store_get_type (void);
+
+static MailLocalStore *global_local_store;
+
+/* ** MailLocalFolder ** (protos) ************************************************* */
+
+#define MAIL_LOCAL_FOLDER_TYPE (mail_local_folder_get_type ())
+#define MAIL_LOCAL_FOLDER(obj) (CAMEL_CHECK_CAST((obj), MAIL_LOCAL_FOLDER_TYPE, MailLocalFolder))
+#define MAIL_LOCAL_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), MAIL_LOCAL_FOLDER_TYPE, MailLocalFolderClass))
+#define MAIL_IS_LOCAL_FOLDER(o) (CAMEL_CHECK_TYPE((o), MAIL_LOCAL_FOLDER_TYPE))
+
+#define LOCAL_STORE_LOCK(folder) (g_mutex_lock (((MailLocalStore *)folder)->folder_info_lock))
+#define LOCAL_STORE_UNLOCK(folder) (g_mutex_unlock (((MailLocalStore *)folder)->folder_info_lock))
+
+struct _local_meta {
+ char *path; /* path of metainfo */
+
+ char *format; /* format of mailbox */
+ char *name; /* name of actual mbox */
+ int indexed; /* is body indexed? */
+};
+
+typedef struct {
+ CamelFolder parent_object;
+
+ CamelFolder *real_folder;
+ CamelStore *real_store;
+
+ char *description;
+ char *real_path;
+
+ struct _local_meta *meta;
+
+ GMutex *real_folder_lock; /* no way to use the CamelFolder's lock, so... */
+} MailLocalFolder;
+
+typedef struct {
+ CamelFolderClass parent_class;
+} MailLocalFolderClass;
+
+static CamelType mail_local_folder_get_type (void);
+
+#ifdef ENABLE_THREADS
+#define LOCAL_FOLDER_LOCK(folder) (g_mutex_lock (((MailLocalFolder *)folder)->real_folder_lock))
+#define LOCAL_FOLDER_UNLOCK(folder) (g_mutex_unlock (((MailLocalFolder *)folder)->real_folder_lock))
+#else
+#define LOCAL_FOLDER_LOCK(folder)
+#define LOCAL_FOLDER_UNLOCK(folder)
+#endif
+
+/* ** MailLocalFolder ************************************************************* */
+
+static struct _local_meta *
+load_metainfo(const char *path)
+{
+ xmlDocPtr doc = NULL;
+ xmlNodePtr node;
+ struct _local_meta *meta;
+ struct stat st;
+
+ d(printf("Loading folder metainfo from : %s\n", path));
+
+ meta = g_malloc0(sizeof(*meta));
+ meta->path = g_strdup(path);
+
+ if (stat (path, &st) == -1 || !S_ISREG (st.st_mode))
+ goto dodefault;
+
+ doc = xmlParseFile(path);
+ if (doc == NULL)
+ goto dodefault;
+
+ node = doc->children;
+ if (strcmp(node->name, "folderinfo"))
+ goto dodefault;
+
+ node = node->children;
+ while (node) {
+ if (!strcmp(node->name, "folder")) {
+ char *index, *txt;
+
+ txt = xmlGetProp(node, "type");
+ meta->format = g_strdup(txt?txt:"mbox");
+ xmlFree(txt);
+
+ txt = xmlGetProp(node, "name");
+ meta->name = g_strdup(txt?txt:"mbox");
+ xmlFree(txt);
+
+ index = xmlGetProp(node, "index");
+ if (index) {
+ meta->indexed = atoi(index);
+ xmlFree(index);
+ } else
+ meta->indexed = TRUE;
+
+ }
+ node = node->next;
+ }
+ xmlFreeDoc(doc);
+ return meta;
+
+ dodefault:
+ meta->format = g_strdup("mbox"); /* defaults */
+ meta->name = g_strdup("mbox");
+ meta->indexed = TRUE;
+ xmlFreeDoc(doc);
+ return meta;
+}
+
+static void
+free_metainfo(struct _local_meta *meta)
+{
+ g_free(meta->path);
+ g_free(meta->format);
+ g_free(meta->name);
+ g_free(meta);
+}
+
+static gboolean
+save_metainfo (struct _local_meta *meta)
+{
+ xmlDocPtr doc;
+ xmlNodePtr root, node;
+ int ret;
+
+ d(printf("Saving folder metainfo to : %s\n", meta->path));
+
+ doc = xmlNewDoc("1.0");
+ root = xmlNewDocNode(doc, NULL, "folderinfo", NULL);
+ xmlDocSetRootElement(doc, root);
+
+ node = xmlNewChild(root, NULL, "folder", NULL);
+ xmlSetProp(node, "type", meta->format);
+ xmlSetProp(node, "name", meta->name);
+ xmlSetProp(node, "index", meta->indexed?"1":"0");
+
+ ret = e_xml_save_file (meta->path, doc);
+
+ xmlFreeDoc (doc);
+
+ return ret == -1 ? FALSE : TRUE;
+}
+
+static CamelFolderClass *mlf_parent_class = NULL;
+
+/* forward a bunch of functions to the real folder. This pretty
+ * much sucks but I haven't found a better way of doing it.
+ */
+
+/* We need to do it without having locked our folder, otherwise
+ we can get sync hangs with vfolders/trash */
+static void
+mlf_refresh_info(CamelFolder *folder, CamelException *ex)
+{
+ MailLocalFolder *mlf = MAIL_LOCAL_FOLDER(folder);
+ CamelFolder *f;
+
+ LOCAL_FOLDER_LOCK(mlf);
+ f = mlf->real_folder;
+ camel_object_ref(f);
+ LOCAL_FOLDER_UNLOCK(mlf);
+
+ camel_folder_refresh_info(f, ex);
+ camel_object_unref(f);
+}
+
+static void
+mlf_sync(CamelFolder *folder, gboolean expunge, CamelException *ex)
+{
+ MailLocalFolder *mlf = MAIL_LOCAL_FOLDER(folder);
+ CamelFolder *f;
+
+ LOCAL_FOLDER_LOCK(mlf);
+ f = mlf->real_folder;
+ camel_object_ref(f);
+ LOCAL_FOLDER_UNLOCK(mlf);
+
+ camel_folder_sync(f, expunge, ex);
+ camel_object_unref(f);
+}
+
+static void
+mlf_expunge(CamelFolder *folder, CamelException *ex)
+{
+ MailLocalFolder *mlf = MAIL_LOCAL_FOLDER(folder);
+ CamelFolder *f;
+
+ LOCAL_FOLDER_LOCK(mlf);
+ f = mlf->real_folder;
+ camel_object_ref(f);
+ LOCAL_FOLDER_UNLOCK(mlf);
+
+ camel_folder_expunge(f, ex);
+ camel_object_unref(f);
+}
+
+static void
+mlf_append_message(CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, char **appended_uid, CamelException *ex)
+{
+ MailLocalFolder *mlf = MAIL_LOCAL_FOLDER(folder);
+ CamelFolder *f;
+
+ LOCAL_FOLDER_LOCK(mlf);
+ f = mlf->real_folder;
+ camel_object_ref(f);
+ LOCAL_FOLDER_UNLOCK(mlf);
+
+ camel_folder_append_message(f, message, info, appended_uid, ex);
+ camel_object_unref(f);
+}
+
+static CamelMimeMessage *
+mlf_get_message(CamelFolder *folder, const char *uid, CamelException *ex)
+{
+ MailLocalFolder *mlf = MAIL_LOCAL_FOLDER(folder);
+ CamelMimeMessage *ret;
+ CamelFolder *f;
+
+ LOCAL_FOLDER_LOCK(mlf);
+ f = mlf->real_folder;
+ camel_object_ref(f);
+ LOCAL_FOLDER_UNLOCK(mlf);
+
+ ret = camel_folder_get_message(f, uid, ex);
+ camel_object_unref(f);
+
+ return ret;
+}
+
+static GPtrArray *
+mlf_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex)
+{
+ MailLocalFolder *mlf = MAIL_LOCAL_FOLDER (folder);
+ GPtrArray *ret;
+ CamelFolder *f;
+
+ LOCAL_FOLDER_LOCK(mlf);
+ f = mlf->real_folder;
+ camel_object_ref(f);
+ LOCAL_FOLDER_UNLOCK(mlf);
+
+ ret = camel_folder_search_by_expression(f, expression, ex);
+ camel_object_unref(f);
+
+ return ret;
+}
+
+static GPtrArray *
+mlf_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex)
+{
+ MailLocalFolder *mlf = MAIL_LOCAL_FOLDER (folder);
+ GPtrArray *ret;
+ CamelFolder *f;
+
+ LOCAL_FOLDER_LOCK(mlf);
+ f = mlf->real_folder;
+ camel_object_ref(f);
+ LOCAL_FOLDER_UNLOCK(mlf);
+
+ ret = camel_folder_search_by_uids(f, expression, uids, ex);
+ camel_object_unref(f);
+
+ return ret;
+}
+
+static void
+mlf_search_free(CamelFolder *folder, GPtrArray *result)
+{
+ MailLocalFolder *mlf = MAIL_LOCAL_FOLDER(folder);
+ CamelFolder *f;
+
+ LOCAL_FOLDER_LOCK(mlf);
+ f = mlf->real_folder;
+ camel_object_ref(f);
+ LOCAL_FOLDER_UNLOCK(mlf);
+
+ camel_folder_search_free(f, result);
+ camel_object_unref(f);
+}
+
+static void
+mlf_set_message_flags(CamelFolder *folder, const char *uid, guint32 flags, guint32 set)
+{
+ MailLocalFolder *mlf = MAIL_LOCAL_FOLDER(folder);
+ CamelFolder *f;
+
+ LOCAL_FOLDER_LOCK(mlf);
+ f = mlf->real_folder;
+ camel_object_ref(f);
+ LOCAL_FOLDER_UNLOCK(mlf);
+
+ camel_folder_set_message_flags(mlf->real_folder, uid, flags, set);
+ camel_object_unref(f);
+}
+
+static void
+mlf_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value)
+{
+ MailLocalFolder *mlf = MAIL_LOCAL_FOLDER(folder);
+ CamelFolder *f;
+
+ LOCAL_FOLDER_LOCK(mlf);
+ f = mlf->real_folder;
+ camel_object_ref(f);
+ LOCAL_FOLDER_UNLOCK(mlf);
+
+ camel_folder_set_message_user_flag(mlf->real_folder, uid, name, value);
+ camel_object_unref(f);
+}
+
+static void
+mlf_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value)
+{
+ MailLocalFolder *mlf = MAIL_LOCAL_FOLDER(folder);
+ CamelFolder *f;
+
+ LOCAL_FOLDER_LOCK(mlf);
+ f = mlf->real_folder;
+ camel_object_ref(f);
+ LOCAL_FOLDER_UNLOCK(mlf);
+
+ camel_folder_set_message_user_tag(mlf->real_folder, uid, name, value);
+ camel_object_unref(f);
+}
+
+/* Internal store-rename call, update our strings */
+static void
+mlf_rename(CamelFolder *folder, const char *new)
+{
+ MailLocalFolder *mlf = (MailLocalFolder *)folder;
+
+ /* first, proxy it down */
+ if (mlf->real_folder) {
+ char *mbox = g_strdup_printf("%s/%s", new, mlf->meta->name);
+
+ d(printf("renaming real folder to %s\n", mbox));
+
+ camel_folder_rename(mlf->real_folder, mbox);
+ g_free(mbox);
+ }
+
+ /* Then do our stuff */
+ g_free(mlf->real_path);
+ mlf->real_path = g_strdup(new);
+
+ g_free(mlf->meta->path);
+ mlf->meta->path = g_strdup_printf("%s/%s/local-metadata.xml", ((CamelService *)folder->parent_store)->url->path, new);
+
+ /* Then pass it up */
+ ((CamelFolderClass *)mlf_parent_class)->rename(folder, new);
+}
+
+/* and, conversely, forward the real folder's signals. */
+
+static void
+mlf_proxy_message_changed(CamelObject *real_folder, gpointer event_data, gpointer user_data)
+{
+ camel_object_trigger_event(user_data, "message_changed", event_data);
+}
+
+static void
+mlf_proxy_folder_changed(CamelObject *real_folder, gpointer event_data, gpointer user_data)
+{
+ camel_object_trigger_event(user_data, "folder_changed", event_data);
+}
+
+static void
+mlf_unset_folder (MailLocalFolder *mlf)
+{
+ CamelFolder *folder = (CamelFolder *)mlf;
+
+ g_assert(mlf->real_folder);
+
+ camel_object_unhook_event(mlf->real_folder,
+ "message_changed",
+ mlf_proxy_message_changed,
+ mlf);
+ camel_object_unhook_event(mlf->real_folder,
+ "folder_changed",
+ mlf_proxy_folder_changed,
+ mlf);
+
+ camel_object_unref(folder->summary);
+ folder->summary = NULL;
+ camel_object_unref(mlf->real_folder);
+ mlf->real_folder = NULL;
+ camel_object_unref(mlf->real_store);
+ mlf->real_store = NULL;
+
+ folder->permanent_flags = 0;
+ folder->folder_flags = 0;
+}
+
+static gboolean
+mlf_set_folder(MailLocalFolder *mlf, guint32 flags, CamelException *ex)
+{
+ CamelFolder *folder = (CamelFolder *)mlf;
+ char *uri, *mbox;
+
+ g_assert(mlf->real_folder == NULL);
+
+ uri = g_strdup_printf("%s:%s", mlf->meta->format, ((CamelService *)folder->parent_store)->url->path);
+
+ d(printf("opening real store: %s\n", uri));
+ mlf->real_store = camel_session_get_store(session, uri, ex);
+ g_free(uri);
+ if (mlf->real_store == NULL)
+ return FALSE;
+
+ if (mlf->meta->indexed)
+ flags |= CAMEL_STORE_FOLDER_BODY_INDEX;
+
+ /* mlf->real_folder = camel_store_get_folder(mlf->real_store, mlf->meta->name, flags, ex); */
+ mbox = g_strdup_printf("%s/%s", mlf->real_path, mlf->meta->name);
+ d(printf("Opening mbox on real path: %s\n", mbox));
+ mlf->real_folder = camel_store_get_folder(mlf->real_store, mbox, flags, ex);
+ g_free(mbox);
+ if (mlf->real_folder == NULL)
+ return FALSE;
+
+ if (mlf->real_folder->folder_flags & CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY) {
+ folder->summary = mlf->real_folder->summary;
+ camel_object_ref(mlf->real_folder->summary);
+ }
+
+ folder->permanent_flags = mlf->real_folder->permanent_flags;
+ folder->folder_flags = mlf->real_folder->folder_flags;
+
+ camel_object_hook_event(mlf->real_folder, "message_changed", mlf_proxy_message_changed, mlf);
+ camel_object_hook_event(mlf->real_folder, "folder_changed", mlf_proxy_folder_changed, mlf);
+
+ return TRUE;
+}
+
+static int
+mlf_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args)
+{
+ CamelFolder *folder = (CamelFolder *)object;
+ MailLocalFolder *mlf = (MailLocalFolder *)object;
+ int i, count=args->argc;
+ guint32 tag;
+
+ for (i=0;i<args->argc;i++) {
+ CamelArgGet *arg = &args->argv[i];
+
+ tag = arg->tag;
+
+ switch (tag & CAMEL_ARG_TAG) {
+ /* CamelObject args */
+ case CAMEL_OBJECT_ARG_DESCRIPTION:
+ if (mlf->description == NULL) {
+ int pathlen;
+
+ /* string to describe a local folder as the location of a message */
+ pathlen = strlen(evolution_dir) + strlen("local") + 1;
+ if (strlen(folder->full_name) > pathlen)
+ mlf->description = g_strdup_printf(_("Local folders/%s"), folder->full_name+pathlen);
+ else
+ mlf->description = g_strdup_printf(_("Local folders/%s"), folder->name);
+ }
+ *arg->ca_str = mlf->description;
+ break;
+ default:
+ count--;
+ continue;
+ }
+
+ arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE;
+ }
+
+ if (count)
+ return ((CamelObjectClass *)mlf_parent_class)->getv(object, ex, args);
+
+ return 0;
+}
+
+static gboolean
+mlf_meta_set(CamelObject *obj, const char *name, const char *value)
+{
+ MailLocalFolder *mlf = MAIL_LOCAL_FOLDER(obj);
+ CamelFolder *f;
+ gboolean res;
+
+ LOCAL_FOLDER_LOCK(mlf);
+ f = mlf->real_folder;
+ camel_object_ref(f);
+ LOCAL_FOLDER_UNLOCK(mlf);
+
+ /* We must write this ourselves, since MailLocalFolder is not persistent itself */
+ if ((res = camel_object_meta_set(f, name, value)))
+ camel_object_state_write(f);
+ camel_object_unref(f);
+
+ return res;
+}
+
+static char *
+mlf_meta_get(CamelObject *obj, const char *name)
+{
+ MailLocalFolder *mlf = MAIL_LOCAL_FOLDER(obj);
+ CamelFolder *f;
+ char * res;
+
+ LOCAL_FOLDER_LOCK(mlf);
+ f = mlf->real_folder;
+ camel_object_ref(f);
+ LOCAL_FOLDER_UNLOCK(mlf);
+
+ res = camel_object_meta_get(f, name);
+ camel_object_unref(f);
+
+ return res;
+}
+
+static void
+mlf_class_init (CamelObjectClass *camel_object_class)
+{
+ CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_object_class);
+
+ /* override all the functions subclassed in providers/local/ */
+ camel_folder_class->refresh_info = mlf_refresh_info;
+ camel_folder_class->sync = mlf_sync;
+ camel_folder_class->expunge = mlf_expunge;
+ camel_folder_class->append_message = mlf_append_message;
+ camel_folder_class->get_message = mlf_get_message;
+ camel_folder_class->search_free = mlf_search_free;
+
+ camel_folder_class->search_by_expression = mlf_search_by_expression;
+ camel_folder_class->search_by_uids = mlf_search_by_uids;
+ camel_folder_class->set_message_flags = mlf_set_message_flags;
+ camel_folder_class->set_message_user_flag = mlf_set_message_user_flag;
+ camel_folder_class->set_message_user_tag = mlf_set_message_user_tag;
+
+ camel_folder_class->rename = mlf_rename;
+
+ camel_object_class->getv = mlf_getv;
+
+ camel_object_class->meta_get = mlf_meta_get;
+ camel_object_class->meta_set = mlf_meta_set;
+}
+
+static void
+mlf_init (CamelObject *obj, CamelObjectClass *klass)
+{
+ MailLocalFolder *mlf = MAIL_LOCAL_FOLDER (obj);
+
+#ifdef ENABLE_THREADS
+ mlf->real_folder_lock = g_mutex_new();
+#endif
+}
+
+static void
+mlf_finalize (CamelObject *obj)
+{
+ MailLocalFolder *mlf = MAIL_LOCAL_FOLDER (obj);
+
+ if (mlf->real_folder)
+ mlf_unset_folder(mlf);
+
+ free_metainfo(mlf->meta);
+
+ g_free (mlf->real_path);
+
+#ifdef ENABLE_THREADS
+ g_mutex_free (mlf->real_folder_lock);
+#endif
+}
+
+static CamelType
+mail_local_folder_get_type (void)
+{
+ static CamelType mail_local_folder_type = CAMEL_INVALID_TYPE;
+
+ if (mail_local_folder_type == CAMEL_INVALID_TYPE) {
+ mail_local_folder_type = camel_type_register(CAMEL_FOLDER_TYPE,
+ "MailLocalFolder",
+ sizeof (MailLocalFolder),
+ sizeof (MailLocalFolderClass),
+ mlf_class_init,
+ NULL,
+ mlf_init,
+ mlf_finalize);
+ mlf_parent_class = (CamelFolderClass *)CAMEL_FOLDER_TYPE;
+ }
+
+ return mail_local_folder_type;
+}
+
+static MailLocalFolder *
+mail_local_folder_construct(MailLocalFolder *mlf, MailLocalStore *parent_store, const char *full_name, CamelException *ex)
+{
+ char *metapath, *name;
+
+ name = g_path_get_basename (full_name);
+ d(printf ("constructing local folder: full = %s, name = %s\n", full_name, name));
+ camel_folder_construct (CAMEL_FOLDER (mlf), CAMEL_STORE (parent_store), full_name, name);
+ g_free (name);
+
+ mlf->real_path = g_strdup (((CamelFolder *) mlf)->full_name);
+
+ metapath = g_strdup_printf ("%s/%s/local-metadata.xml", ((CamelService *) parent_store)->url->path, full_name);
+ mlf->meta = load_metainfo (metapath);
+ g_free (metapath);
+
+ return mlf;
+}
+
+static gboolean
+mail_local_folder_reconfigure (MailLocalFolder *mlf, const char *new_format, int index_body, CamelException *ex)
+{
+ CamelStore *fromstore = NULL;
+ CamelFolder *fromfolder = NULL;
+ char *oldformat = NULL;
+ char *store_uri;
+ GPtrArray *uids;
+ int real_folder_frozen = FALSE;
+ int format_change, index_changed;
+ char *tmpname = NULL;
+ char *mbox = NULL;
+
+ format_change = strcmp(mlf->meta->format, new_format) != 0;
+ index_changed = mlf->meta->indexed != index_body;
+
+ if (format_change == FALSE && index_changed == FALSE)
+ return TRUE;
+
+ camel_operation_start(NULL, _("Reconfiguring folder"));
+
+ /* first things first */
+ g_assert (ex);
+ LOCAL_FOLDER_LOCK (mlf);
+
+ /* first, 'close' the old folder */
+ if (mlf->real_folder) {
+ camel_folder_sync(mlf->real_folder, FALSE, ex);
+ if (camel_exception_is_set (ex))
+ goto cleanup;
+ mlf_unset_folder(mlf);
+ }
+
+ /* only indexed change, just re-open with new flags */
+ if (!format_change) {
+ mlf->meta->indexed = index_body;
+ mlf_set_folder(mlf, CAMEL_STORE_FOLDER_CREATE, ex);
+ save_metainfo(mlf->meta);
+ goto cleanup;
+ }
+
+ store_uri = g_strdup_printf("%s:%s", mlf->meta->format, ((CamelService *)((CamelFolder *)mlf)->parent_store)->url->path);
+ fromstore = camel_session_get_store(session, store_uri, ex);
+ g_free(store_uri);
+ if (fromstore == NULL)
+ goto cleanup;
+
+ oldformat = mlf->meta->format;
+ mlf->meta->format = g_strdup(new_format);
+
+ /* rename the old mbox and open it again, without indexing */
+ tmpname = g_strdup_printf ("%s/%s_reconfig", mlf->real_path, mlf->meta->name);
+ mbox = g_strdup_printf("%s/%s", mlf->real_path, mlf->meta->name);
+ d(printf("renaming %s to %s, and opening it\n", mbox, tmpname));
+
+ camel_store_rename_folder(fromstore, mbox, tmpname, ex);
+ if (camel_exception_is_set(ex))
+ goto cleanup;
+
+ /* we dont need to set the create flag ... or need an index if it has one */
+ fromfolder = camel_store_get_folder(fromstore, tmpname, 0, ex);
+ if (fromfolder == NULL || camel_exception_is_set(ex)) {
+ /* try and recover ... */
+ camel_exception_clear(ex);
+ camel_store_rename_folder(fromstore, tmpname, mbox, ex);
+ goto cleanup;
+ }
+
+ /* create a new mbox */
+ d(printf("Creating the destination mbox\n"));
+
+ if (!mlf_set_folder(mlf, CAMEL_STORE_FOLDER_CREATE, ex)) {
+ d(printf("cannot open destination folder\n"));
+ /* try and recover ... */
+ camel_exception_clear(ex);
+ camel_store_rename_folder(fromstore, tmpname, mbox, ex);
+ goto cleanup;
+ }
+
+ real_folder_frozen = TRUE;
+ camel_folder_freeze(mlf->real_folder);
+
+ uids = camel_folder_get_uids(fromfolder);
+ camel_folder_transfer_messages_to(fromfolder, uids, mlf->real_folder, NULL, TRUE, ex);
+ camel_folder_free_uids(fromfolder, uids);
+ if (camel_exception_is_set(ex))
+ goto cleanup;
+
+ camel_folder_expunge(fromfolder, ex);
+
+ d(printf("delete old mbox ...\n"));
+ camel_object_unref(fromfolder);
+ fromfolder = NULL;
+ camel_store_delete_folder(fromstore, tmpname, ex);
+
+ /* switch format */
+ g_free(oldformat);
+ oldformat = NULL;
+ if (save_metainfo(mlf->meta) == FALSE) {
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Cannot save folder metainfo; "
+ "you may find you can't\n"
+ "open this folder anymore: %s: %s"),
+ mlf->meta->path, strerror(errno));
+ }
+
+ cleanup:
+ if (oldformat) {
+ g_free(mlf->meta->format);
+ mlf->meta->format = oldformat;
+ }
+ if (mlf->real_folder == NULL)
+ mlf_set_folder (mlf, CAMEL_STORE_FOLDER_CREATE, ex);
+ if (fromfolder)
+ camel_object_unref(fromfolder);
+ if (fromstore)
+ camel_object_unref(fromstore);
+
+ g_free(tmpname);
+ g_free(mbox);
+
+ LOCAL_FOLDER_UNLOCK (mlf);
+
+ if (real_folder_frozen)
+ camel_folder_thaw(mlf->real_folder);
+
+ camel_operation_end(NULL);
+
+ return !camel_exception_is_set(ex);
+}
+
+/* ******************************************************************************** */
+
+static CamelObjectClass *local_store_parent_class = NULL;
+
+static CamelFolder *
+mls_get_folder(CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex)
+{
+ MailLocalStore *local_store = MAIL_LOCAL_STORE (store);
+ MailLocalFolder *folder;
+
+ d(printf("--LOCAL-- get_folder: %s\n", folder_name));
+
+ folder = (MailLocalFolder *)camel_object_new(MAIL_LOCAL_FOLDER_TYPE);
+ folder = mail_local_folder_construct(folder, local_store, folder_name, ex);
+ if (folder == NULL)
+ return NULL;
+
+ if (!mlf_set_folder(folder, flags, ex)) {
+ camel_object_unref(folder);
+ return NULL;
+ }
+
+ if (flags & CAMEL_STORE_FOLDER_CREATE) {
+ if (save_metainfo(folder->meta) == FALSE) {
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Cannot save folder metainfo to %s: %s"),
+ folder->meta->path, g_strerror(errno));
+ camel_object_unref(folder);
+ return NULL;
+ }
+ }
+
+ return (CamelFolder *)folder;
+}
+
+static void
+mls_delete_folder(CamelStore *store, const char *folder_name, CamelException *ex)
+{
+ CamelStore *real_store;
+ char *metapath, *uri, *mbox;
+ CamelException local_ex;
+ struct _local_meta *meta;
+
+ d(printf("Deleting folder: %s %s\n", ((CamelService *)store)->url->path, folder_name));
+
+ camel_exception_init(&local_ex);
+
+ /* find the real store for this folder, and proxy the call */
+ metapath = g_strdup_printf("%s%s/local-metadata.xml", ((CamelService *)store)->url->path, folder_name);
+ meta = load_metainfo(metapath);
+ uri = g_strdup_printf("%s:%s", meta->format, ((CamelService *)store)->url->path);
+ real_store = (CamelStore *)camel_session_get_service(session, uri, CAMEL_PROVIDER_STORE, ex);
+ g_free(uri);
+ if (real_store == NULL) {
+ g_free(metapath);
+ free_metainfo(meta);
+ camel_object_unref(real_store);
+ return;
+ }
+
+ mbox = g_strdup_printf("%s/%s", folder_name, meta->name);
+ camel_store_delete_folder(real_store, mbox, &local_ex);
+ g_free(mbox);
+ if (camel_exception_is_set(&local_ex)) {
+ camel_exception_xfer(ex, &local_ex);
+ g_free(metapath);
+ free_metainfo(meta);
+ camel_object_unref(real_store);
+ return;
+ }
+
+ camel_object_unref((CamelObject *)real_store);
+
+ free_metainfo(meta);
+
+ if (unlink(metapath) == -1) {
+ camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Cannot delete folder metadata %s: %s"),
+ metapath, g_strerror(errno));
+ }
+
+ g_free(metapath);
+}
+
+static void
+mls_rename_folder(CamelStore *store, const char *old_name, const char *new_name, CamelException *ex)
+{
+ CamelStore *real_store;
+ /*MailLocalStore *mls = (MailLocalStore *)store;*/
+ char *uri;
+ /*CamelException local_ex;*/
+ struct _local_meta *meta;
+ char *oldname, *newname;
+ char *oldmeta, *newmeta;
+ struct stat st;
+
+ /* folder:rename() updates all our in-memory data to match */
+
+ /* FIXME: Need to lock the subfolder that matches this if its open
+ Then rename it and unlock it when done */
+
+ d(printf("Renaming folder from '%s' to '%s'\n", old_name, new_name));
+
+ oldmeta = g_strdup_printf("%s%s/local-metadata.xml", ((CamelService *)store)->url->path, old_name);
+ newmeta = g_strdup_printf("%s%s/local-metadata.xml", ((CamelService *)store)->url->path, new_name);
+
+ meta = load_metainfo(oldmeta);
+ uri = g_strdup_printf("%s:%s", meta->format, ((CamelService *)store)->url->path);
+ real_store = (CamelStore *)camel_session_get_service(session, uri, CAMEL_PROVIDER_STORE, ex);
+ g_free(uri);
+ if (real_store == NULL) {
+ g_free(newmeta);
+ g_free(oldmeta);
+ free_metainfo(meta);
+ return;
+ }
+
+ oldname = g_strdup_printf("%s/%s", old_name, meta->name);
+ newname = g_strdup_printf("%s/%s", new_name, meta->name);
+
+ camel_store_rename_folder(real_store, oldname, newname, ex);
+ if (!camel_exception_is_set(ex)) {
+ /* If this fails? Well, doesn't really matter but 'fail' anyway */
+ if (stat(oldmeta, &st) == 0
+ && rename(oldmeta, newmeta) == -1) {
+ camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Could not rename folder %s to %s: %s"),
+ old_name, new_name, strerror(errno));
+ } else {
+ /* So .. .the shell does a remove/add now the rename worked, so we dont
+ have to do this. However totally broken that idea might be */
+#if 0
+ CamelFolderInfo *info;
+ const char *tmp;
+ char *olduri, *newuri;
+
+ olduri = g_strdup_printf("%s:%s%s", ((CamelService *)store)->url->protocol, ((CamelService *)store)->url->path, old_name);
+ newuri = g_strdup_printf("%s:%s%s", ((CamelService *)store)->url->protocol, ((CamelService *)store)->url->path, new_name);
+ info = g_hash_table_lookup(mls->folder_infos, olduri);
+ if (info) {
+ CamelRenameInfo reninfo;
+
+ g_free(info->url);
+ g_free(info->full_name);
+ g_free(info->name);
+ g_free(info->path);
+ info->url = newuri;
+ info->full_name = g_strdup(new_name);
+ info->path = g_strdup_printf("/%s", new_name);
+ tmp = strchr(new_name, '/');
+ if (tmp == NULL)
+ tmp = new_name;
+ info->name = g_strdup(tmp);
+ g_hash_table_insert(mls->folder_infos, info->url, info);
+
+ reninfo.new = info;
+ reninfo.old_base = (char *)old_name;
+
+ camel_object_trigger_event(store, "folder_renamed", &reninfo);
+ } else {
+ g_free(newuri);
+ g_warning("Cannot find existing folder '%s' in table?\n", olduri);
+ }
+
+ g_free(olduri);
+#endif
+ }
+ }
+
+ g_free(newname);
+ g_free(oldname);
+
+ camel_object_unref(real_store);
+
+ free_metainfo(meta);
+
+ g_free(newmeta);
+ g_free(oldmeta);
+}
+
+static char *
+mls_get_name (CamelService *service, gboolean brief)
+{
+ if (brief)
+ return g_strdup("local");
+
+ return g_strdup("Local mail folders");
+}
+
+static void
+mls_init (MailLocalStore *mls, MailLocalStoreClass *mlsclass)
+{
+ mls->folder_infos = g_hash_table_new(g_str_hash, g_str_equal);
+ mls->folder_info_lock = g_mutex_new();
+}
+
+static void
+free_info(void *key, void *value, void *data)
+{
+ CamelFolderInfo *info = value;
+
+ camel_folder_info_free (info);
+}
+
+static void
+mls_finalise(MailLocalStore *mls)
+{
+ g_hash_table_foreach(mls->folder_infos, (GHFunc)free_info, NULL);
+ g_hash_table_destroy(mls->folder_infos);
+ g_mutex_free(mls->folder_info_lock);
+}
+
+static void
+mls_class_init (CamelObjectClass *camel_object_class)
+{
+ CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS(camel_object_class);
+ CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS(camel_object_class);
+
+ /* virtual method overload -- the bare minimum */
+ camel_service_class->get_name = mls_get_name;
+ camel_store_class->get_folder = mls_get_folder;
+ camel_store_class->delete_folder = mls_delete_folder;
+ camel_store_class->rename_folder = mls_rename_folder;
+
+ local_store_parent_class = camel_type_get_global_classfuncs (CAMEL_STORE_TYPE);
+}
+
+static CamelType
+mail_local_store_get_type (void)
+{
+ static CamelType mail_local_store_type = CAMEL_INVALID_TYPE;
+
+ if (mail_local_store_type == CAMEL_INVALID_TYPE) {
+ mail_local_store_type = camel_type_register (
+ CAMEL_STORE_TYPE, "MailLocalStore",
+ sizeof (MailLocalStore),
+ sizeof (MailLocalStoreClass),
+ (CamelObjectClassInitFunc) mls_class_init,
+ NULL,
+ (CamelObjectInitFunc) mls_init,
+ (CamelObjectFinalizeFunc) mls_finalise);
+ }
+
+ return mail_local_store_type;
+}
+
+static void mail_local_store_add_folder(MailLocalStore *mls, const char *uri, const char *path, const char *name)
+{
+ CamelFolderInfo *info = NULL;
+ CamelURL *url;
+
+ d(printf("Shell adding folder: '%s' path = '%s'\n", uri, path));
+
+ url = camel_url_new(uri, NULL);
+ if (url == NULL) {
+ g_warning("Shell trying to add invalid folder url: %s", uri);
+ return;
+ }
+ if (url->path == NULL || url->path[0] == 0) {
+ g_warning("Shell trying to add invalid folder url: %s", uri);
+ camel_url_free(url);
+ return;
+ }
+
+ LOCAL_STORE_LOCK(mls);
+
+ if (g_hash_table_lookup(mls->folder_infos, uri)) {
+ g_warning("Shell trying to add a folder I already have!");
+ } else {
+ info = g_malloc0(sizeof(*info));
+ info->url = g_strdup(uri);
+ info->full_name = g_strdup(url->path+1);
+ info->name = g_strdup(name);
+ info->unread_message_count = -1;
+ info->path = g_strdup (path);
+ g_hash_table_insert(mls->folder_infos, info->url, info);
+ }
+
+ LOCAL_STORE_UNLOCK(mls);
+
+ camel_url_free(url);
+
+ if (info) {
+ /* FIXME: should copy info, so we dont get a removed while we're using it? */
+ camel_object_trigger_event(mls, "folder_created", info);
+
+ /* this is just so the folder is opened at least once to setup the folder
+ counts etc in the display. Joy eh? The result is discarded. */
+ mail_get_folder (uri, CAMEL_STORE_FOLDER_CREATE, NULL, NULL, mail_thread_queued_slow);
+ }
+}
+
+struct _search_info {
+ const char *path;
+ CamelFolderInfo *info;
+};
+
+static void
+remove_find_path(char *uri, CamelFolderInfo *info, struct _search_info *data)
+{
+ if (!strcmp(info->path, data->path))
+ data->info = info;
+}
+
+static void mail_local_store_remove_folder(MailLocalStore *mls, const char *path)
+{
+ struct _search_info data = { path, NULL };
+
+ d(printf("shell removing folder? '%s'\n", path));
+
+ /* we're keyed on uri, not path, so have to search for it manually */
+
+ LOCAL_STORE_LOCK(mls);
+ g_hash_table_foreach(mls->folder_infos, (GHFunc)remove_find_path, &data);
+ if (data.info)
+ g_hash_table_remove(mls->folder_infos, data.info->url);
+ LOCAL_STORE_UNLOCK(mls);
+
+ if (data.info) {
+ camel_object_trigger_event(mls, "folder_deleted", data.info);
+
+ g_free(data.info->url);
+ g_free(data.info->full_name);
+ g_free(data.info->name);
+ g_free(data.info);
+ }
+}
+
+/* ** Local Provider ************************************************************** */
+
+static CamelProvider local_provider = {
+ "file", "Local mail", "Local mailbox file", "mail",
+ CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_IS_EXTERNAL,
+ CAMEL_URL_NEED_PATH,
+ /* ... */
+};
+
+/* There's only one "file:" store. */
+static guint
+non_hash (gconstpointer key)
+{
+ return 0;
+}
+
+static gint
+non_equal (gconstpointer ap, gconstpointer bp)
+{
+ const CamelURL *a = ap, *b = bp;
+
+ return strcmp(a->protocol, "file") == 0
+ && strcmp(a->protocol, b->protocol) == 0;
+}
+
+static void
+mail_local_provider_init (void)
+{
+ /* Register with Camel to handle file: URLs */
+ local_provider.object_types[CAMEL_PROVIDER_STORE] = MAIL_LOCAL_STORE_TYPE;
+
+ local_provider.url_hash = non_hash;
+ local_provider.url_equal = non_equal;
+ camel_session_register_provider (session, &local_provider);
+}
+
+/* ** Local Storage Listener ****************************************************** */
+
+static void
+local_storage_new_folder_cb_trash_or_junk (const GNOME_Evolution_Folder *folder, const gchar *path, gchar *full_name, gchar *url_base)
+{
+ CamelFolderInfo info;
+ CamelURL *url;
+
+ url = camel_url_new(folder->physicalUri, NULL);
+ if (url == NULL) {
+ g_warning("Shell trying to add invalid folder url: %s", folder->physicalUri);
+ return;
+ }
+ if (url->path == NULL || url->path[0] == 0) {
+ g_warning("Shell trying to add invalid folder url: %s", folder->physicalUri);
+ camel_url_free(url);
+ return;
+ }
+
+ memset(&info, 0, sizeof(info));
+ info.full_name = full_name;
+ info.name = folder->displayName;
+ info.url = g_strdup_printf("%s:%s", url_base, folder->physicalUri);
+ info.unread_message_count = 0;
+ info.path = (char *)path;
+
+ camel_object_trigger_event(global_local_store, "folder_created", &info);
+ g_free(info.url);
+ camel_url_free(url);
+}
+
+static void
+local_storage_new_folder_cb (EvolutionStorageListener *storage_listener,
+ const char *path,
+ const GNOME_Evolution_Folder *folder,
+ void *data)
+{
+ d(printf("Local folder new:\n"));
+ d(printf(" path = '%s'\n uri = '%s'\n display = '%s'\n",
+ path, folder->physicalUri, folder->displayName));
+
+ /* We dont actually add the trash/junk to our local folders list, get_trash is handled
+ outside our internal folder list */
+
+ if (strcmp(folder->type, "mail") == 0) {
+ mail_local_store_add_folder(global_local_store, folder->physicalUri, path, folder->displayName);
+ } else if (strcmp(folder->type, "vtrash") == 0)
+ local_storage_new_folder_cb_trash_or_junk (folder, path, CAMEL_VTRASH_NAME, "vtrash");
+ else if (strcmp(folder->type, "vjunk") == 0)
+ local_storage_new_folder_cb_trash_or_junk (folder, path, CAMEL_VJUNK_NAME, "vjunk");
+
+}
+
+
+static void
+local_storage_removed_folder_cb (EvolutionStorageListener *storage_listener,
+ const char *path,
+ void *data)
+{
+ d(printf("Local folder remove:\n"));
+ d(printf(" path = '%s'\n", path));
+
+ mail_local_store_remove_folder(global_local_store, path);
+}
+
+static void
+storage_listener_startup (EvolutionShellClient *shellclient)
+{
+ EvolutionStorageListener *local_storage_listener;
+ GNOME_Evolution_StorageListener corba_local_storage_listener;
+ GNOME_Evolution_Storage corba_storage;
+ CORBA_Environment ev;
+
+ d(printf("---- CALLING STORAGE LISTENER STARTUP ---\n"));
+
+ local_corba_storage = corba_storage = evolution_shell_client_get_local_storage (shellclient);
+ if (corba_storage == CORBA_OBJECT_NIL) {
+ g_warning ("No local storage available from shell client!");
+ return;
+ }
+
+ /* setup to record this store's changes */
+ mail_note_store((CamelStore *)global_local_store, NULL, NULL, local_corba_storage, NULL, NULL);
+
+ local_storage_listener = evolution_storage_listener_new ();
+ corba_local_storage_listener = evolution_storage_listener_corba_objref (
+ local_storage_listener);
+
+ g_signal_connect(local_storage_listener,
+ "new_folder",
+ G_CALLBACK (local_storage_new_folder_cb),
+ corba_storage);
+ g_signal_connect(local_storage_listener,
+ "removed_folder",
+ G_CALLBACK (local_storage_removed_folder_cb),
+ corba_storage);
+
+ CORBA_exception_init (&ev);
+ GNOME_Evolution_Storage_addListener (corba_storage,
+ corba_local_storage_listener, &ev);
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("Cannot add a listener to the Local Storage.");
+ CORBA_exception_free (&ev);
+ return;
+ }
+ CORBA_exception_free (&ev);
+}
+
+/* ** The rest ******************************************************************** */
+
+void
+mail_local_storage_startup (EvolutionShellClient *shellclient, const char *evolution_path)
+{
+ mail_local_provider_init ();
+
+ global_local_store = MAIL_LOCAL_STORE(camel_session_get_service (session, "file:/", CAMEL_PROVIDER_STORE, NULL));
+
+ if (!global_local_store) {
+ g_warning ("No local store!");
+ return;
+ }
+
+ storage_listener_startup (shellclient);
+}
+
+void
+mail_local_storage_shutdown (void)
+{
+ bonobo_object_release_unref (local_corba_storage, NULL);
+ local_corba_storage = CORBA_OBJECT_NIL;
+}
+
+
+/*----------------------------------------------------------------------
+ * Local folder reconfiguration stuff
+ *----------------------------------------------------------------------*/
+
+/*
+ open new
+ copy old->new
+ close old
+ rename old oldsave
+ rename new old
+ open oldsave
+ delete oldsave
+
+ close old
+ rename oldtmp
+ open new
+ open oldtmp
+ copy oldtmp new
+ close oldtmp
+ close oldnew
+
+*/
+
+/* we should have our own progress bar for this */
+
+struct _reconfigure_msg {
+ struct _mail_msg msg;
+
+ char *uri;
+ CamelFolder *folder;
+
+ char *newtype;
+ unsigned int index_body:1;
+ GtkWidget *frame;
+ GtkWidget *apply;
+ GtkWidget *cancel;
+ GtkWidget *check_index_body;
+ GtkOptionMenu *optionlist;
+
+ void (*done)(const char *uri, CamelFolder *folder, void*data);
+ void *done_data;
+};
+
+/* hash table of folders that the user has a reconfig-folder dialog for */
+static GHashTable *reconfigure_folder_hash = NULL;
+
+static char *
+reconfigure_folder_describe (struct _mail_msg *mm, int done)
+{
+ struct _reconfigure_msg *m = (struct _reconfigure_msg *)mm;
+
+ return g_strdup_printf (_("Changing folder \"%s\" to \"%s\" format"),
+ camel_folder_get_full_name (m->folder),
+ m->newtype);
+}
+
+static void
+reconfigure_folder_reconfigure (struct _mail_msg *mm)
+{
+ struct _reconfigure_msg *m = (struct _reconfigure_msg *)mm;
+
+ d(printf("reconfiguring folder: %s to type %s\n", m->uri, m->newtype));
+
+ mail_local_folder_reconfigure (MAIL_LOCAL_FOLDER (m->folder), m->newtype, m->index_body, &mm->ex);
+}
+
+static void
+reconfigure_folder_reconfigured (struct _mail_msg *mm)
+{
+ struct _reconfigure_msg *m = (struct _reconfigure_msg *)mm;
+ GtkWidget *dialog;
+ /*char *uri;*/
+
+ if (camel_exception_is_set (&mm->ex)) {
+ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK, "%s",
+ _("If you can no longer open this mailbox, then\n"
+ "you may need to repair it manually."));
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ }
+
+ if (m->done)
+ m->done(m->uri, m->folder, m->done_data);
+}
+
+static void
+reconfigure_folder_free (struct _mail_msg *mm)
+{
+ struct _reconfigure_msg *m = (struct _reconfigure_msg *)mm;
+
+ /* remove this folder from our hash since we are done with it */
+ g_hash_table_remove (reconfigure_folder_hash, m->folder);
+ if (g_hash_table_size (reconfigure_folder_hash) == 0) {
+ /* additional cleanup */
+ g_hash_table_destroy (reconfigure_folder_hash);
+ reconfigure_folder_hash = NULL;
+ }
+
+ if (m->folder)
+ camel_object_unref (m->folder);
+ g_free(m->uri);
+ g_free (m->newtype);
+}
+
+static struct _mail_msg_op reconfigure_folder_op = {
+ reconfigure_folder_describe,
+ reconfigure_folder_reconfigure,
+ reconfigure_folder_reconfigured,
+ reconfigure_folder_free,
+};
+
+static void
+reconfigure_response(GtkDialog *dialog, int button, struct _reconfigure_msg *m)
+{
+ switch(button) {
+ case GTK_RESPONSE_OK: {
+ GtkWidget *menu, *item;
+
+ menu = gtk_option_menu_get_menu(m->optionlist);
+ item = gtk_menu_get_active(GTK_MENU(menu));
+ m->newtype = g_strdup(g_object_get_data ((GObject *)item, "type"));
+ m->index_body = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(m->check_index_body));
+
+ gtk_widget_set_sensitive (m->frame, FALSE);
+ gtk_widget_set_sensitive (m->apply, FALSE);
+ gtk_widget_set_sensitive (m->cancel, FALSE);
+
+ e_thread_put (mail_thread_new, (EMsg *)m);
+ break; }
+ case GTK_RESPONSE_CANCEL:
+ default:
+ if (m->done)
+ m->done(m->uri, NULL, m->done_data);
+ mail_msg_free ((struct _mail_msg *)m);
+ break;
+ }
+
+ gtk_widget_destroy((GtkWidget *)dialog);
+}
+
+static void
+reconfigure_got_folder(char *uri, CamelFolder *folder, void *data)
+{
+ GladeXML *gui;
+ GtkDialog *gd;
+ struct _reconfigure_msg *m = data;
+ char *title;
+ GList *p;
+ GtkWidget *menu;
+ char *currentformat;
+ int index=0, history=0;
+
+ if (folder == NULL
+ || !MAIL_IS_LOCAL_FOLDER (folder)) {
+ g_warning ("Trying to reconfigure nonexistant folder");
+ /* error display ? */
+ if (m->done)
+ m->done(uri, NULL, m->done_data);
+ mail_msg_free((struct _mail_msg *)m);
+ return;
+ }
+
+ if (!reconfigure_folder_hash)
+ reconfigure_folder_hash = g_hash_table_new (NULL, NULL);
+
+ if ((gd = g_hash_table_lookup (reconfigure_folder_hash, folder))) {
+ gdk_window_raise (GTK_WIDGET (gd)->window);
+ if (m->done)
+ m->done(uri, NULL, m->done_data);
+ mail_msg_free((struct _mail_msg *)m);
+ return;
+ }
+
+ gui = glade_xml_new (EVOLUTION_GLADEDIR "/local-config.glade", "dialog_format", NULL);
+ gd = (GtkDialog *)glade_xml_get_widget (gui, "dialog_format");
+
+ title = g_strdup_printf (_("Reconfigure /%s"),
+ camel_folder_get_full_name (folder));
+ gtk_window_set_title (GTK_WINDOW (gd), title);
+ g_free (title);
+
+ m->uri = g_strdup(uri);
+ m->frame = glade_xml_get_widget (gui, "frame_format");
+ m->apply = glade_xml_get_widget (gui, "apply_format");
+ m->cancel = glade_xml_get_widget (gui, "cancel_format");
+ m->optionlist = (GtkOptionMenu *)glade_xml_get_widget (gui, "option_format");
+ m->check_index_body = glade_xml_get_widget (gui, "check_index_body");
+ m->newtype = NULL;
+ m->folder = folder;
+ camel_object_ref(folder);
+
+ /* dynamically create the folder type list from camel */
+ /* we assume the list is static and never freed */
+ currentformat = MAIL_LOCAL_FOLDER (folder)->meta->format;
+ p = camel_session_list_providers (session, TRUE);
+ menu = gtk_menu_new ();
+ while (p) {
+ CamelProvider *cp = p->data;
+
+ /* we only want local providers */
+ if (cp->flags & CAMEL_PROVIDER_IS_LOCAL) {
+ GtkWidget *item;
+ char *label;
+
+ if (!strcmp (cp->protocol, currentformat))
+ history = index;
+
+ label = g_strdup_printf("%s (%s)", cp->protocol, _(cp->name));
+ item = gtk_menu_item_new_with_label (label);
+ g_free (label);
+ g_object_set_data ((GObject *) item, "type", cp->protocol);
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ index++;
+ }
+ p = p->next;
+ }
+ gtk_option_menu_remove_menu (GTK_OPTION_MENU (m->optionlist));
+ gtk_option_menu_set_menu (GTK_OPTION_MENU(m->optionlist), menu);
+ gtk_option_menu_set_history(GTK_OPTION_MENU(m->optionlist), history);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m->check_index_body), MAIL_LOCAL_FOLDER (folder)->meta->indexed);
+
+ gtk_label_set_text ((GtkLabel *)glade_xml_get_widget (gui, "label_format"),
+ MAIL_LOCAL_FOLDER (folder)->meta->format);
+
+ g_signal_connect(gd, "response", G_CALLBACK(reconfigure_response), m);
+ g_object_unref(gui);
+
+ g_hash_table_insert (reconfigure_folder_hash, (gpointer) folder, (gpointer) gd);
+
+ gtk_widget_show((GtkWidget *)gd);
+}
+
+void
+mail_local_reconfigure_folder(const char *uri, void (*done)(const char *uri, CamelFolder *folder, void *data), void *done_data)
+{
+ struct _reconfigure_msg *m;
+
+ if (strncmp(uri, "file:", 5) != 0) {
+ e_notice (NULL, GTK_MESSAGE_WARNING,
+ _("You cannot change the format of a non-local folder."));
+ if (done)
+ done(uri, NULL, done_data);
+ return;
+ }
+
+ m = mail_msg_new (&reconfigure_folder_op, NULL, sizeof (*m));
+ m->done = done;
+ m->done_data = done_data;
+
+ mail_get_folder(uri, 0, reconfigure_got_folder, m, mail_thread_new);
+}
diff --git a/mail/mail-ops.c b/mail/mail-ops.c
index 8d3711ff4e..3474885047 100644
--- a/mail/mail-ops.c
+++ b/mail/mail-ops.c
@@ -38,7 +38,6 @@
#include <camel/camel-vtrash-folder.h>
#include <camel/camel-vee-store.h>
#include "mail.h"
-#include "mail-component.h"
#include "mail-tools.h"
#include "mail-ops.h"
#include "mail-vfolder.h"
@@ -230,8 +229,7 @@ uid_cachename_hack (CamelStore *store)
url->host);
e_filename_make_safe (encoded_url);
- filename = g_strdup_printf ("%s/mail/pop3/cache-%s",
- mail_component_peek_base_directory (mail_component_peek ()), encoded_url);
+ filename = g_strdup_printf ("%s/mail/pop3/cache-%s", evolution_dir, encoded_url);
/* lame hack, but we can't expect user's to actually migrate
their cache files - brain power requirements are too
@@ -240,9 +238,7 @@ uid_cachename_hack (CamelStore *store)
/* This is either the first time the user has checked
mail with this POP provider or else their cache
file is in the old location... */
- old_location = g_strdup_printf ("%s/config/cache-%s",
- mail_component_peek_base_directory (mail_component_peek ()),
- encoded_url);
+ old_location = g_strdup_printf ("%s/config/cache-%s", evolution_dir, encoded_url);
if (stat (old_location, &st) == -1) {
/* old location doesn't exist either so use the new location */
g_free (old_location);
@@ -1063,9 +1059,9 @@ get_folderinfo_desc (struct _mail_msg *mm, int done)
}
static void
-add_vtrash_info (CamelStore *store, CamelFolderInfo *info)
+add_vtrash_or_vjunk_info (CamelStore *store, CamelFolderInfo *info, gchar *name, gchar *full_name, gchar *url_base, gboolean unread_count)
{
- CamelFolderInfo *fi, *vtrash, *parent;
+ CamelFolderInfo *fi, *vinfo, *parent;
char *uri, *path;
CamelURL *url;
@@ -1073,14 +1069,14 @@ add_vtrash_info (CamelStore *store, CamelFolderInfo *info)
parent = NULL;
for (fi = info; fi; fi = fi->sibling) {
- if (!strcmp (fi->name, CAMEL_VTRASH_NAME))
+ if (!strcmp (fi->name, name))
break;
parent = fi;
}
- /* create our vTrash URL */
+ /* create our vTrash/vJunk URL */
url = camel_url_new (info->url, NULL);
- path = g_strdup_printf ("/%s", CAMEL_VTRASH_NAME);
+ path = g_strdup_printf ("/%s", name);
if (url->fragment)
camel_url_set_fragment (url, path);
else
@@ -1090,32 +1086,45 @@ add_vtrash_info (CamelStore *store, CamelFolderInfo *info)
camel_url_free (url);
if (fi) {
- /* We're going to replace the physical Trash folder with our vTrash folder */
- vtrash = fi;
- g_free (vtrash->full_name);
- g_free (vtrash->name);
- g_free (vtrash->url);
+ /* We're going to replace the physical Trash/Junk folder with our vTrash/vJunk folder */
+ vinfo = fi;
+ g_free (vinfo->full_name);
+ g_free (vinfo->name);
+ g_free (vinfo->url);
} else {
- /* There wasn't a Trash folder so create a new folder entry */
- vtrash = g_new0 (CamelFolderInfo, 1);
+ /* There wasn't a Trash/Junk folder so create a new folder entry */
+ vinfo = g_new0 (CamelFolderInfo, 1);
g_assert(parent != NULL);
/* link it into the right spot */
- vtrash->sibling = parent->sibling;
- parent->sibling = vtrash;
+ vinfo->sibling = parent->sibling;
+ parent->sibling = vinfo;
}
/* Fill in the new fields */
- vtrash->full_name = g_strdup (_("Trash"));
- vtrash->name = g_strdup(vtrash->full_name);
- vtrash->url = g_strdup_printf ("vtrash:%s", uri);
- vtrash->unread_message_count = -1;
- vtrash->path = g_strdup_printf("/%s", vtrash->name);
+ vinfo->full_name = g_strdup (full_name);
+ vinfo->name = g_strdup(vinfo->full_name);
+ vinfo->url = g_strdup_printf ("%s:%s", url_base, uri);
+ if (!unread_count)
+ vinfo->unread_message_count = -1;
+ vinfo->path = g_strdup_printf("/%s", vinfo->name);
g_free (uri);
}
static void
+add_vtrash_info (CamelStore *store, CamelFolderInfo *info)
+{
+ add_vtrash_or_vjunk_info (store, info, CAMEL_VTRASH_NAME, _("Trash"), "vtrash", FALSE);
+}
+
+static void
+add_vjunk_info (CamelStore *store, CamelFolderInfo *info)
+{
+ add_vtrash_or_vjunk_info (store, info, CAMEL_VJUNK_NAME, _("Junk"), "vjunk", TRUE);
+}
+
+static void
add_unmatched_info(CamelFolderInfo *fi)
{
for (; fi; fi = fi->sibling) {
@@ -1142,6 +1151,8 @@ get_folderinfo_get (struct _mail_msg *mm)
if (m->info) {
if (m->info->url && (m->store->flags & CAMEL_STORE_VTRASH))
add_vtrash_info(m->store, m->info);
+ if (m->info->url && (m->store->flags & CAMEL_STORE_VJUNK))
+ add_vjunk_info(m->store, m->info);
if (CAMEL_IS_VEE_STORE(m->store))
add_unmatched_info(m->info);
}
@@ -2329,3 +2340,101 @@ mail_execute_shell_command (CamelFilterDriver *driver, int argc, char **argv, vo
gnome_execute_async_fds (NULL, argc, argv, TRUE);
}
+
+/* [Un]mark junk flag */
+
+struct _mark_junk_mail_msg {
+ struct _mail_msg msg;
+
+ CamelFolder *folder;
+ MessageList *list;
+ gboolean junk;
+};
+
+static char *
+mark_junk_describe (struct _mail_msg *mm, int complete)
+{
+ return g_strdup (_("Changing junk status"));
+}
+
+/* filter a folder, or a subset thereof, uses source_folder/source_uids */
+/* this is shared with fetch_mail */
+static void
+mark_junk_mark (struct _mail_msg *mm)
+{
+ struct _mark_junk_mail_msg *m = (struct _mark_junk_mail_msg *) mm;
+ CamelJunkPlugin *csp = NULL;
+ GPtrArray *uids;
+ gboolean commit_reports = FALSE;
+ int i;
+
+ if (m->folder == NULL)
+ return;
+
+ uids = message_list_get_selected (m->list);
+ camel_folder_freeze (m->folder);
+
+ for (i=0; i<uids->len; i++) {
+ guint32 flags;
+
+ flags = camel_folder_get_message_flags (m->folder, uids->pdata[i]);
+ if (((flags & CAMEL_MESSAGE_JUNK) == CAMEL_MESSAGE_JUNK) != m->junk) {
+ CamelMimeMessage *msg = camel_folder_get_message (m->folder, uids->pdata[i], NULL);
+
+ if (msg) {
+ csp = CAMEL_SERVICE (m->folder->parent_store)->session->junk_plugin;
+ if (m->junk)
+ camel_junk_plugin_report_junk (csp, msg);
+ else
+ camel_junk_plugin_report_notjunk (csp, msg);
+
+ commit_reports = TRUE;
+ camel_object_unref (msg);
+ }
+ }
+ camel_folder_set_message_flags(m->folder, uids->pdata[i],
+ CAMEL_MESSAGE_JUNK | (m->junk ? CAMEL_MESSAGE_DELETED : 0),
+ m->junk ? CAMEL_MESSAGE_JUNK : 0);
+ }
+
+ if (commit_reports)
+ camel_junk_plugin_commit_reports (csp);
+
+ message_list_free_uids(m->list, uids);
+ camel_folder_thaw(m->folder);
+}
+
+static void
+mark_junk_marked (struct _mail_msg *mm)
+{
+}
+
+static void
+mark_junk_free (struct _mail_msg *mm)
+{
+ struct _mark_junk_mail_msg *m = (struct _mark_junk_mail_msg *)mm;
+
+ if (m->folder)
+ camel_object_unref (m->folder);
+}
+
+static struct _mail_msg_op mark_junk_op = {
+ mark_junk_describe,
+ mark_junk_mark,
+ mark_junk_marked,
+ mark_junk_free,
+};
+
+void
+mail_mark_junk (CamelFolder *folder, MessageList *list, gboolean junk)
+{
+ struct _mark_junk_mail_msg *m;
+
+ m = mail_msg_new (&mark_junk_op, NULL, sizeof (*m));
+ m->folder = folder;
+ camel_object_ref (folder);
+ m->list = list;
+ m->junk = junk;
+
+ e_thread_put (mail_thread_new, (EMsg *) m);
+}
diff --git a/mail/mail-ops.h b/mail/mail-ops.h
index e15d7729c2..081e1a1425 100644
--- a/mail/mail-ops.h
+++ b/mail/mail-ops.h
@@ -36,6 +36,8 @@ extern "C" {
#include "camel/camel-mime-message.h"
#include "camel/camel-operation.h"
+#include "message-list.h"
+
#include "evolution-storage.h" /*EvolutionStorage */
#include "e-util/e-msgport.h"
#include "e-util/e-account.h"
@@ -164,6 +166,8 @@ int mail_store_set_offline(CamelStore *store, gboolean offline,
/* filter driver execute shell command async callback */
void mail_execute_shell_command (CamelFilterDriver *driver, int argc, char **argv, void *data);
+void mail_mark_junk (CamelFolder *folder, MessageList *list, gboolean junk);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/mail/mail-session.c b/mail/mail-session.c
index 58773513c4..61adfa812c 100644
--- a/mail/mail-session.c
+++ b/mail/mail-session.c
@@ -40,7 +40,6 @@
#include "filter/filter-context.h"
#include "filter/filter-filter.h"
#include "mail.h"
-#include "mail-component.h"
#include "mail-config.h"
#include "mail-session.h"
#include "mail-tools.h"
@@ -48,6 +47,7 @@
#include "mail-ops.h"
#include "e-util/e-passwords.h"
#include "e-util/e-msgport.h"
+#include "em-junk-filter.h"
#define d(x)
@@ -594,7 +594,7 @@ main_get_filter_driver (CamelSession *session, const char *type, CamelException
gconf = mail_config_get_gconf_client ();
- user = g_strdup_printf ("%s/mail/filters.xml", mail_component_peek_base_directory (mail_component_peek ()));
+ user = g_strdup_printf ("%s/filters.xml", evolution_dir);
system = EVOLUTION_PRIVDATADIR "/filtertypes.xml";
fc = (RuleContext *) filter_context_new ();
rule_context_load (fc, system, user);
@@ -626,6 +626,9 @@ main_get_filter_driver (CamelSession *session, const char *type, CamelException
fsearch = g_string_new ("");
faction = g_string_new ("");
+
+ /* implicit junk check as 1st rule */
+ camel_filter_driver_add_rule (driver, "Junk check", "(junk-test)", "(begin (set-system-flag \"junk\"))");
/* add the user-defined rules next */
while ((rule = rule_context_next_rule (fc, rule, type))) {
@@ -634,7 +637,6 @@ main_get_filter_driver (CamelSession *session, const char *type, CamelException
filter_rule_build_code (rule, fsearch);
filter_filter_build_action ((FilterFilter *) rule, faction);
-
camel_filter_driver_add_rule (driver, rule->name, fsearch->str, faction->str);
}
@@ -744,17 +746,19 @@ mail_session_forget_password (const char *key)
}
void
-mail_session_init (const char *base_directory)
+mail_session_init (void)
{
char *camel_dir;
-
- if (camel_init (base_directory, TRUE) != 0)
+
+ if (camel_init (evolution_dir, TRUE) != 0)
exit (0);
session = CAMEL_SESSION (camel_object_new (MAIL_SESSION_TYPE));
- camel_dir = g_strdup_printf ("%s/mail", base_directory);
+ camel_dir = g_strdup_printf ("%s/mail", evolution_dir);
camel_session_construct (session, camel_dir);
+
+ session->junk_plugin = CAMEL_JUNK_PLUGIN (em_junk_filter_get_plugin ());
/* The shell will tell us to go online. */
camel_session_set_online ((CamelSession *) session, FALSE);
diff --git a/mail/mail-tools.c b/mail/mail-tools.c
index b85a18c12f..dde9b5e9c8 100644
--- a/mail/mail-tools.c
+++ b/mail/mail-tools.c
@@ -46,10 +46,10 @@
#include "e-util/e-meta.h"
#include "mail.h" /*session*/
-#include "mail-component.h"
#include "mail-config.h"
#include "mail-vfolder.h"
#include "mail-tools.h"
+#include "mail-local.h"
#include "mail-mt.h"
#include "mail-folder-cache.h"
@@ -62,8 +62,7 @@ mail_tool_get_local_inbox (CamelException *ex)
CamelFolder *folder;
char *url;
- url = g_strdup_printf("file://%s/local/Inbox",
- mail_component_peek_base_directory (mail_component_peek ()));
+ url = g_strdup_printf("file://%s/local/Inbox", evolution_dir);
folder = mail_tool_uri_to_folder (url, 0, ex);
g_free (url);
@@ -121,9 +120,7 @@ mail_tool_get_local_movemail_path (const unsigned char *uri)
if (strchr ("/:;=|%&#!*^()\\, ", *c) || !isprint ((int) *c))
*c = '_';
- path = g_strdup_printf ("%s/local/Inbox/movemail.%s",
- mail_component_peek_base_directory (mail_component_peek ()),
- safe_uri);
+ path = g_strdup_printf ("%s/local/Inbox/movemail.%s", evolution_dir, safe_uri);
g_free (safe_uri);
return path;
@@ -312,6 +309,8 @@ mail_tool_uri_to_folder (const char *uri, guint32 flags, CamelException *ex)
/* This hack is still needed for file:/ since it's its own EvolutionStorage type */
if (!strncmp (uri, "vtrash:", 7))
offset = 7;
+ else if (!strncmp (uri, "vjunk:", 6))
+ offset = 6;
url = camel_url_new (uri + offset, ex);
if (!url) {
@@ -321,7 +320,7 @@ mail_tool_uri_to_folder (const char *uri, guint32 flags, CamelException *ex)
store = camel_session_get_store (session, uri + offset, ex);
if (store) {
const char *name;
-
+
/* if we have a fragment, then the path is actually used by the store,
so the fragment is the path to the folder instead */
if (url->fragment) {
@@ -333,9 +332,14 @@ mail_tool_uri_to_folder (const char *uri, guint32 flags, CamelException *ex)
name = "";
}
- if (offset)
- folder = camel_store_get_trash (store, ex);
- else
+ if (offset) {
+ if (offset == 7)
+ folder = camel_store_get_trash (store, ex);
+ else if (offset == 6)
+ folder = camel_store_get_junk (store, ex);
+ else
+ g_assert (FALSE);
+ } else
folder = camel_store_get_folder (store, name, flags, ex);
camel_object_unref (store);
}
@@ -415,7 +419,6 @@ mail_tools_folder_to_url (CamelFolder *folder)
static char *meta_data_key(const char *uri, char **pathp)
{
- const char *base_directory = mail_component_peek_base_directory (mail_component_peek ());
CamelURL *url;
GString *path;
const char *key;
@@ -425,12 +428,12 @@ static char *meta_data_key(const char *uri, char **pathp)
if (url == NULL) {
g_warning("Trying to retrieve meta-data for unparsable uri: %s", uri);
- *pathp = g_build_path(base_directory, "meta/unknown", NULL);
+ *pathp = g_build_path(evolution_dir, "meta/unknown", NULL);
return g_strdup("folder");
}
- path = g_string_new(base_directory);
+ path = g_string_new(evolution_dir);
g_string_append_printf(path, "/meta/%s/", url->protocol);
if (url->host && url->host[0]) {
diff --git a/mail/mail-vfolder.c b/mail/mail-vfolder.c
index f47fe4c660..82635df8df 100644
--- a/mail/mail-vfolder.c
+++ b/mail/mail-vfolder.c
@@ -32,7 +32,6 @@
#include "evolution-storage.h"
#include "evolution-shell-component.h"
-#include "mail-component.h"
#include "mail-vfolder.h"
#include "mail-tools.h"
#include "mail-autofilter.h"
@@ -65,6 +64,7 @@ static GHashTable *vfolder_hash;
extern EvolutionShellClient *global_shell_client;
/* more globals ... */
+extern char *evolution_dir;
extern CamelSession *session;
static void rule_changed(FilterRule *rule, CamelFolder *folder);
@@ -345,7 +345,7 @@ mail_vfolder_add_uri(CamelStore *store, const char *uri, int remove)
GCompareFunc uri_cmp = CAMEL_STORE_CLASS(CAMEL_OBJECT_GET_CLASS(store))->compare_folder_name;
int is_ignore;
- if (CAMEL_IS_VEE_STORE(store) || !strncmp(uri, "vtrash:", 7) || context == NULL)
+ if (CAMEL_IS_VEE_STORE(store) || !strncmp(uri, "vtrash:", 7) || !strncmp(uri, "vjunk:", 6) || context == NULL)
return;
g_assert(pthread_self() == mail_gui_thread);
@@ -426,7 +426,7 @@ mail_vfolder_delete_uri(CamelStore *store, const char *uri)
CamelVeeFolder *vf;
GString *changed;
- if (context == NULL || !strncmp(uri, "vtrash:", 7))
+ if (context == NULL || !strncmp(uri, "vtrash:", 7) || !strncmp(uri, "vjunk:", 6))
return;
d(printf ("Deleting uri to check: %s\n", uri));
@@ -471,8 +471,7 @@ mail_vfolder_delete_uri(CamelStore *store, const char *uri)
g_signal_connect_swapped (dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog);
gtk_widget_show (dialog);
- user = g_strdup_printf ("%s/mail/vfolders.xml",
- mail_component_peek_base_directory (mail_component_peek ()));
+ user = g_strdup_printf ("%s/vfolders.xml", evolution_dir);
rule_context_save ((RuleContext *) context, user);
g_free (user);
}
@@ -492,7 +491,7 @@ mail_vfolder_rename_uri(CamelStore *store, const char *from, const char *to)
d(printf("vfolder rename uri: %s to %s\n", from, to));
- if (context == NULL || !strncmp(from, "vtrash:", 7) || !strncmp(to, "vtrash:", 7))
+ if (context == NULL || !strncmp(from, "vtrash:", 7) || !strncmp(to, "vtrash:", 7) || !strncmp(from, "vjunk:", 6) || !strncmp(to, "vjunk:", 6))
return;
g_assert(pthread_self() == mail_gui_thread);
@@ -527,7 +526,7 @@ mail_vfolder_rename_uri(CamelStore *store, const char *from, const char *to)
char *user;
d(printf("Vfolders updated from renamed folder\n"));
- user = g_strdup_printf("%s/mail/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ()));
+ user = g_strdup_printf("%s/vfolders.xml", evolution_dir);
rule_context_save((RuleContext *)context, user);
g_free(user);
}
@@ -647,10 +646,7 @@ static void context_rule_removed(RuleContext *ctx, FilterRule *rule)
/* TODO: remove from folder info cache? */
path = g_strdup_printf("/%s", rule->name);
-
- /* EPFIXME This leaks, the original code was broken too. */
- e_storage_removed_folder (mail_component_lookup_storage (mail_component_peek (), vfolder_store), path);
-
+ evolution_storage_removed_folder(mail_lookup_storage(vfolder_store), path);
g_free(path);
LOCK();
@@ -700,8 +696,8 @@ store_folder_deleted(CamelObject *o, void *event_data, void *data)
rule_context_remove_rule((RuleContext *)context, rule);
g_object_unref(rule);
g_signal_connect(context, "rule_removed", G_CALLBACK(context_rule_removed), context);
-
- user = g_strdup_printf("%s/mail/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ()));
+
+ user = g_strdup_printf("%s/vfolders.xml", evolution_dir);
rule_context_save((RuleContext *)context, user);
g_free(user);
} else {
@@ -742,7 +738,7 @@ store_folder_renamed(CamelObject *o, void *event_data, void *data)
filter_rule_set_name(rule, info->new->full_name);
g_signal_connect(rule, "changed", G_CALLBACK(rule_changed), folder);
- user = g_strdup_printf("%s/mail/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ()));
+ user = g_strdup_printf("%s/vfolders.xml", evolution_dir);
rule_context_save((RuleContext *)context, user);
g_free(user);
@@ -754,7 +750,7 @@ store_folder_renamed(CamelObject *o, void *event_data, void *data)
}
void
-vfolder_load_storage(void)
+vfolder_load_storage(GNOME_Evolution_Shell shell)
{
char *user, *storeuri;
FilterRule *rule;
@@ -762,7 +758,7 @@ vfolder_load_storage(void)
vfolder_hash = g_hash_table_new(g_str_hash, g_str_equal);
/* first, create the vfolder store, and set it up */
- storeuri = g_strdup_printf("vfolder:%s/vfolder", mail_component_peek_base_directory (mail_component_peek ()));
+ storeuri = g_strdup_printf("vfolder:%s/vfolder", evolution_dir);
vfolder_store = camel_session_get_store(session, storeuri, NULL);
if (vfolder_store == NULL) {
g_warning("Cannot open vfolder store - no vfolders available");
@@ -777,10 +773,10 @@ vfolder_load_storage(void)
(CamelObjectEventHookFunc)store_folder_renamed, NULL);
d(printf("got store '%s' = %p\n", storeuri, vfolder_store));
- mail_component_load_storage_by_uri(mail_component_peek (), storeuri, _("VFolders"));
+ mail_load_storage_by_uri(shell, storeuri, _("VFolders"));
/* load our rules */
- user = g_strdup_printf ("%s/mail/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ()));
+ user = g_strdup_printf ("%s/vfolders.xml", evolution_dir);
context = vfolder_context_new ();
if (rule_context_load ((RuleContext *)context,
EVOLUTION_PRIVDATADIR "/vfoldertypes.xml", user) != 0) {
@@ -810,7 +806,8 @@ vfolder_editor_response (GtkWidget *dialog, int button, void *data)
{
char *user;
- user = g_strdup_printf ("%s/mail/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ()));
+ user = alloca(strlen(evolution_dir)+16);
+ sprintf(user, "%s/vfolders.xml", evolution_dir);
switch(button) {
case GTK_RESPONSE_ACCEPT:
@@ -823,8 +820,6 @@ vfolder_editor_response (GtkWidget *dialog, int button, void *data)
vfolder_editor = NULL;
gtk_widget_destroy(dialog);
-
- g_free (user);
}
void
@@ -851,7 +846,7 @@ edit_rule_response(GtkWidget *w, int button, void *data)
FilterRule *orig = g_object_get_data (G_OBJECT (w), "orig");
filter_rule_copy(orig, rule);
- user = g_strdup_printf("%s/mail/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ()));
+ user = g_strdup_printf("%s/vfolders.xml", evolution_dir);
rule_context_save((RuleContext *)context, user);
g_free(user);
}
@@ -882,7 +877,7 @@ vfolder_edit_rule(const char *uri)
GTK_STOCK_OK,
GTK_RESPONSE_OK,
NULL);
- gtk_container_set_border_width (GTK_CONTAINER (gd), 6);
+ gtk_container_set_border_width ((GtkContainer *) gd, 6);
gtk_box_set_spacing ((GtkBox *) gd->vbox, 6);
gtk_dialog_set_default_response(gd, GTK_RESPONSE_OK);
g_object_set(gd, "allow_shrink", FALSE, "allow_grow", TRUE, NULL);
@@ -930,7 +925,7 @@ new_rule_clicked(GtkWidget *w, int button, void *data)
g_object_ref(rule);
rule_context_add_rule((RuleContext *)context, rule);
- user = g_strdup_printf("%s/mail/vfolders.xml", mail_component_peek_base_directory (mail_component_peek ()));
+ user = g_strdup_printf("%s/vfolders.xml", evolution_dir);
rule_context_save((RuleContext *)context, user);
g_free(user);
}
@@ -976,7 +971,7 @@ vfolder_gui_add_rule(VfolderRule *rule)
GTK_RESPONSE_OK,
NULL);
gtk_dialog_set_default_response(gd, GTK_RESPONSE_OK);
- gtk_container_set_border_width (GTK_CONTAINER (gd), 6);
+ gtk_container_set_border_width ((GtkContainer *) gd, 6);
gtk_box_set_spacing ((GtkBox *) gd->vbox, 6);
g_object_set(gd, "allow_shrink", FALSE, "allow_grow", TRUE, NULL);
gtk_window_set_default_size (GTK_WINDOW (gd), 500, 500);
diff --git a/mail/message-list.c b/mail/message-list.c
index a16c40f265..6d0ed3146e 100644
--- a/mail/message-list.c
+++ b/mail/message-list.c
@@ -50,6 +50,7 @@
#include <camel/camel-file-utils.h>
#include <camel/camel-folder.h>
#include <camel/camel-folder-thread.h>
+#include <e-util/ename/e-name-western.h>
#include <e-util/e-memory.h>
#include "filter/filter-label.h"
@@ -188,6 +189,9 @@ static struct {
{ NULL, NULL }
};
+/* FIXME: junk prefs */
+static gboolean junk_folder = TRUE;
+
#ifdef SMART_ADDRESS_COMPARE
static EMailAddress *
e_mail_address_new (const char *address)
@@ -716,7 +720,7 @@ void
message_list_paste(MessageList *ml)
{
gtk_selection_convert(ml->priv->invisible, GDK_SELECTION_CLIPBOARD,
- gdk_atom_intern ("x-uid-list", FALSE),
+ gdk_atom_intern("x-evolution-message", FALSE),
GDK_CURRENT_TIME);
}
@@ -1424,12 +1428,12 @@ ml_selection_get(GtkWidget *widget, GtkSelectionData *data, guint info, guint ti
return;
if (info & 2) {
- /* text/plain */
+ /* text_plain */
printf("setting text/plain selection for uids\n");
em_utils_selection_set_mailbox(data, ml->folder, uids);
} else {
- /* x-uid-list */
- printf("setting x-uid-list selection for uids\n");
+ /* x-evolution-message */
+ printf("setting x-evolution-message selection for uids\n");
em_utils_selection_set_uidlist(data, ml->folder_uri, uids);
}
}
@@ -1478,7 +1482,7 @@ ml_selection_received_uidlist(MessageList *ml, GtkSelectionData *data)
static void
ml_selection_received(GtkWidget *widget, GtkSelectionData *data, guint time, MessageList *ml)
{
- if (data->target != gdk_atom_intern ("x-uid-list", FALSE)) {
+ if (data->target != gdk_atom_intern("x-evolution-message", FALSE)) {
printf("Unknown selection received by message-list\n");
return;
@@ -1488,7 +1492,7 @@ ml_selection_received(GtkWidget *widget, GtkSelectionData *data, guint time, Mes
}
static GtkTargetEntry ml_drag_types[] = {
- { "x-uid-list", 0, 0 },
+ { "x-evolution-message", 0, 0 },
{ "message/rfc822", 0, 1 },
/* not included in dest types */
{ "text/uri-list", 0, 2 },
@@ -1505,7 +1509,7 @@ ml_tree_drag_data_get (ETree *tree, int row, ETreePath path, int col,
if (uids->len > 0) {
switch (info) {
- case 0 /*DND_TARGET_TYPE_X_UID_LIST */:
+ case 0 /*DND_TARGET_TYPE_X_EVOLUTION_MESSAGE*/:
em_utils_selection_set_uidlist(data, ml->folder_uri, uids);
break;
case 1 /*DND_TARGET_TYPE_MESSAGE_RFC822*/:
@@ -1577,7 +1581,7 @@ message_list_init (GtkObject *object)
g_object_ref(p->invisible);
gtk_object_sink((GtkObject *)p->invisible);
- matom = gdk_atom_intern ("x-uid-list", FALSE);
+ matom = gdk_atom_intern("x-evolution-message", FALSE);
gtk_selection_add_target(p->invisible, GDK_SELECTION_CLIPBOARD, matom, 0);
gtk_selection_add_target(p->invisible, GDK_SELECTION_PRIMARY, matom, 1);
gtk_selection_add_target(p->invisible, GDK_SELECTION_CLIPBOARD, GDK_SELECTION_TYPE_STRING, 2);
@@ -2377,11 +2381,44 @@ build_flat_diff(MessageList *ml, CamelFolderChangeInfo *changes)
static void
+mail_folder_hide_by_flag (CamelFolder *folder, MessageList *ml, CamelFolderChangeInfo **changes, int flag)
+{
+ CamelFolderChangeInfo *newchanges, *oldchanges = *changes;
+ CamelMessageInfo *info;
+ int i;
+
+ newchanges = camel_folder_change_info_new ();
+
+ for (i = 0; i < oldchanges->uid_changed->len; i++) {
+ ETreePath node = g_hash_table_lookup (ml->uid_nodemap, oldchanges->uid_changed->pdata[i]);
+
+ info = camel_folder_get_message_info (folder, oldchanges->uid_changed->pdata[i]);
+ if (node != NULL && info != NULL && (info->flags & flag) != 0)
+ camel_folder_change_info_remove_uid (newchanges, oldchanges->uid_changed->pdata[i]);
+ else if (node == NULL && info != NULL && (info->flags & flag) == 0)
+ camel_folder_change_info_add_uid (newchanges, oldchanges->uid_changed->pdata[i]);
+ else
+ camel_folder_change_info_change_uid (newchanges, oldchanges->uid_changed->pdata[i]);
+ camel_folder_free_message_info (folder, info);
+ }
+
+ if (newchanges->uid_added->len > 0 || newchanges->uid_removed->len > 0) {
+ for (i = 0; i < oldchanges->uid_added->len; i++)
+ camel_folder_change_info_add_uid (newchanges, oldchanges->uid_added->pdata[i]);
+ for (i = 0; i < oldchanges->uid_removed->len; i++)
+ camel_folder_change_info_remove_uid (newchanges, oldchanges->uid_removed->pdata[i]);
+ camel_folder_change_info_free (oldchanges);
+ *changes = newchanges;
+ } else {
+ camel_folder_change_info_free (newchanges);
+ }
+}
+
+static void
main_folder_changed (CamelObject *o, gpointer event_data, gpointer user_data)
{
MessageList *ml = MESSAGE_LIST (user_data);
- CamelFolderChangeInfo *changes = (CamelFolderChangeInfo *)event_data, *newchanges;
- CamelMessageInfo *info;
+ CamelFolderChangeInfo *changes = (CamelFolderChangeInfo *)event_data;
CamelFolder *folder = (CamelFolder *)o;
int i;
@@ -2402,35 +2439,9 @@ main_folder_changed (CamelObject *o, gpointer event_data, gpointer user_data)
}
/* check if the hidden state has changed, if so modify accordingly, then regenerate */
- if (ml->hidedeleted) {
- newchanges = camel_folder_change_info_new ();
-
- for (i = 0; i < changes->uid_changed->len; i++) {
- ETreePath node = g_hash_table_lookup (ml->uid_nodemap, changes->uid_changed->pdata[i]);
-
- info = camel_folder_get_message_info (folder, changes->uid_changed->pdata[i]);
- if (node != NULL && info != NULL && (info->flags & CAMEL_MESSAGE_DELETED) != 0) {
- camel_folder_change_info_remove_uid (newchanges, changes->uid_changed->pdata[i]);
- } else if (node == NULL && info != NULL && (info->flags & CAMEL_MESSAGE_DELETED) == 0) {
- camel_folder_change_info_add_uid (newchanges, changes->uid_changed->pdata[i]);
- } else {
- camel_folder_change_info_change_uid (newchanges, changes->uid_changed->pdata[i]);
- }
- camel_folder_free_message_info (folder, info);
- }
-
- if (newchanges->uid_added->len > 0 || newchanges->uid_removed->len > 0) {
- for (i = 0; i < changes->uid_added->len; i++)
- camel_folder_change_info_add_uid (newchanges, changes->uid_added->pdata[i]);
- for (i = 0; i < changes->uid_removed->len; i++)
- camel_folder_change_info_remove_uid (newchanges, changes->uid_removed->pdata[i]);
- camel_folder_change_info_free (changes);
- changes = newchanges;
- } else {
- camel_folder_change_info_free (newchanges);
- }
- }
-
+ if (ml->hidejunk || ml->hidedeleted)
+ mail_folder_hide_by_flag (folder, ml, &changes, (ml->hidejunk ? CAMEL_MESSAGE_JUNK : 0) | (ml->hidedeleted ? CAMEL_MESSAGE_DELETED : 0));
+
if (changes->uid_added->len == 0 && changes->uid_removed->len == 0 && changes->uid_changed->len < 100) {
for (i = 0; i < changes->uid_changed->len; i++) {
ETreePath node = g_hash_table_lookup (ml->uid_nodemap, changes->uid_changed->pdata[i]);
@@ -2579,6 +2590,7 @@ message_list_set_folder (MessageList *message_list, CamelFolder *folder, const c
gconf = mail_config_get_gconf_client ();
hide_deleted = !gconf_client_get_bool (gconf, "/apps/evolution/mail/display/show_deleted", NULL);
message_list->hidedeleted = hide_deleted && !(folder->folder_flags & CAMEL_FOLDER_IS_TRASH);
+ message_list->hidejunk = junk_folder && !(folder->folder_flags & CAMEL_FOLDER_IS_JUNK) && !(folder->folder_flags & CAMEL_FOLDER_IS_TRASH);
hide_load_state (message_list);
mail_regen_list (message_list, message_list->search, NULL, NULL);
@@ -3038,6 +3050,7 @@ struct _regen_list_msg {
CamelFolderChangeInfo *changes;
gboolean dotree; /* we are building a tree */
gboolean hidedel; /* we want to/dont want to show deleted messages */
+ gboolean hidejunk; /* we want to/dont want to show junk messages */
gboolean thread_subject;
CamelFolderThread *tree;
@@ -3076,17 +3089,36 @@ regen_list_regen (struct _mail_msg *mm)
} else if (m->hidedel) {
char *expr;
- if (m->search) {
- expr = alloca(strlen(m->search) + 64);
- sprintf(expr, "(and (match-all (not (system-flag \"deleted\")))\n %s)", m->search);
- } else
- expr = "(match-all (not (system-flag \"deleted\")))";
+ if (m->hidejunk) {
+ if (m->search) {
+ expr = alloca(strlen(m->search) + 92);
+ sprintf(expr, "(and (match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\"))))\n %s)", m->search);
+ } else
+ expr = "(match-all (and (not (system-flag \"deleted\")) (not (system-flag \"junk\"))))";
+ } else {
+ if (m->search) {
+ expr = alloca(strlen(m->search) + 64);
+ sprintf(expr, "(and (match-all (not (system-flag \"deleted\")))\n %s)", m->search);
+ } else
+ expr = "(match-all (not (system-flag \"deleted\")))";
+ }
searchuids = uids = camel_folder_search_by_expression (m->folder, expr, &mm->ex);
} else {
- if (m->search)
- searchuids = uids = camel_folder_search_by_expression (m->folder, m->search, &mm->ex);
- else
- uids = camel_folder_get_uids (m->folder);
+ char *expr;
+
+ if (m->hidejunk) {
+ if (m->search) {
+ expr = alloca(strlen(m->search) + 64);
+ sprintf(expr, "(and (match-all (not (system-flag \"junk\")))\n %s)", m->search);
+ } else
+ expr = "(match-all (not (system-flag \"junk\")))";
+ searchuids = uids = camel_folder_search_by_expression (m->folder, expr, &mm->ex);
+ } else {
+ if (m->search)
+ searchuids = uids = camel_folder_search_by_expression (m->folder, m->search, &mm->ex);
+ else
+ uids = camel_folder_get_uids (m->folder);
+ }
}
if (camel_exception_is_set (&mm->ex))
@@ -3318,6 +3350,7 @@ mail_regen_list (MessageList *ml, const char *search, const char *hideexpr, Came
m->changes = changes;
m->dotree = ml->threaded;
m->hidedel = ml->hidedeleted;
+ m->hidejunk = ml->hidejunk;
m->thread_subject = gconf_client_get_bool (gconf, "/apps/evolution/mail/display/thread_subject", NULL);
g_object_ref(ml);
m->folder = ml->folder;
diff --git a/mail/message-list.h b/mail/message-list.h
index a5c88cf308..8052ed791b 100644
--- a/mail/message-list.h
+++ b/mail/message-list.h
@@ -113,6 +113,9 @@ struct _MessageList {
/* do we automatically hide deleted messages? */
guint hidedeleted : 1;
+
+ /* do we automatically hide junk messages? */
+ guint hidejunk : 1;
/* is the message-list object in a destroyed state? */
guint destroyed : 1;