diff options
Diffstat (limited to 'camel')
46 files changed, 2263 insertions, 2219 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index 68495b7d07..d7c203d0b0 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,6 +1,11 @@ -2004-12-01 Mengjie Yu <meng-jie.yu@sun.com> +2004-12-02 Not Zed <NotZed@Ximian.com> - * providers/imap/camel-imap-provider.c:add mnemonic for checkboxes. + ** See bug #69533. + + * providers/imap/camel-imap-command.c (imap_read_untagged): gross + hack, if we get a blank line after a literal, assume the server + (read: groupwise) made a mistake. Given the complexity of this + code i'm not sure it is the server anyway but what can you do. 2004-12-01 Not Zed <NotZed@Ximian.com> @@ -29,6 +34,8 @@ 2004-11-30 Not Zed <NotZed@Ximian.com> + ** See bug #69982 (maybe). + * providers/nntp/camel-nntp-stream.c (CAMEL_NNTP_STREAM_LINE): rename to STREAM_LINE_SIZE so it doesn't override the STREAM_LINE enum. Sigh. @@ -50,17 +57,12 @@ * evolution-2.0.2/camel/providers/imap/camel-imap-command.c (camel_imap_response_free) * evolution-2.0.2/camel/providers/imap/camel-imap-folder.c (camel_imap_folder_new,camel_imap_folder_selected,imap_refresh_info,camel_imap_folder_new,camel_imap_folder_selected) * evolution-2.0.2/camel/providers/imap/camel-imap-store.c (imap_get_capability,imap_connect_online,get_folder_online,get_folder_offline,get_subscribed_folders,folder_hash,get_folders) + * evolution-2.0.2/camel/providers/imap4/camel-imap4-engine.c (engine_parse_capability) * evolution-2.0.2/camel/providers/pop3/camel-pop3-store.c (get_folder) * evolution-2.0.2/camel/tests/lib/folders.c: (test_folder_message_ops) some strcasecmp() calls changed with g_ascii_strcasecmp() for Turkish character conversiton problems [ http://www.i18nguy.com/unicode/turkish-i18n.html ] -2004-10-12 Radek Doulik <rodo@ximian.com> - - * camel-junk-plugin.c: new init method implementation - - * camel-junk-plugin.h: added junk plugin init declaration - 2004-11-10 Not Zed <NotZed@Ximian.com> ** See bug #69109. @@ -71,16 +73,11 @@ nameinfo flags a bit so we know when we got a numeric name and need to wrap it in []. -2004-11-21 Sivaiah Nallagatla <snallagatla@novell.com> - - * providers/groupwise/camel-groupwise-provider.c : added - a setting to mark the account for offline usuage +2004-11-19 Not Zed <NotZed@Ximian.com> - * providers/groupwise/came-gw-listener.c - (add_esource) (modify_esource) : changed the prototypes - to pass CamelUrl instead of individual properties - Add offline_sync property on e-sources if account is - marked for offline + * providers/imap/camel-imap-store.c (connect_to_server): if we + have CAMEL_IMAP_BRAINDAMAGED set, then treat the server as + braindamaged ok. Testing for #69533. 2004-11-18 Not Zed <NotZed@Ximian.com> @@ -89,10 +86,6 @@ * providers/nntp/camel-nntp-summary.c: Make debug run based on 'nntp' debug option. - * providers/nntp/camel-nntp-stream.c (stream_fill): if we get a 0 - read, return ECONNRESET. This should really have been put on the - stream for that imap hack fix. - * providers/nntp/camel-nntp-store.c (camel_nntp_try_authenticate): retry if the password attempt failed. @@ -103,140 +96,6 @@ (camel_nntp_command): if we continue, then set the return code to -1, so we re-loop rather than abort. -2004-11-15 Jeffrey Stedfast <fejj@novell.com> - - * providers/pop3/camel-pop3-store.c (connect_to_server_wrapper): - In the fallback cases, clear the exception first. - - * providers/imap/camel-imap-store.c (connect_to_server_wrapper): - In the fallback cases, clear the exception first. - - * providers/imap4/camel-imap4-store.c (connect_to_server_wrapper): - In the fallback cases, clear the exception first. - -2004-11-15 Jeffrey Stedfast <fejj@novell.com> - - * providers/imap/camel-imap-store.c (connect_to_server): Use - camel_tcp_stream_ssl_new_raw() for STARTTLS stream. - - * providers/imap4/camel-imap4-store.c (connect_to_server): Use - camel_tcp_stream_ssl_new_raw() for STARTTLS stream. - - * providers/pop3/camel-pop3-store.c: Change default port numbers - to be correct (they shouldn't all be the pop3s port). - (connect_to_server): Moved the last tcp_stream unref to afetr the - last fail-check so that we won't ever get a double-unref on - something we only own one ref on. - (connect_to_server): Unref the tcp_stream if we fail to create an - engine object before returning fail. - (connect_to_server): Use camel_tcp_stream_ssl_new_raw() for - STARTTLS stream. - - * providers/imap4/camel-imap4-stream.c (camel_imap4_stream_line): - Fix bug #69408 by filling our input buffer if inptr == inend. - -2004-11-13 Jeffrey Stedfast <fejj@ximian.com> - - * providers/imap4/camel-imap4-engine.c - (camel_imap4_engine_parse_resp_code): Handle numeric tokens for - the COPYUID set values as well. - -2004-11-12 Jeffrey Stedfast <fejj@novell.com> - - * providers/imap4/camel-imap4-summary.c (camel_imap4_summary_new): - Folder now gets set on the CamelFolderSummary object rather than - the CamelIMAP4Summary. - (imap4_fetch_all_update): Base summary class now has a folder - member, use that instead. - (imap4_fetch_all_add): Same. - (imap4_summary_fetch_all): Same. - (imap4_summary_fetch_flags): Same. - (camel_imap4_summary_set_uidvalidity): Same. - (camel_imap4_summary_expunge): Same. - (camel_imap4_summary_flush_updates): Same. - - * providers/imap4/camel-imap4-folder.c (imap4_append_message): - Init appended_uid value to NULL - - * providers/imap4/camel-imap4-engine.c (engine_parse_namespace): - Properly handle NILs for the namespace separator (somehow I missed - this, silly me). - -2004-11-16 Not Zed <NotZed@Ximian.com> - - * camel-lock-helper.c (g_strerror): have our own so we don't need - to link with glib. - - * providers/*/Makefile.am: Do not install ANY provider header - files. No providers are subclassable. No providers are directly - linkable. - - * camel.pc.in: create package config file. - - * tests/lib/folders.c (test_folder_message_ops): updated counts for - delete also marking unread. - - * tests/lib/camel-test.c (camel_test_provider_init): new api for - initialising test system 'in-build'. - - * camel-provider.c: remove the assertions, init if we need to,k - use pthread_once stuff to serialise it. - - * tests/folder/test3.c (main): remove gtk stuff (???). - - * tests/*: Fix all the makefiles. Made make-check work 'in-build'. - - * tests/lib/folders.c (test_folder_counts): update for api changes. - (test_message_info): similar. - - * providers/Makefile.am: removed groupwise from the build, this - can't go in here anymore, not in its current state. - - * camel-net-utils.c (camel_gethostbyaddr_r) - (camel_gethostbyname_r): the old e_gethost* calls from - e-host-utils.c. - -2004-11-15 Not Zed <NotZed@Ximian.com> - - * providers/imap/camel-imap-utils.c (imap_path_to_physical): - copied from e-path.c. - (imap_path_find_folders): copied from e-path.c. - - * camel.h: remove the provider stuff from the header. - - * camel-provider.c: globalise provider_init variable, and asserton - it in all functions that rely on it. - - * camel-service.c: removed getaddrinfo/etc. - - * camel-net-utils.[ch]: separate out camel_getaddrinfo etc. - - * Makefile.am: split camel into 2 libraries, libcamel and - libcamel-store. - - * camel-multipart-signed.c (camel_multipart_signed_sign) - (camel_multipart_signed_verify, prepare_sign): remove old - deprecated api. - - * camel-multipart-encrypted.c (camel_multipart_encrypted_encrypt) - (camel_multipart_encrypted_decrypt): remove old deprecated api. - -2004-11-12 Not Zed <NotZed@Ximian.com> - - ** Merge in notzed-messageinfo-branch, fix some minor conflicts. - -2004-11-11 Jeffrey Stedfast <fejj@novell.com> - - * providers/imap4/camel-imap4-store.c (imap4_reconnect): Free the - passwd here if we need to retry to authenticate. - -2004-11-10 Jeffrey Stedfast <fejj@novell.com> - - * providers/imap4/camel-imap4-summary.c (imap4_summary_fetch_all): - Use the expanded ALL macro as on closer inspection of the RFC, - we're not allowed to use macros in conjunction with other FETCH - items (such as UID in our case). - 2004-11-09 Not Zed <NotZed@Ximian.com> * providers/imap/camel-imap-folder.c (imap_get_message): before @@ -252,14 +111,6 @@ (content_info_incomplete): recursively check the content-info for completeness, not just one level. -2004-11-09 Jeffrey Stedfast <fejj@novell.com> - - * providers/imap4/camel-imap4-provider.c: Updated the properties - to include all the same settings as the old imap code. - - * providers/imap4/camel-imap4-folder.c (imap4_getv): Implemented. - (imap4_setv): Implemented. - 2004-11-08 Jeffrey Stedfast <fejj@novell.com> Fix for bug #69241. @@ -271,303 +122,11 @@ part, we need to use camel_data_wrapper_decode_to_stream() in case the part was encoded in any way. -2004-11-09 Jeffrey Stedfast <fejj@novell.com> - - * providers/imap4/camel-imap4-stream.c (camel_imap4_stream_line): - Handle not getting the CRLF pair together. Also don't require that - we have at least 3 bytes in the read buffer as it is possible we - don't have that much (see bug #69160). - -2004-11-08 Jeffrey Stedfast <fejj@novell.com> - - * providers/imap4/camel-imap4-store.c (imap4_subscribe_folder): - Note the folder-info just subscribed. - (imap4_unsubscribe_folder): Unnote the folder-info. - -2004-11-04 Jeffrey Stedfast <fejj@novell.com> - - * providers/imap4/camel-imap4-engine.c: Added much in-line - documentation. - (engine_parse_capability): Use g_ascii_str[n]casecmp(). - (camel_imap4_engine_nstring): New convenience function. - -2004-11-02 Not Zed <NotZed@Ximian.com> - - * camel-object.c (camel_object_hook_event): check interfaces for - events too. - (camel_object_trigger_event): check interfaces for events too. - (camel_object_class_add_event): more checks for interfaces vs - normal object classes. - (camel_object_class_add_interface): add an interface to a class. - (camel_object_get_interface): query for interfaces on an object. - (camel_object_get_type): register the interface type. - -2004-11-02 Jeffrey Stedfast <fejj@novell.com> - - * providers/imap4/camel-imap4-store.c (imap4_folder_utf7_name): - Don't bother getting the folder delim if the name is "" since we - don't need it in that case. - - * providers/imap4/camel-imap4-utils.c - (camel_imap4_get_path_delim): add an assert that s->namespaces is - non-NULL. - - * providers/imap4/camel-imap4-stream.c - (camel_imap4_stream_literal): Update stream->inptr after fetching - the literal chunk. - - * providers/imap4/camel-imap4-summary.c (envelope_decode_address): - Do proper cleanup in case of error and also handle literals. - - * providers/imap4/camel-imap4-store.c (imap4_get_folder_info): - Removed camel_service_connect() call which is no longer needed. - (imap4_connect): If engine is already connected, shortcut to - simply returning success. - (imap4_disconnect): Check engine state rather than poking at - stream state. - -2004-11-01 Jeffrey Stedfast <fejj@novell.com> - - * providers/smtp/camel-smtp-transport.c - (connect_to_server_wrapper): Do the same SSL->TLS and TLS->CLEAR - fallbacks that the 2.0 (and older) code did. - - * providers/pop3/camel-pop3-store.c (connect_to_server_wrapper): - Same. - - * providers/imap4/camel-imap4-store.c (connect_to_server_wrapper): - Same. - - * providers/imap/camel-imap-store.c (connect_to_server_wrapper): - Same. - -2004-11-01 Jeffrey Stedfast <fejj@novell.com> - - * providers/imap4/camel-imap4-summary.c - (camel_imap4_summary_expunge): Remove expunged messages from the - cache. - (camel_imap4_summary_set_uidvalidity): Clear the cache if the - UIDVALIDITY has changed. - - * providers/imap4/camel-imap4-folder.c (imap4_get_message): If the - message exists in the cache, use that rather than fetching it from - the server and cache messages fetched from the server for later - use. - (camel_imap4_folder_finalize): Unref the cache if non-NULL. - (camel_imap4_folder_new): Create the CamelDataCache. - - * providers/imap4/camel-imap4-store.c (imap4_create_folder): Cache - the folder-info on the summary if successful. - (imap4_delete_folder): Un-cache the folder-info from the summary. - - * providers/imap4/camel-imap4-store-summary.c (load_namespaces): - Cleaned up a bit. - (save_namespaces): Same. - (camel_imap4_store_summary_unnote_info): New function. - (camel_imap4_store_summary_get_folder_info): Fixed the logic a - bit. - -2004-11-11 Not Zed <NotZed@Ximian.com> - - * providers/imap4/*: Update for folder-summary api changes. - - * providers/imap4/camel-imap4-store.c (imap4_build_folder_info): - clean up the logic for getting counts from the folder, we have - code to do this already. Also always run it against the selected - folder, does'nt need to have FAST bit unset. - - * camel-folder-summary.c (camel_folder_summary_info_new): removed. - - * camel-string-utils.c (camel_pstring_strdup, camel_pstring_free): - pooled string allocators. Oh so much easier than the poolv thing, - and these refcount too. - - * camel-folder-summary.h: put message_id back into the summary. - -2004-11-08 Not Zed <NotZed@Ximian.com> - - * camel-folder.c (camel_folder_get_deleted_message_count): use - getv method to get the deleted count. - (get_deleted_message_count): removed. - - * camel-vtrash-folder.c (vtrash_getv): override the unread count - to ignore junked or deleted. - - * camel-folder.c (folder_getv): ignore junked and deleted in the - unread count. - - * camel-vee-folder.c (camel_vee_folder_finalise): changed the - logic slightly not to call internal functions directly. - (vee_delete): implement, remove all our folders when we're - deleted, to give unmatched at least a snowflakes chance in hell of - working. - - * camel-vtrash-folder.c (vtrash_search_by_expression) - (vtrash_search_by_uids, vtrash_folder_changed, vtrash_add_folder) - (vtrash_remove_folder, vtrash_rebuild_folder): implement - vtrash-optimised versions. Much faster. - - * camel-vee-folder.c (camel_vee_folder_set_folders): don't rebuild - the folder. - (camel_vee_folder_add_folder): track folders here, but invoke - virtual method to let subclasses know about it. - (camel_vee_folder_remove_folder): similar. - (vee_search_by_uids): free the folder_uids array with TRUE, - plugging memory leak. - -2004-11-06 Not Zed <NotZed@Ximian.com> - - * camel-vee-folder.c: Removed vname, use Folder->full_name - instead. Make add_folder/remove_folder/set_expression/set_folders - virtual methods. - (vee_add_folder): virtual implementation. - - * camel-vee-summary.c (camel_vee_summary_add): remove folder arg. - -2004-11-05 Not Zed <NotZed@Ximian.com> - - * camel-vee-summary.c (vee_info_set_flags): don't emit changed for - ourselves, let it filter through the changed handler, otherwise we - do it twice. - (vee_info_set_user_tag, vee_info_set_user_flag): same. - - * camel-folder-summary.c (message_info_new_from_header): use the - string pool for allocations. - (message_info_load): same here. - (camel_pstring_strdup): noop for NULL or "" - (camel_pstring_free): same. - (summary_assign_uid): don't always assing the flagged bit, der. - -2004-11-02 Not Zed <NotZed@Ximian.com> - - * camel-folder-summary.c (camel_pstring_strdup) - (camel_pstring_free, message_info_free, message_info_clone): - 'uniquify' the strings. - -2004-10-28 Jeffrey Stedfast <fejj@ximian.com> - - * providers/imap4/camel-imap4-summary.c (envelope_decode_nstring): - Handle literal strings. - (envelope_decode_date): Same. Fixes bug #68894. - - * providers/imap4/camel-imap4-stream.c - (camel_imap4_stream_next_token): Properly tokenise "\*" as a flag - token. Fixes bug #68869. - -2004-10-21 Björn Torkelsson <torkel@acc.umu.se> - - * camel-sasl-kerberos4.c: #include "camel-i18n.h" - 2004-10-27 Julio M. Merino Vidal <jmmv@menta.net> * camel-operation.c (camel_operation_shutdown): fix the arguments to pthread_key_delete. -2004-10-26 Jeffrey Stedfast <fejj@novell.com> - - * providers/imap4/camel-imap4-store-summary.[c,h]: New files - implementing a folder-info cache for offline mode (and faster - startup I guess). - - * providers/imap4/camel-imap4-store.c (imap4_build_folder_info): - Cache the folder-info for later use in offline mode. - - * providers/imap4/camel-imap4-utils.c - (camel_imap4_get_path_delim): Instead of assigning top = "INBOX", - do strcpy (top, "INBOX") so that we can later modify the - string. Fixes bug #68814. - -2004-10-25 Jeffrey Stedfast <fejj@novell.com> - - * providers/imap4/camel-imap4-engine.c (engine_parse_namespace): - Updated to use the public function in camel-imap4-utils.c - (camel_imap4_engine_finalize): Same. - - * providers/imap4/camel-imap4-store.c (imap4_construct): Setup and - load the store summary. - (camel_imap4_store_finalize): Unref the store summary. - (imap4_get_folder): Implemented offline support. - (imap4_folder_utf7_name): Pass the summary to get_delim rather - than the engine. - (imap4_create_folder): Same. - (imap4_reconnect): Update the namespaces on the store summary. - (connect_to_server): Update the store summary capabilities. - - * providers/imap4/camel-imap4-utils.c - (camel_imap4_get_path_delim): Now takes a store-summary rather - than an engine so that it will work in offline mode. - (camel_imap4_namespace_clear): Moved here from - camel-imap4-engine.c - (camel_imap4_namespace_list_copy): New convenience function. - (camel_imap4_namespace_list_free): New. - - * providers/imap4/camel-imap4-folder.c (camel_imap4_folder_new): - Check the return value of summary loading in offline mode (if it - fails, we can't get the folder). - -2004-10-21 Jeffrey Stedfast <fejj@novell.com> - - * camel-sasl-gssapi.c: #include "camel-i18n.h" - -2004-10-20 Jeffrey Stedfast <fejj@ximian.com> - - * providers/imap4/camel-imap4-store.c (imap4_get_folder): Don't - allow users to create folders in offline mode. When in offline - mode, use a different codepath to get a folder object. - (imap4_noop): Handle offline mode. - (imap4_unsubscribe_folder): Throw an exception if we are in - offline mode. - (imap4_subscribe_folder): Same. - (imap4_get_folder_info): Started to implement offline - support. Also, even if we are in online mode but the engine has - not yet been connected, we should follow the "offline" code path - and get the folder info's from the cache. - (imap4_rename_folder): Disallow in offline mode. - (imap4_delete_folder): Same. - (imap4_connect): Handle offline mode. - (imap4_disconnect): Handle offline mode and do proper locking. - (imap4_query_auth_types): Same. - -2004-10-19 Jeffrey Stedfast <fejj@ximian.com> - - * providers/imap4/camel-imap4-summary.c (imap4_summary_fetch_all): - Removed an already-fixed FIXME comment. - (imap4_summary_fetch_flags): Same. - - * providers/imap4/camel-imap4-folder.c (imap4_get_path_delim): - Removed. Use camel_imap4_get_path_delim() instead. - (camel_imap4_folder_new): Updated. - (imap4_sync): If we aren't online, we're done. nothing to do. - (imap4_refresh_info): Same. - (imap4_append_message): Same but set an exception. - (imap4_transfer_messages_to): Same. - - * providers/imap4/camel-imap4-utils.c - (camel_imap4_get_path_delim): Moved here from camel-imap4-store.c - - * providers/imap4/camel-imap4-store.c (imap4_try_authenticate): - Change the service string for the sasl mechanism to"imap" rather - than "imap4". - (imap4_get_path_delim): Removed. - (imap4_create_folder): Updated. - (imap4_folder_utf7_name): Same. - -2004-10-13 Not Zed <NotZed@Ximian.com> - - * providers/imap4/camel-imap4-folder.c (camel_imap4_folder_new) - (imap4_sync_changes, imap4_sync): - * providers/imap4/camel-imap4-summary.c (untagged_fetch_all): kill - cast as lvalue warning. - - * camel-string-utils.h: add prototype for camel_toupper. - - * providers/imap4/camel-imap4-utils.c: - * providers/imap4/camel-imap4-summary.c: - * providers/imap4/camel-imap4-folder.c: - * providers/imap4/camel-imap4-engine.c: - * providers/imap4/camel-imap4-command.c: - * providers/imap4/camel-imap4-store.c: include camel-i18n.h. - 2004-10-12 Not Zed <NotZed@Ximian.com> ** See bug ??? @@ -591,11 +150,11 @@ ** See bug #67898 and probably others. * providers/imapp/camel-imapp-store.c (connect_to_server): - * providers/pop3/camel-pop3-store.c (connect_to_server_wrapper): + * providers/pop3/camel-pop3-store.c (connect_to_server): * providers/imap4/camel-imap4-store.c (connect_to_server_wrapper): - * providers/imap/camel-imap-store.c (connect_to_server_wrapper): - * providers/nntp/camel-nntp-store.c (connect_to_server_wrapper): - * providers/smtp/camel-smtp-transport.c (connect_to_server_wrapper): + * providers/imap/camel-imap-store.c (connect_to_server): + * providers/nntp/camel-nntp-store.c (connect_to_server): + * providers/smtp/camel-smtp-transport.c (connect_to_server): Fallback to hard-coded port number if the name lookup fails and no port was supplied. @@ -609,11 +168,11 @@ 2004-10-09 Sivaiah Nallagatla <snallagatla@novell.com> - * providers/groupwise/camel-gw-listner.c (add_esource) : add the - source uid to list of selected calendar and tasks so that - groupwise calendar and tasks are automatically selected + * providers/groupwise/camel-gw-listner.c (add_esource) : + add the source uid to list of selected calendar and tasks + so that groupwise calendar and tasks are automatically selected (remove_esource) : remove the uids from corresponding gconf keys - Fixes #62053 + Fixes #62053 2004-10-08 Not Zed <NotZed@Ximian.com> @@ -643,16 +202,6 @@ EAI_AGAIN, it doesn't appear to mean the same as EAGAIN does with system calls (i guess 'no shit sherlock' really). -2004-10-04 JP Rosevear <jpr@novell.com> - - * providers/imap4/camel-imap4-provider.c: include camel-i18n.h - -2004-10-01 Jeffrey Stedfast <fejj@novell.com> - - * camel-service.c (camel_getaddrinfo): Avoid assigning a value to - the member of a const struct (which newer gcc's apparently break - over) by casting to non-const. - 2004-09-28 Not Zed <NotZed@Ximian.com> ** See bug #66509. @@ -696,7 +245,7 @@ * camel-vee-store.c: * camel-vee-folder.c: move the unmatched folder onto the camel-vee-store object. Removede the global - unmatched folder and associated locks/etc, fixed all the code up + unmatched folder and associated locks/etc, fixed all the code up to work with the new unmatched folder, if present. 2004-09-27 Not Zed <NotZed@Ximian.com> @@ -722,24 +271,6 @@ (spool_get_meta_path): implement, this needs to work differnetly to the parent classes implementations :-/. -2004-09-22 Jeffrey Stedfast <fejj@novell.com> - - * providers/imap/camel-imap-store.c (connect_to_server): Instead - of doing a host-lookup ourselves, get it passed in to us as an - argument. Also simplified a bit (try_starttls is no longer an - option). - (connect_to_server_wrapper): Simplified (we no longer have - fallback cases for SSL stuff). Also, perform host lookup here. - - * providers/imap4/camel-imap4-store.c: Same changes as above. - - * providers/pop3/camel-pop3-store.c: Same. - - * providers/smtp/camel-smtp-transport.c: Same. Other changes - include making the code consistant with the other providers. - - * providers/nntp/camel-nntp-store.c: Same as pop/imap. - 2004-09-21 Not Zed <NotZed@Ximian.com> ** See bug #63521. @@ -824,12 +355,6 @@ * camel-http-stream.c: turn off debug. -2004-09-08 Hannah & Fazlu <hannah_lins@yahoo.co.in> - - Fixes Bug#61088 - - * camel/camel-smime-context.c: Change of strings. - 2004-09-15 Not Zed <NotZed@Ximian.com> ** See bug #0xffff. @@ -1150,60 +675,6 @@ CAMEL_GROUPWISE_CFLAGS. (libcamelgroupwise_la_LIBADD): use CAMEL_GROUPWISE_LIBS. -2004-09-07 Not Zed <NotZed@Ximian.com> - - * providers/groupwise/camel-groupwise-provider.c: put the options - in their own section. - -2004-09-06 Not Zed <NotZed@Ximian.com> - - * camel-search-private.c (utf8_get): remove this, and make the - code use camel_utf8_getc instead. Quite a bit faster esp if - optimising with inlines. - - * camel-object.c (check_magic_fail): change the check_magic code - to mostly run from a macro, its worth it. - -2004-09-04 Not Zed <NotZed@Ximian.com> - - * providers/local/camel-mbox-summary.c (message_info_new): fix - cast issue. - - * providers/pop3/camel-pop3-engine.c (get_capabilities): remove - some unused variables. - - * camel-object.h: remove camel-i18n.h, fixed all c files where - appropriate. - -2004-08-25 Not Zed <NotZed@Ximian.com> - - * camel-list-utils.[ch]: Copied e_dlist* stuff to here, part of - removing e-util dependency on camel. - -2004-08-05 Not Zed <NotZed@Ximian.com> - - * providers/local/camel-local-provider.c: same. - - * providers/imap/camel-imap-provider.c: put the extra stuff into a - 'general' section. - - * providers/imapp/camel-imapp-provider.c: same. - - * providers/pop3/camel-pop3-provider.c: make sure each section - start has a name. - -2004-08-03 Not Zed <NotZed@Ximian.com> - - * camel-url.c (camel_url_set_param): when clearing a param, use - remove_data instead of set_data_full. craptatious glib at it - again. - - * providers/nntp/camel-nntp-provider.c: turn on ssl option. - -2004-07-07 Not Zed <NotZed@Ximian.com> - - * camel-folder.c: removed filter-rule.h ugh. - 2004-07-02 Christian Neumair <chris@gnome-de.org> * camel-smime-context.c: s/Can't/Cannot/. diff --git a/camel/camel-charset-map.c b/camel/camel-charset-map.c index 74ab90bc5d..59f916c700 100644 --- a/camel/camel-charset-map.c +++ b/camel/camel-charset-map.c @@ -203,7 +203,7 @@ int main (void) #include "camel-charset-map.h" #include "camel-charset-map-private.h" -#include <libedataserver/e-iconv.h> +#include <gal/util/e-iconv.h> #include <glib.h> #include <locale.h> diff --git a/camel/camel-filter-driver.c b/camel/camel-filter-driver.c index ddc787b1e8..cd26c3c390 100644 --- a/camel/camel-filter-driver.c +++ b/camel/camel-filter-driver.c @@ -44,12 +44,12 @@ #include "camel-stream-fs.h" #include "camel-stream-mem.h" #include "camel-mime-message.h" + #include "camel-debug.h" -#include "camel-i18n.h" -#include "libedataserver/e-sexp.h" -#include "libedataserver/e-memory.h" -#include "libedataserver/e-msgport.h" /* for edlist */ +#include "e-util/e-sexp.h" +#include "e-util/e-memory.h" +#include "e-util/e-msgport.h" /* for edlist */ #define d(x) @@ -575,7 +575,7 @@ do_colour (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDr if (p->source && p->uid && camel_folder_has_summary_capability (p->source)) camel_folder_set_message_user_tag (p->source, p->uid, "colour", argv[0]->value.string); else - camel_message_info_set_user_tag(p->info, "colour", argv[0]->value.string); + camel_tag_set (&p->info->user_tags, "colour", argv[0]->value.string); camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Set colour to %s", argv[0]->value.string); } @@ -595,7 +595,7 @@ do_score (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDri if (p->source && p->uid && camel_folder_has_summary_capability (p->source)) camel_folder_set_message_user_tag (p->source, p->uid, "score", value); else - camel_message_info_set_user_tag(p->info, "score", value); + camel_tag_set (&p->info->user_tags, "score", value); camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Set score to %d", argv[0]->value.number); g_free (value); } @@ -615,7 +615,7 @@ set_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterDri if (p->source && p->uid && camel_folder_has_summary_capability (p->source)) camel_folder_set_message_flags (p->source, p->uid, flags, ~0); else - camel_message_info_set_flags(p->info, flags | CAMEL_MESSAGE_FOLDER_FLAGGED, ~0); + p->info->flags |= flags | CAMEL_MESSAGE_FOLDER_FLAGGED; camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Set %s flag", argv[0]->value.string); } @@ -634,7 +634,7 @@ unset_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFilterD if (p->source && p->uid && camel_folder_has_summary_capability (p->source)) camel_folder_set_message_flags (p->source, p->uid, flags, 0); else - camel_message_info_set_flags(p->info, flags | CAMEL_MESSAGE_FOLDER_FLAGGED, 0); + p->info->flags = (p->info->flags & ~flags) | CAMEL_MESSAGE_FOLDER_FLAGGED; camel_filter_driver_log (driver, FILTER_LOG_ACTION, "Unset %s flag", argv[0]->value.string); } @@ -1150,8 +1150,8 @@ camel_filter_driver_filter_mbox (CamelFilterDriver *driver, const char *mbox, co goto fail; } - info = camel_message_info_new_from_header(NULL, ((CamelMimePart *)msg)->headers); - ((CamelMessageInfoBase *)info)->size = camel_mime_parser_tell(mp) - last; + info = camel_message_info_new_from_header(((CamelMimePart *)msg)->headers); + info->size = camel_mime_parser_tell(mp) - last; last = camel_mime_parser_tell(mp); status = camel_filter_driver_filter_message (driver, msg, info, NULL, NULL, source_url, original_source_url ? original_source_url : source_url, ex); @@ -1365,10 +1365,10 @@ camel_filter_driver_filter_message (CamelFilterDriver *driver, CamelMimeMessage } h = CAMEL_MIME_PART (message)->headers; - info = camel_message_info_new_from_header (NULL, h); + info = camel_message_info_new_from_header (h); freeinfo = TRUE; } else { - if (camel_message_info_flags(info) & CAMEL_MESSAGE_DELETED) + if (info->flags & CAMEL_MESSAGE_DELETED) return 0; uid = camel_message_info_uid (info); @@ -1443,7 +1443,7 @@ camel_filter_driver_filter_message (CamelFilterDriver *driver, CamelMimeMessage if (p->source && p->uid && camel_folder_has_summary_capability (p->source)) camel_folder_set_message_flags(p->source, p->uid, CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_SEEN, ~0); else - camel_message_info_set_flags(info, CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_FOLDER_FLAGGED, ~0); + info->flags |= CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_FOLDER_FLAGGED; } /* Logic: if !Moved and there exists a default folder... */ diff --git a/camel/camel-filter-search.c b/camel/camel-filter-search.c index 2e35cb5e0d..9999b0ad2c 100644 --- a/camel/camel-filter-search.c +++ b/camel/camel-filter-search.c @@ -42,8 +42,9 @@ #include <signal.h> #include <sys/wait.h> -#include <libedataserver/e-sexp.h> -#include <libedataserver/e-iconv.h> +#include <e-util/e-sexp.h> + +#include <gal/util/e-iconv.h> #include "camel-mime-message.h" #include "camel-provider.h" @@ -54,7 +55,7 @@ #include "camel-stream-mem.h" #include "camel-stream-fs.h" #include "camel-search-private.h" -#include "camel-i18n.h" + #include "camel-url.h" #define d(x) @@ -364,7 +365,7 @@ user_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessage /* performs an OR of all words */ for (i = 0; i < argc && !truth; i++) { if (argv[i]->type == ESEXP_RES_STRING - && camel_message_info_user_flag(fms->info, argv[i]->value.string)) { + && camel_flag_get (&fms->info->user_flags, argv[i]->value.string)) { truth = TRUE; break; } @@ -385,7 +386,7 @@ system_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessa e_sexp_fatal_error(f, _("Invalid arguments to (system-flag)")); r = e_sexp_result_new (f, ESEXP_RES_BOOL); - r->value.bool = camel_system_flag_get (camel_message_info_flags(fms->info), argv[0]->value.string); + r->value.bool = camel_system_flag_get (fms->info->flags, argv[0]->value.string); return r; } @@ -399,7 +400,7 @@ user_tag (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageS if (argc != 1 || argv[0]->type != ESEXP_RES_STRING) e_sexp_fatal_error(f, _("Invalid arguments to (user-tag)")); - tag = camel_message_info_user_tag(fms->info, argv[0]->value.string); + tag = camel_tag_get (&fms->info->user_tags, argv[0]->value.string); r = e_sexp_result_new (f, ESEXP_RES_STRING); r->value.string = g_strdup (tag ? tag : ""); @@ -490,7 +491,7 @@ get_size (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageS ESExpResult *r; r = e_sexp_result_new(f, ESEXP_RES_INT); - r->value.number = camel_message_info_size(fms->info) / 1024; + r->value.number = fms->info->size / 1024; return r; } diff --git a/camel/camel-folder-search.c b/camel/camel-folder-search.c index 51597ee0c7..db7e6076fe 100644 --- a/camel/camel-folder-search.c +++ b/camel/camel-folder-search.c @@ -35,8 +35,6 @@ #include <glib.h> -#include "libedataserver/e-memory.h" - #include "camel-folder-search.h" #include "camel-folder-thread.h" @@ -45,8 +43,8 @@ #include "camel-multipart.h" #include "camel-mime-message.h" #include "camel-stream-mem.h" +#include "e-util/e-memory.h" #include "camel-search-private.h" -#include "camel-i18n.h" #define d(x) #define r(x) @@ -862,7 +860,7 @@ check_header(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolder header = camel_message_info_subject(search->current); } else if (!strcasecmp(headername, "date")) { /* FIXME: not a very useful form of the date */ - sprintf(strbuf, "%d", (int)camel_message_info_date_sent(search->current)); + sprintf(strbuf, "%d", (int)search->current->date_sent); header = strbuf; } else if (!strcasecmp(headername, "from")) { header = camel_message_info_from(search->current); @@ -1248,7 +1246,7 @@ search_user_flag(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFo /* performs an OR of all words */ for (i=0;i<argc && !truth;i++) { if (argv[i]->type == ESEXP_RES_STRING - && camel_message_info_user_flag(search->current, argv[i]->value.string)) { + && camel_flag_get(&search->current->user_flags, argv[i]->value.string)) { truth = TRUE; break; } @@ -1274,7 +1272,7 @@ search_system_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, Came gboolean truth = FALSE; if (argc == 1) - truth = camel_system_flag_get (camel_message_info_flags(search->current), argv[0]->value.string); + truth = camel_system_flag_get (search->current->flags, argv[0]->value.string); r = e_sexp_result_new(f, ESEXP_RES_BOOL); r->value.bool = truth; @@ -1295,7 +1293,7 @@ search_user_tag(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFol r(printf("executing user-tag\n")); if (argc == 1) - value = camel_message_info_user_tag(search->current, argv[0]->value.string); + value = camel_tag_get (&search->current->user_tags, argv[0]->value.string); r = e_sexp_result_new(f, ESEXP_RES_STRING); r->value.string = g_strdup (value ? value : ""); @@ -1314,7 +1312,7 @@ search_get_sent_date(struct _ESExp *f, int argc, struct _ESExpResult **argv, Cam if (s->current) { r = e_sexp_result_new(f, ESEXP_RES_INT); - r->value.number = camel_message_info_date_sent(s->current); + r->value.number = s->current->date_sent; } else { r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR); r->value.ptrarray = g_ptr_array_new (); @@ -1334,7 +1332,7 @@ search_get_received_date(struct _ESExp *f, int argc, struct _ESExpResult **argv, if (s->current) { r = e_sexp_result_new(f, ESEXP_RES_INT); - r->value.number = camel_message_info_date_received(s->current); + r->value.number = s->current->date_received; } else { r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR); r->value.ptrarray = g_ptr_array_new (); @@ -1365,7 +1363,7 @@ search_get_size (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFo /* are we inside a match-all? */ if (s->current) { r = e_sexp_result_new (f, ESEXP_RES_INT); - r->value.number = camel_message_info_size(s->current) / 1024; + r->value.number = s->current->size / 1024; } else { r = e_sexp_result_new (f, ESEXP_RES_ARRAY_PTR); r->value.ptrarray = g_ptr_array_new (); diff --git a/camel/camel-folder-summary.c b/camel/camel-folder-summary.c index d4d99b7cfe..bf58f4a47e 100644 --- a/camel/camel-folder-summary.c +++ b/camel/camel-folder-summary.c @@ -33,13 +33,10 @@ #include <errno.h> #include <ctype.h> -#include <libedataserver/e-iconv.h> +#include <gal/util/e-iconv.h> #include "camel-folder-summary.h" -/* for change events, perhaps we should just do them ourselves */ -#include "camel-folder.h" - #include <camel/camel-file-utils.h> #include <camel/camel-mime-filter.h> #include <camel/camel-mime-filter-index.h> @@ -55,8 +52,8 @@ #include <camel/camel-string-utils.h> -#include "libedataserver/md5-utils.h" -#include "libedataserver/e-memory.h" +#include "e-util/md5-utils.h" +#include "e-util/e-memory.h" #include "camel-private.h" @@ -93,14 +90,14 @@ static int my_list_size(struct _node **list); static int summary_header_load(CamelFolderSummary *, FILE *); static int summary_header_save(CamelFolderSummary *, FILE *); -static CamelMessageInfo * message_info_new_from_header(CamelFolderSummary *, struct _camel_header_raw *); +static CamelMessageInfo * message_info_new(CamelFolderSummary *, struct _camel_header_raw *); static CamelMessageInfo * message_info_new_from_parser(CamelFolderSummary *, CamelMimeParser *); static CamelMessageInfo * message_info_new_from_message(CamelFolderSummary *s, CamelMimeMessage *msg); static CamelMessageInfo * message_info_load(CamelFolderSummary *, FILE *); static int message_info_save(CamelFolderSummary *, FILE *, CamelMessageInfo *); static void message_info_free(CamelFolderSummary *, CamelMessageInfo *); -static CamelMessageContentInfo * content_info_new_from_header(CamelFolderSummary *, struct _camel_header_raw *); +static CamelMessageContentInfo * content_info_new(CamelFolderSummary *, struct _camel_header_raw *); static CamelMessageContentInfo * content_info_new_from_parser(CamelFolderSummary *, CamelMimeParser *); static CamelMessageContentInfo * content_info_new_from_message(CamelFolderSummary *s, CamelMimePart *mp); static CamelMessageContentInfo * content_info_load(CamelFolderSummary *, FILE *); @@ -119,6 +116,31 @@ static void camel_folder_summary_finalize (CamelObject *obj); static CamelObjectClass *camel_folder_summary_parent; static void +camel_folder_summary_class_init (CamelFolderSummaryClass *klass) +{ + camel_folder_summary_parent = camel_type_get_global_classfuncs (camel_object_get_type ()); + + klass->summary_header_load = summary_header_load; + klass->summary_header_save = summary_header_save; + + klass->message_info_new = message_info_new; + klass->message_info_new_from_parser = message_info_new_from_parser; + klass->message_info_new_from_message = message_info_new_from_message; + klass->message_info_load = message_info_load; + klass->message_info_save = message_info_save; + klass->message_info_free = message_info_free; + + klass->content_info_new = content_info_new; + klass->content_info_new_from_parser = content_info_new_from_parser; + klass->content_info_new_from_message = content_info_new_from_message; + klass->content_info_load = content_info_load; + klass->content_info_save = content_info_save; + klass->content_info_free = content_info_free; + + klass->next_uid_string = next_uid_string; +} + +static void camel_folder_summary_init (CamelFolderSummary *s) { struct _CamelFolderSummaryPrivate *p; @@ -127,7 +149,7 @@ camel_folder_summary_init (CamelFolderSummary *s) p->filter_charset = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); - s->message_info_size = sizeof(CamelMessageInfoBase); + s->message_info_size = sizeof(CamelMessageInfo); s->content_info_size = sizeof(CamelMessageContentInfo); s->message_info_chunks = NULL; @@ -227,22 +249,18 @@ camel_folder_summary_get_type (void) /** * camel_folder_summary_new: - * @folder: Parent folder. It will hold a ref to us, not the other way around. * * Create a new CamelFolderSummary object. * * Return value: A new CamelFolderSummary widget. **/ CamelFolderSummary * -camel_folder_summary_new (struct _CamelFolder *folder) +camel_folder_summary_new (void) { - CamelFolderSummary *new = CAMEL_FOLDER_SUMMARY ( camel_object_new (camel_folder_summary_get_type ())); - - new->folder = folder; - - return new; + CamelFolderSummary *new = CAMEL_FOLDER_SUMMARY ( camel_object_new (camel_folder_summary_get_type ())); return new; } + /** * camel_folder_summary_set_filename: * @s: @@ -322,6 +340,7 @@ camel_folder_summary_count(CamelFolderSummary *s) * * Return value: The summary item, or NULL if the index @i is out * of range. + * It must be freed using camel_folder_summary_info_free(). **/ CamelMessageInfo * camel_folder_summary_index(CamelFolderSummary *s, int i) @@ -387,9 +406,8 @@ camel_folder_summary_array_free(CamelFolderSummary *s, GPtrArray *array) { int i; - /* FIXME: do the locking around the whole lot to make it faster */ for (i=0;i<array->len;i++) - camel_message_info_free(array->pdata[i]); + camel_folder_summary_info_free(s, array->pdata[i]); g_ptr_array_free(array, TRUE); } @@ -406,6 +424,7 @@ camel_folder_summary_array_free(CamelFolderSummary *s, GPtrArray *array) * * Return value: The summary item, or NULL if the uid @uid * is not available. + * It must be freed using camel_folder_summary_info_free(). **/ CamelMessageInfo * camel_folder_summary_uid(CamelFolderSummary *s, const char *uid) @@ -541,11 +560,10 @@ camel_folder_summary_load(CamelFolderSummary *s) if (mi == NULL) goto error; - /* FIXME: this should be done differently, how i don't know */ if (s->build_content) { - ((CamelMessageInfoBase *)mi)->content = perform_content_info_load(s, in); - if (((CamelMessageInfoBase *)mi)->content == NULL) { - camel_message_info_free(mi); + mi->content = perform_content_info_load(s, in); + if (mi->content == NULL) { + camel_folder_summary_info_free(s, mi); goto error; } } @@ -613,8 +631,6 @@ camel_folder_summary_save(CamelFolderSummary *s) CamelMessageInfo *mi; char *path; - g_assert(s->message_info_size >= sizeof(CamelMessageInfoBase)); - if (s->summary_path == NULL || (s->flags & CAMEL_SUMMARY_DIRTY) == 0) return 0; @@ -649,7 +665,7 @@ camel_folder_summary_save(CamelFolderSummary *s) goto exception; if (s->build_content) { - if (perform_content_info_save (s, out, ((CamelMessageInfoBase *)mi)->content) == -1) + if (perform_content_info_save (s, out, mi->content) == -1) goto exception; } } @@ -724,8 +740,8 @@ summary_assign_uid(CamelFolderSummary *s, CamelMessageInfo *info) uid = camel_message_info_uid(info); if (uid == NULL || uid[0] == 0) { - g_free(info->uid); - uid = info->uid = camel_folder_summary_next_uid_string(s); + camel_message_info_set_uid(info, camel_folder_summary_next_uid_string(s)); + uid = camel_message_info_uid(info); } CAMEL_SUMMARY_LOCK(s, summary_lock); @@ -735,14 +751,13 @@ summary_assign_uid(CamelFolderSummary *s, CamelMessageInfo *info) if (mi == info) return 0; d(printf ("Trying to insert message with clashing uid (%s). new uid re-assigned", camel_message_info_uid(info))); - g_free(info->uid); - uid = info->uid = camel_folder_summary_next_uid_string(s); - camel_message_info_set_flags(info, CAMEL_MESSAGE_FOLDER_FLAGGED, CAMEL_MESSAGE_FOLDER_FLAGGED); + camel_message_info_set_uid(info, camel_folder_summary_next_uid_string(s)); + uid = camel_message_info_uid(info); + info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED; CAMEL_SUMMARY_LOCK(s, summary_lock); } CAMEL_SUMMARY_UNLOCK(s, summary_lock); - return 1; } @@ -851,11 +866,12 @@ CamelMessageInfo *camel_folder_summary_add_from_message(CamelFolderSummary *s, C * * Create a new info record from a header. * - * Return value: Guess? Free using camel_message_info_free(). + * Return value: Guess? This info record MUST be freed using + * camel_folder_summary_info_free(), camel_message_info_free() will not work. **/ CamelMessageInfo *camel_folder_summary_info_new_from_header(CamelFolderSummary *s, struct _camel_header_raw *h) { - return ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s))) -> message_info_new_from_header(s, h); + return ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s))) -> message_info_new(s, h); } /** @@ -876,7 +892,8 @@ CamelMessageInfo *camel_folder_summary_info_new_from_header(CamelFolderSummary * * Once complete, the parser will be positioned at the end of * the message. * - * Return value: Guess? + * Return value: Guess? This info record MUST be freed using + * camel_folder_summary_info_free(), camel_message_info_free() will not work. **/ CamelMessageInfo *camel_folder_summary_info_new_from_parser(CamelFolderSummary *s, CamelMimeParser *mp) { @@ -911,7 +928,7 @@ CamelMessageInfo *camel_folder_summary_info_new_from_parser(CamelFolderSummary * } /* always scan the content info, even if we dont save it */ - ((CamelMessageInfoBase *)info)->content = summary_build_content_info(s, info, mp); + info->content = summary_build_content_info(s, info, mp); if (name) { camel_index_write_name(p->index, name); @@ -921,7 +938,7 @@ CamelMessageInfo *camel_folder_summary_info_new_from_parser(CamelFolderSummary * CAMEL_SUMMARY_UNLOCK(s, filter_lock); - ((CamelMessageInfoBase *)info)->size = camel_mime_parser_tell(mp) - start; + info->size = camel_mime_parser_tell(mp) - start; } return info; } @@ -965,7 +982,7 @@ CamelMessageInfo *camel_folder_summary_info_new_from_message(CamelFolderSummary } } - ((CamelMessageInfoBase *)info)->content = summary_build_content_info_message(s, info, (CamelMimePart *)msg); + info->content = summary_build_content_info_message(s, info, (CamelMimePart *)msg); if (name) { camel_index_write_name(p->index, name); @@ -1000,6 +1017,58 @@ camel_folder_summary_content_info_free(CamelFolderSummary *s, CamelMessageConten } /** + * camel_folder_summary_info_free: + * @s: + * @mi: + * + * Unref and potentially free the message info @mi, and all associated memory. + **/ +void camel_folder_summary_info_free(CamelFolderSummary *s, CamelMessageInfo *mi) +{ + CamelMessageContentInfo *ci; + + g_assert(mi); + g_assert(s); + + CAMEL_SUMMARY_LOCK(s, ref_lock); + + g_assert(mi->refcount >= 1); + + mi->refcount--; + if (mi->refcount > 0) { + CAMEL_SUMMARY_UNLOCK(s, ref_lock); + return; + } + + CAMEL_SUMMARY_UNLOCK(s, ref_lock); + + ci = mi->content; + + ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_free(s, mi); + if (s->build_content && ci) { + camel_folder_summary_content_info_free(s, ci); + } +} + +/** + * camel_folder_summary_info_ref: + * @s: + * @mi: + * + * Add an extra reference to @mi. + **/ +void camel_folder_summary_info_ref(CamelFolderSummary *s, CamelMessageInfo *mi) +{ + g_assert(mi); + g_assert(s); + + CAMEL_SUMMARY_LOCK(s, ref_lock); + g_assert(mi->refcount >= 1); + mi->refcount++; + CAMEL_SUMMARY_UNLOCK(s, ref_lock); +} + +/** * camel_folder_summary_touch: * @s: * @@ -1031,7 +1100,7 @@ camel_folder_summary_clear(CamelFolderSummary *s) } for (i=0;i<s->messages->len;i++) - camel_message_info_free(s->messages->pdata[i]); + camel_folder_summary_info_free(s, s->messages->pdata[i]); g_ptr_array_set_size(s->messages, 0); g_hash_table_destroy(s->messages_uid); @@ -1055,7 +1124,7 @@ void camel_folder_summary_remove(CamelFolderSummary *s, CamelMessageInfo *info) s->flags |= CAMEL_SUMMARY_DIRTY; CAMEL_SUMMARY_UNLOCK(s, summary_lock); - camel_message_info_free(info); + camel_folder_summary_info_free(s, info); } /** @@ -1078,7 +1147,7 @@ void camel_folder_summary_remove_uid(CamelFolderSummary *s, const char *uid) CAMEL_SUMMARY_UNLOCK(s, ref_lock); CAMEL_SUMMARY_UNLOCK(s, summary_lock); camel_folder_summary_remove(s, oldinfo); - camel_message_info_free(oldinfo); + camel_folder_summary_info_free(s, oldinfo); } else { CAMEL_SUMMARY_UNLOCK(s, ref_lock); CAMEL_SUMMARY_UNLOCK(s, summary_lock); @@ -1103,7 +1172,7 @@ void camel_folder_summary_remove_index(CamelFolderSummary *s, int index) s->flags |= CAMEL_SUMMARY_DIRTY; CAMEL_SUMMARY_UNLOCK(s, summary_lock); - camel_message_info_free(info); + camel_folder_summary_info_free(s, info); } else { CAMEL_SUMMARY_UNLOCK(s, summary_lock); } @@ -1144,7 +1213,7 @@ void camel_folder_summary_remove_range(CamelFolderSummary *s, int start, int end CAMEL_SUMMARY_UNLOCK(s, summary_lock); for (i=start;i<end;i++) - camel_message_info_free(infos[i-start]); + camel_folder_summary_info_free(s, infos[i-start]); g_free(infos); } else { CAMEL_SUMMARY_UNLOCK(s, summary_lock); @@ -1390,20 +1459,18 @@ summary_header_save(CamelFolderSummary *s, FILE *out) count = camel_folder_summary_count(s); for (i=0; i<count; i++) { CamelMessageInfo *info = camel_folder_summary_index(s, i); - guint32 flags; if (info == NULL) continue; - flags = camel_message_info_flags(info); - if ((flags & CAMEL_MESSAGE_SEEN) == 0) + if ((info->flags & CAMEL_MESSAGE_SEEN) == 0) unread++; - if ((flags & CAMEL_MESSAGE_DELETED) != 0) + if ((info->flags & CAMEL_MESSAGE_DELETED) != 0) deleted++; - if ((flags & CAMEL_MESSAGE_JUNK) != 0) + if ((info->flags & CAMEL_MESSAGE_JUNK) != 0) junk++; - camel_message_info_free(info); + camel_folder_summary_info_free(s, info); } camel_file_util_encode_fixed_int32(out, count); @@ -1424,7 +1491,7 @@ static CamelMessageInfo * message_info_new_from_parser(CamelFolderSummary *s, Ca case CAMEL_MIME_PARSER_STATE_HEADER: case CAMEL_MIME_PARSER_STATE_MESSAGE: case CAMEL_MIME_PARSER_STATE_MULTIPART: - mi = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_new_from_header(s, camel_mime_parser_headers_raw(mp)); + mi = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_new(s, camel_mime_parser_headers_raw(mp)); break; default: g_error("Invalid parser state"); @@ -1441,7 +1508,7 @@ static CamelMessageContentInfo * content_info_new_from_parser(CamelFolderSummary case CAMEL_MIME_PARSER_STATE_HEADER: case CAMEL_MIME_PARSER_STATE_MESSAGE: case CAMEL_MIME_PARSER_STATE_MULTIPART: - ci = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_new_from_header(s, camel_mime_parser_headers_raw(mp)); + ci = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_new(s, camel_mime_parser_headers_raw(mp)); if (ci) { ci->type = camel_mime_parser_content_type(mp); camel_content_type_ref(ci->type); @@ -1458,7 +1525,7 @@ static CamelMessageInfo * message_info_new_from_message(CamelFolderSummary *s, C { CamelMessageInfo *mi; - mi = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_new_from_header(s, ((CamelMimePart *)msg)->headers); + mi = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->message_info_new(s, ((CamelMimePart *)msg)->headers); return mi; } @@ -1467,7 +1534,7 @@ static CamelMessageContentInfo * content_info_new_from_message(CamelFolderSummar { CamelMessageContentInfo *ci; - ci = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_new_from_header(s, mp->headers); + ci = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->content_info_new(s, mp->headers); return ci; } @@ -1507,6 +1574,37 @@ summary_format_string (struct _camel_header_raw *h, const char *name, const char } /** + * camel_folder_summary_info_new: + * @s: + * + * Allocate a new camel message info, suitable for adding + * to this summary. + * + * Return value: + **/ +CamelMessageInfo * +camel_folder_summary_info_new(CamelFolderSummary *s) +{ + CamelMessageInfo *mi; + + CAMEL_SUMMARY_LOCK(s, alloc_lock); + if (s->message_info_chunks == NULL) + s->message_info_chunks = e_memchunk_new(32, s->message_info_size); + mi = e_memchunk_alloc(s->message_info_chunks); + CAMEL_SUMMARY_UNLOCK(s, alloc_lock); + + memset(mi, 0, s->message_info_size); +#ifdef DOEPOOLV + mi->strings = e_poolv_new (s->message_info_strings); +#endif +#ifdef DOESTRV + mi->strings = e_strv_new(s->message_info_strings); +#endif + mi->refcount = 1; + return mi; +} + +/** * camel_folder_summary_content_info_new: * @s: * @@ -1531,9 +1629,9 @@ camel_folder_summary_content_info_new(CamelFolderSummary *s) } static CamelMessageInfo * -message_info_new_from_header(CamelFolderSummary *s, struct _camel_header_raw *h) +message_info_new(CamelFolderSummary *s, struct _camel_header_raw *h) { - CamelMessageInfoBase *mi; + CamelMessageInfo *mi; const char *received; guchar digest[16]; struct _camel_header_references *refs, *irt, *scan; @@ -1543,7 +1641,7 @@ message_info_new_from_header(CamelFolderSummary *s, struct _camel_header_raw *h) CamelContentType *ct = NULL; const char *content, *charset = NULL; - mi = (CamelMessageInfoBase *)camel_message_info_new(s); + mi = camel_folder_summary_info_new(s); if ((content = camel_header_raw_find(&h, "Content-Type", NULL)) && (ct = camel_content_type_decode(content)) @@ -1562,17 +1660,25 @@ message_info_new_from_header(CamelFolderSummary *s, struct _camel_header_raw *h) if (ct) camel_content_type_unref(ct); - mi->subject = camel_pstring_strdup(subject); - mi->from = camel_pstring_strdup(from); - mi->to = camel_pstring_strdup(to); - mi->cc = camel_pstring_strdup(cc); - mi->mlist = camel_pstring_strdup(mlist); - - g_free(subject); - g_free(from); - g_free(to); - g_free(cc); - g_free(mlist); +#ifdef DOEPOOLV + e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_SUBJECT, subject, TRUE); + e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_FROM, from, TRUE); + e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_TO, to, TRUE); + e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_CC, cc, TRUE); + e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_MLIST, mlist, TRUE); +#elif defined (DOESTRV) + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_SUBJECT, subject); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_FROM, from); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_TO, to); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_CC, cc); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_MLIST, mlist); +#else + mi->subject = subject; + mi->from = from; + mi->to = to; + mi->cc = cc; + mi->mlist = mlist; +#endif mi->user_flags = NULL; mi->user_tags = NULL; @@ -1621,18 +1727,19 @@ message_info_new_from_header(CamelFolderSummary *s, struct _camel_header_raw *h) camel_header_references_list_clear(&refs); } - return (CamelMessageInfo *)mi; + return mi; } + static CamelMessageInfo * message_info_load(CamelFolderSummary *s, FILE *in) { - CamelMessageInfoBase *mi; + CamelMessageInfo *mi; guint count; int i; char *subject, *from, *to, *cc, *mlist, *uid;; - mi = (CamelMessageInfoBase *)camel_message_info_new(s); + mi = camel_folder_summary_info_new(s); io(printf("Loading message info\n")); @@ -1647,18 +1754,28 @@ message_info_load(CamelFolderSummary *s, FILE *in) camel_file_util_decode_string(in, &cc); camel_file_util_decode_string(in, &mlist); +#ifdef DOEPOOLV + e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_UID, uid, TRUE); + e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_SUBJECT, subject, TRUE); + e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_FROM, from, TRUE); + e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_TO, to, TRUE); + e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_CC, cc, TRUE); + e_poolv_set(mi->strings, CAMEL_MESSAGE_INFO_MLIST, mlist, TRUE); +#elif defined (DOESTRV) + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_UID, uid); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_SUBJECT, subject); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_FROM, from); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_TO, to); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_CC, cc); + e_strv_set_ref_free(mi->strings, CAMEL_MESSAGE_INFO_MLIST, mlist); +#else mi->uid = uid; - mi->subject = camel_pstring_strdup(subject); - mi->from = camel_pstring_strdup(from); - mi->to = camel_pstring_strdup(to); - mi->cc = camel_pstring_strdup(cc); - mi->mlist = camel_pstring_strdup(mlist); - - g_free(subject); - g_free(from); - g_free(to); - g_free(cc); - g_free(mlist); + mi->subject = subject; + mi->from = from; + mi->to = to; + mi->cc = cc; + mi->mlist = mlist; +#endif mi->content = NULL; @@ -1702,22 +1819,21 @@ message_info_load(CamelFolderSummary *s, FILE *in) } if (!ferror(in)) - return (CamelMessageInfo *)mi; + return mi; error: - camel_message_info_free((CamelMessageInfo *)mi); + camel_folder_summary_info_free(s, mi); return NULL; } static int -message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *info) +message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *mi) { guint32 count; CamelFlag *flag; CamelTag *tag; int i; - CamelMessageInfoBase *mi = (CamelMessageInfoBase *)info; io(printf("Saving message info\n")); @@ -1766,27 +1882,28 @@ message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *info) } static void -message_info_free(CamelFolderSummary *s, CamelMessageInfo *info) +message_info_free(CamelFolderSummary *s, CamelMessageInfo *mi) { - CamelMessageInfoBase *mi = (CamelMessageInfoBase *)info; - +#ifdef DOEPOOLV + e_poolv_destroy(mi->strings); +#elif defined (DOESTRV) + e_strv_destroy(mi->strings); +#else g_free(mi->uid); - camel_pstring_free(mi->subject); - camel_pstring_free(mi->from); - camel_pstring_free(mi->to); - camel_pstring_free(mi->cc); - camel_pstring_free(mi->mlist); + g_free(mi->subject); + g_free(mi->from); + g_free(mi->to); + g_free(mi->cc); + g_free(mi->mlist); +#endif g_free(mi->references); camel_flag_list_free(&mi->user_flags); camel_tag_list_free(&mi->user_tags); - if (s) - e_memchunk_free(s->message_info_chunks, mi); - else - g_free(mi); + e_memchunk_free(s->message_info_chunks, mi); } static CamelMessageContentInfo * -content_info_new_from_header(CamelFolderSummary *s, struct _camel_header_raw *h) +content_info_new (CamelFolderSummary *s, struct _camel_header_raw *h) { CamelMessageContentInfo *ci; const char *charset; @@ -1939,7 +2056,7 @@ summary_build_content_info(CamelFolderSummary *s, CamelMessageInfo *msginfo, Cam || camel_content_type_is(ct, "application", "pkcs7-signature") #endif ) - camel_message_info_set_flags(msginfo, CAMEL_MESSAGE_SECURE, CAMEL_MESSAGE_SECURE); + msginfo->flags |= CAMEL_MESSAGE_SECURE; if (p->index && camel_content_type_is(ct, "text", "*")) { char *encoding; @@ -1949,7 +2066,7 @@ summary_build_content_info(CamelFolderSummary *s, CamelMessageInfo *msginfo, Cam encoding = camel_content_transfer_encoding_decode(camel_mime_parser_header(mp, "content-transfer-encoding", NULL)); if (encoding) { - if (!g_ascii_strcasecmp(encoding, "base64")) { + if (!strcasecmp(encoding, "base64")) { d(printf(" decoding base64\n")); if (p->filter_64 == NULL) p->filter_64 = camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_BASE64_DEC); @@ -1963,7 +2080,7 @@ summary_build_content_info(CamelFolderSummary *s, CamelMessageInfo *msginfo, Cam else camel_mime_filter_reset((CamelMimeFilter *)p->filter_qp); enc_id = camel_mime_parser_filter_add(mp, (CamelMimeFilter *)p->filter_qp); - } else if (!g_ascii_strcasecmp (encoding, "x-uuencode")) { + } else if (!strcasecmp (encoding, "x-uuencode")) { d(printf(" decoding x-uuencode\n")); if (p->filter_uu == NULL) p->filter_uu = camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_UU_DEC); @@ -1979,7 +2096,7 @@ summary_build_content_info(CamelFolderSummary *s, CamelMessageInfo *msginfo, Cam charset = camel_content_type_param(ct, "charset"); if (charset!=NULL && !(g_ascii_strcasecmp(charset, "us-ascii")==0 - || g_ascii_strcasecmp(charset, "utf-8")==0)) { + || strcasecmp(charset, "utf-8")==0)) { d(printf(" Adding conversion filter from %s to UTF-8\n", charset)); mfc = g_hash_table_lookup(p->filter_charset, charset); if (mfc == NULL) { @@ -2023,10 +2140,10 @@ summary_build_content_info(CamelFolderSummary *s, CamelMessageInfo *msginfo, Cam /* update attachments flag as we go */ ct = camel_mime_parser_content_type(mp); if (camel_content_type_is(ct, "multipart", "mixed")) - camel_message_info_set_flags(msginfo, CAMEL_MESSAGE_ATTACHMENTS, CAMEL_MESSAGE_ATTACHMENTS); + msginfo->flags |= CAMEL_MESSAGE_ATTACHMENTS; if (camel_content_type_is(ct, "multipart", "signed") || camel_content_type_is(ct, "multipart", "encrypted")) - camel_message_info_set_flags(msginfo, CAMEL_MESSAGE_SECURE, CAMEL_MESSAGE_SECURE); + msginfo->flags |= CAMEL_MESSAGE_SECURE; while (camel_mime_parser_step(mp, &buffer, &len) != CAMEL_MIME_PARSER_STATE_MULTIPART_END) { camel_mime_parser_unstep(mp); @@ -2040,7 +2157,7 @@ summary_build_content_info(CamelFolderSummary *s, CamelMessageInfo *msginfo, Cam case CAMEL_MIME_PARSER_STATE_MESSAGE: d(printf("Summarising message\n")); /* update attachments flag as we go */ - camel_message_info_set_flags(msginfo, CAMEL_MESSAGE_ATTACHMENTS, CAMEL_MESSAGE_ATTACHMENTS); + msginfo->flags |= CAMEL_MESSAGE_ATTACHMENTS; part = summary_build_content_info(s, msginfo, mp); if (part) { @@ -2086,17 +2203,17 @@ summary_build_content_info_message(CamelFolderSummary *s, CamelMessageInfo *msgi ct = ((CamelDataWrapper *)containee)->mime_type; if (camel_content_type_is(ct, "multipart", "*")) { if (camel_content_type_is(ct, "multipart", "mixed")) - camel_message_info_set_flags(msginfo, CAMEL_MESSAGE_ATTACHMENTS, CAMEL_MESSAGE_ATTACHMENTS); + msginfo->flags |= CAMEL_MESSAGE_ATTACHMENTS; if (camel_content_type_is(ct, "multipart", "signed") || camel_content_type_is(ct, "multipart", "encrypted")) - camel_message_info_set_flags(msginfo, CAMEL_MESSAGE_SECURE, CAMEL_MESSAGE_SECURE); + msginfo->flags |= CAMEL_MESSAGE_SECURE; } else if (camel_content_type_is(ct, "application", "pgp-signature") #ifdef ENABLE_SMIME || camel_content_type_is(ct, "application", "x-pkcs7-signature") || camel_content_type_is(ct, "application", "pkcs7-signature") #endif ) { - camel_message_info_set_flags(msginfo, CAMEL_MESSAGE_SECURE, CAMEL_MESSAGE_SECURE); + msginfo->flags |= CAMEL_MESSAGE_SECURE; } /* using the object types is more accurate than using the mime/types */ @@ -2490,23 +2607,19 @@ camel_system_flag_get (guint32 flags, const char *name) * * Returns a new CamelMessageInfo structure. **/ -void * -camel_message_info_new (CamelFolderSummary *s) +CamelMessageInfo * +camel_message_info_new (void) { CamelMessageInfo *info; - - if (s) { - CAMEL_SUMMARY_LOCK(s, alloc_lock); - if (s->message_info_chunks == NULL) - s->message_info_chunks = e_memchunk_new(32, s->message_info_size); - info = e_memchunk_alloc0(s->message_info_chunks); - CAMEL_SUMMARY_UNLOCK(s, alloc_lock); - } else { - info = g_malloc0(sizeof(CamelMessageInfoBase)); - } - + + info = g_malloc0(sizeof(*info)); +#ifdef DOEPOOLV + info->strings = e_poolv_new(CAMEL_MESSAGE_INFO_LAST); +#endif +#ifdef DOESTRV + info->strings = e_strv_new (CAMEL_MESSAGE_INFO_LAST); +#endif info->refcount = 1; - info->summary = s; return info; } @@ -2516,22 +2629,14 @@ camel_message_info_new (CamelFolderSummary *s) * @info: * * Reference an info. + * + * NOTE: This interface is not MT-SAFE, like the others. **/ -void camel_message_info_ref(void *o) +void camel_message_info_ref(CamelMessageInfo *info) { - CamelMessageInfo *mi = o; - - if (mi->summary) { - CAMEL_SUMMARY_LOCK(mi->summary, ref_lock); - g_assert(mi->refcount >= 1); - mi->refcount++; - CAMEL_SUMMARY_UNLOCK(mi->summary, ref_lock); - } else { - GLOBAL_INFO_LOCK(info); - g_assert(mi->refcount >= 1); - mi->refcount++; - GLOBAL_INFO_UNLOCK(info); - } + GLOBAL_INFO_LOCK(info); + info->refcount++; + GLOBAL_INFO_UNLOCK(info); } /** @@ -2541,89 +2646,108 @@ void camel_message_info_ref(void *o) * Returns a new CamelMessageInfo structure populated by the header. **/ CamelMessageInfo * -camel_message_info_new_from_header(CamelFolderSummary *s, struct _camel_header_raw *header) +camel_message_info_new_from_header (struct _camel_header_raw *header) { - if (s) - return ((CamelFolderSummaryClass *)((CamelObject *)s)->klass)->message_info_new_from_header(s, header); + CamelMessageInfo *info; + char *subject, *from, *to, *cc, *mlist; + CamelContentType *ct = NULL; + const char *content, *date, *charset = NULL; + + if ((content = camel_header_raw_find(&header, "Content-Type", NULL)) + && (ct = camel_content_type_decode(content)) + && (charset = camel_content_type_param(ct, "charset")) + && (g_ascii_strcasecmp(charset, "us-ascii") == 0)) + charset = NULL; + + charset = charset ? e_iconv_charset_name (charset) : NULL; + + subject = summary_format_string(header, "subject", charset); + from = summary_format_address(header, "from", charset); + to = summary_format_address(header, "to", charset); + cc = summary_format_address(header, "cc", charset); + date = camel_header_raw_find(&header, "date", NULL); + mlist = camel_header_raw_check_mailing_list(&header); + + if (ct) + camel_content_type_unref(ct); + + info = camel_message_info_new(); + + camel_message_info_set_subject(info, subject); + camel_message_info_set_from(info, from); + camel_message_info_set_to(info, to); + camel_message_info_set_cc(info, cc); + camel_message_info_set_mlist(info, mlist); + + if (date) + info->date_sent = camel_header_decode_date (date, NULL); + else + info->date_sent = time (NULL); + + date = camel_header_raw_find (&header, "received", NULL); + if (date && (date = strrchr (date, ';'))) + date++; + + if (date) + info->date_received = camel_header_decode_date (date, NULL); else - return message_info_new_from_header(NULL, header); + info->date_received = time (NULL); + + return info; } /** - * camel_message_info_free: - * @mi: the message info - * - * Unref's and potentially frees a CamelMessageInfo and its contents. + * camel_message_info_dup_to: + * @from: source message info + * @to: destination message info * + * Duplicates the contents of one CamelMessageInfo structure into another. + * (The destination is assumed to be empty: its contents are not freed.) + * The slightly odd interface is to allow this to be used to initialize + * "subclasses" of CamelMessageInfo. **/ void -camel_message_info_free(void *o) -{ - CamelMessageInfo *mi = o; - - g_return_if_fail(mi != NULL); - - if (mi->summary) { - CAMEL_SUMMARY_LOCK(mi->summary, ref_lock); - - g_assert(mi->refcount >= 1); - mi->refcount--; - if (mi->refcount > 0) { - CAMEL_SUMMARY_UNLOCK(mi->summary, ref_lock); - return; - } - - CAMEL_SUMMARY_UNLOCK(mi->summary, ref_lock); - - /* FIXME: this is kinda busted, should really be handled by message info free */ - if (mi->summary->build_content - && ((CamelMessageInfoBase *)mi)->content) { - camel_folder_summary_content_info_free(mi->summary, ((CamelMessageInfoBase *)mi)->content); - } - - ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(mi->summary)))->message_info_free(mi->summary, mi); - } else { - GLOBAL_INFO_LOCK(info); - mi->refcount--; - if (mi->refcount > 0) { - GLOBAL_INFO_UNLOCK(info); - return; - } - GLOBAL_INFO_UNLOCK(info); - - message_info_free(NULL, mi); - } -} - -static CamelMessageInfo * -message_info_clone(CamelFolderSummary *s, const CamelMessageInfo *mi) +camel_message_info_dup_to(const CamelMessageInfo *from, CamelMessageInfo *to) { - CamelMessageInfoBase *to, *from = (CamelMessageInfoBase *)mi; CamelFlag *flag; CamelTag *tag; - to = (CamelMessageInfoBase *)camel_message_info_new(s); - + /* Copy numbers */ to->flags = from->flags; to->size = from->size; to->date_sent = from->date_sent; to->date_received = from->date_received; to->refcount = 1; - /* NB: We don't clone the uid */ - - to->subject = camel_pstring_strdup(from->subject); - to->from = camel_pstring_strdup(from->from); - to->to = camel_pstring_strdup(from->to); - to->cc = camel_pstring_strdup(from->cc); - to->mlist = camel_pstring_strdup(from->mlist); - memcpy(&to->message_id, &from->message_id, sizeof(to->message_id)); + /* Copy strings */ +#ifdef DOEPOOLV + to->strings = e_poolv_cpy (to->strings, from->strings); +#elif defined (DOESTRV) + /* to->strings = e_strv_new(CAMEL_MESSAGE_INFO_LAST); */ + e_strv_set(to->strings, CAMEL_MESSAGE_INFO_SUBJECT, camel_message_info_subject(from)); + e_strv_set(to->strings, CAMEL_MESSAGE_INFO_FROM, camel_message_info_from(from)); + e_strv_set(to->strings, CAMEL_MESSAGE_INFO_TO, camel_message_info_to(from)); + e_strv_set(to->strings, CAMEL_MESSAGE_INFO_CC, camel_message_info_cc(from)); + e_strv_set(to->strings, CAMEL_MESSAGE_INFO_UID, camel_message_info_uid(from)); + e_strv_set(to->strings, CAMEL_MESSAGE_INFO_UID, camel_message_info_mlist(from)); +#else + to->subject = g_strdup(from->subject); + to->from = g_strdup(from->from); + to->to = g_strdup(from->to); + to->cc = g_strdup(from->cc); + to->uid = g_strdup(from->uid); + to->mlist = g_strdup(from->mlist); +#endif + memcpy(&to->message_id, &from->message_id, sizeof(from->message_id)); + /* Copy structures */ if (from->references) { int len = sizeof(*from->references) + ((from->references->size-1) * sizeof(from->references->references[0])); to->references = g_malloc(len); memcpy(to->references, from->references, len); + } else { + to->references = NULL; } flag = from->user_flags; @@ -2638,226 +2762,83 @@ message_info_clone(CamelFolderSummary *s, const CamelMessageInfo *mi) tag = tag->next; } - if (from->content) { - /* FIXME: copy content-infos */ - } - - return (CamelMessageInfo *)to; -} - -void * -camel_message_info_clone(const void *o) -{ - const CamelMessageInfo *mi = o; - - if (mi->summary) - return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->message_info_clone(mi->summary, mi); - else - return message_info_clone(NULL, mi); -} - -static const void * -info_ptr(const CamelMessageInfo *mi, int id) -{ - switch (id) { - case CAMEL_MESSAGE_INFO_SUBJECT: - return ((const CamelMessageInfoBase *)mi)->subject; - case CAMEL_MESSAGE_INFO_FROM: - return ((const CamelMessageInfoBase *)mi)->from; - case CAMEL_MESSAGE_INFO_TO: - return ((const CamelMessageInfoBase *)mi)->to; - case CAMEL_MESSAGE_INFO_CC: - return ((const CamelMessageInfoBase *)mi)->cc; - case CAMEL_MESSAGE_INFO_MLIST: - return ((const CamelMessageInfoBase *)mi)->mlist; - case CAMEL_MESSAGE_INFO_MESSAGE_ID: - return &((const CamelMessageInfoBase *)mi)->message_id; - case CAMEL_MESSAGE_INFO_REFERENCES: - return ((const CamelMessageInfoBase *)mi)->references; - case CAMEL_MESSAGE_INFO_USER_FLAGS: - return ((const CamelMessageInfoBase *)mi)->user_flags; - case CAMEL_MESSAGE_INFO_USER_TAGS: - return ((const CamelMessageInfoBase *)mi)->user_tags; - default: - abort(); - } -} - -static guint32 -info_uint32(const CamelMessageInfo *mi, int id) -{ - switch (id) { - case CAMEL_MESSAGE_INFO_FLAGS: - return ((const CamelMessageInfoBase *)mi)->flags; - case CAMEL_MESSAGE_INFO_SIZE: - return ((const CamelMessageInfoBase *)mi)->size; - default: - abort(); - } -} - -static time_t -info_time(const CamelMessageInfo *mi, int id) -{ - switch (id) { - case CAMEL_MESSAGE_INFO_DATE_SENT: - return ((const CamelMessageInfoBase *)mi)->date_sent; - case CAMEL_MESSAGE_INFO_DATE_RECEIVED: - return ((const CamelMessageInfoBase *)mi)->date_received; - default: - abort(); - } -} - -static gboolean -info_user_flag(const CamelMessageInfo *mi, const char *id) -{ - return camel_flag_get(&((CamelMessageInfoBase *)mi)->user_flags, id); -} - -static const char * -info_user_tag(const CamelMessageInfo *mi, const char *id) -{ - return camel_tag_get(&((CamelMessageInfoBase *)mi)->user_tags, id); -} - -const void * -camel_message_info_ptr(const CamelMessageInfo *mi, int id) -{ - if (mi->summary) - return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_ptr(mi, id); - else - return info_ptr(mi, id); -} - -guint32 camel_message_info_uint32(const CamelMessageInfo *mi, int id) -{ - if (mi->summary) - return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_uint32(mi, id); - else - return info_uint32(mi, id); -} - -time_t camel_message_info_time(const CamelMessageInfo *mi, int id) -{ - if (mi->summary) - return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_time(mi, id); - else - return info_time(mi, id); -} - -gboolean camel_message_info_user_flag(const CamelMessageInfo *mi, const char *id) -{ - if (mi->summary) - return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_user_flag(mi, id); - else - return info_user_flag(mi, id); -} - -const char *camel_message_info_user_tag(const CamelMessageInfo *mi, const char *id) -{ - if (mi->summary) - return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_user_tag(mi, id); - else - return info_user_tag(mi, id); -} - -static gboolean -info_set_flags(CamelMessageInfo *info, guint32 flags, guint32 set) -{ - guint32 old; - CamelMessageInfoBase *mi = (CamelMessageInfoBase *)info; - - /* TODO: locking? */ - - old = mi->flags; - mi->flags = (old & ~flags) | (set & flags); - if (old != mi->flags) { - mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED; - if (mi->summary) - camel_folder_summary_touch(mi->summary); - } - - if ((old & ~CAMEL_MESSAGE_SYSTEM_MASK) == (mi->flags & ~CAMEL_MESSAGE_SYSTEM_MASK)) - return FALSE; - - if (mi->summary && mi->summary->folder && mi->uid) { - CamelFolderChangeInfo *changes = camel_folder_change_info_new(); - - camel_folder_change_info_change_uid(changes, camel_message_info_uid(info)); - camel_object_trigger_event(mi->summary->folder, "folder_changed", changes); - camel_folder_change_info_free(changes); - } - - return TRUE; -} - -gboolean camel_message_info_set_flags(CamelMessageInfo *mi, guint32 flags, guint32 set) -{ - if (mi->summary) - return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_set_flags(mi, flags, set); - else - return info_set_flags(mi, flags, set); + /* No, this is impossible without knowing the class of summary we came from */ + /* FIXME some day */ + to->content = NULL; } -static gboolean -info_set_user_flag(CamelMessageInfo *info, const char *name, gboolean value) +/** + * camel_message_info_free: + * @mi: the message info + * + * Unref's and potentially frees a CamelMessageInfo and its contents. + * + * Can only be used to free CamelMessageInfo's created with + * camel_message_info_dup_to. + * + * NOTE: This interface is not MT-SAFE, like the others. + * + **/ +void +camel_message_info_free(CamelMessageInfo *mi) { - CamelMessageInfoBase *mi = (CamelMessageInfoBase *)info; - int res; - - res = camel_flag_set(&mi->user_flags, name, value); - - /* TODO: check this item is still in the summary first */ - if (mi->summary && res && mi->summary->folder && mi->uid) { - CamelFolderChangeInfo *changes = camel_folder_change_info_new(); + g_return_if_fail(mi != NULL); - mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED; - camel_folder_summary_touch(mi->summary); - camel_folder_change_info_change_uid(changes, camel_message_info_uid(info)); - camel_object_trigger_event(mi->summary->folder, "folder_changed", changes); - camel_folder_change_info_free(changes); + GLOBAL_INFO_LOCK(info); + mi->refcount--; + if (mi->refcount > 0) { + GLOBAL_INFO_UNLOCK(info); + return; } + GLOBAL_INFO_UNLOCK(info); - return res; +#ifdef DOEPOOLV + e_poolv_destroy(mi->strings); +#elif defined (DOESTRV) + e_strv_destroy(mi->strings); +#else + g_free(mi->uid); + g_free(mi->subject); + g_free(mi->from); + g_free(mi->to); + g_free(mi->cc); + g_free(mi->mlist); +#endif + g_free(mi->references); + camel_flag_list_free(&mi->user_flags); + camel_tag_list_free(&mi->user_tags); + /* FIXME: content info? */ + g_free(mi); } -gboolean camel_message_info_set_user_flag(CamelMessageInfo *mi, const char *id, gboolean state) +#if defined (DOEPOOLV) || defined (DOESTRV) +const char * +camel_message_info_string (const CamelMessageInfo *mi, int type) { - if (mi->summary) - return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_set_user_flag(mi, id, state); - else - return info_set_user_flag(mi, id, state); + g_assert (mi != NULL); + + if (mi->strings == NULL) + return ""; +#ifdef DOEPOOLV + return e_poolv_get (mi->strings, type); +#else + return e_strv_get (mi->strings, type); +#endif } -static gboolean -info_set_user_tag(CamelMessageInfo *info, const char *name, const char *value) +void +camel_message_info_set_string (CamelMessageInfo *mi, int type, char *str) { - CamelMessageInfoBase *mi = (CamelMessageInfoBase *)info; - int res; - - res = camel_tag_set(&mi->user_tags, name, value); - - if (mi->summary && res && mi->summary->folder && mi->uid) { - CamelFolderChangeInfo *changes = camel_folder_change_info_new(); - - mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED; - camel_folder_summary_touch(mi->summary); - camel_folder_change_info_change_uid(changes, camel_message_info_uid(info)); - camel_object_trigger_event(mi->summary->folder, "folder_changed", changes); - camel_folder_change_info_free(changes); - } - - return res; + g_assert (mi != NULL); + g_assert (mi->strings != NULL); +#ifdef DOEPOOLV + e_poolv_set (mi->strings, type, str, TRUE); +#else + mi->strings = e_strv_set_ref_free (mi->strings, type, str); +#endif } +#endif -gboolean camel_message_info_set_user_tag(CamelMessageInfo *mi, const char *id, const char *val) -{ - if (mi->summary) - return ((CamelFolderSummaryClass *)((CamelObject *)mi->summary)->klass)->info_set_user_tag(mi, id, val); - else - return info_set_user_tag(mi, id, val); -} void camel_content_info_dump (CamelMessageContentInfo *ci, int depth) @@ -2902,50 +2883,6 @@ camel_message_info_dump (CamelMessageInfo *mi) printf("mailing list: %s\n", camel_message_info_mlist(mi)); printf("From: %s\n", camel_message_info_from(mi)); printf("UID: %s\n", camel_message_info_uid(mi)); - printf("Flags: %04x\n", camel_message_info_flags(mi)); - /*camel_content_info_dump(mi->content, 0);*/ -} - - -static void -camel_folder_summary_class_init (CamelFolderSummaryClass *klass) -{ - camel_folder_summary_parent = camel_type_get_global_classfuncs (camel_object_get_type ()); - - klass->summary_header_load = summary_header_load; - klass->summary_header_save = summary_header_save; - - klass->message_info_new_from_header = message_info_new_from_header; - klass->message_info_new_from_parser = message_info_new_from_parser; - klass->message_info_new_from_message = message_info_new_from_message; - klass->message_info_load = message_info_load; - klass->message_info_save = message_info_save; - klass->message_info_free = message_info_free; - klass->message_info_clone = message_info_clone; - - klass->content_info_new_from_header = content_info_new_from_header; - klass->content_info_new_from_parser = content_info_new_from_parser; - klass->content_info_new_from_message = content_info_new_from_message; - klass->content_info_load = content_info_load; - klass->content_info_save = content_info_save; - klass->content_info_free = content_info_free; - - klass->next_uid_string = next_uid_string; - - klass->info_ptr = info_ptr; - klass->info_uint32 = info_uint32; - klass->info_time = info_time; - klass->info_user_flag = info_user_flag; - klass->info_user_tag = info_user_tag; - -#if 0 - klass->info_set_string = info_set_string; - klass->info_set_uint32 = info_set_uint32; - klass->info_set_time = info_set_time; - klass->info_set_ptr = info_set_ptr; -#endif - klass->info_set_user_flag = info_set_user_flag; - klass->info_set_user_tag = info_set_user_tag; - - klass->info_set_flags = info_set_flags; + printf("Flags: %04x\n", mi->flags & 0xffff); + camel_content_info_dump(mi->content, 0); } diff --git a/camel/camel-gpg-context.c b/camel/camel-gpg-context.c index 928b4ed4be..b52f6feb6b 100644 --- a/camel/camel-gpg-context.c +++ b/camel/camel-gpg-context.c @@ -46,7 +46,7 @@ #include <errno.h> #include <ctype.h> -#include "libedataserver/e-iconv.h" +#include "gal/util/e-iconv.h" #include "camel-gpg-context.h" #include "camel-mime-filter-charset.h" @@ -56,9 +56,9 @@ #include "camel-operation.h" #include "camel-mime-part.h" #include "camel-mime-filter-canon.h" + #include "camel-multipart-signed.h" #include "camel-multipart-encrypted.h" -#include "camel-i18n.h" #define d(x) diff --git a/camel/camel-http-stream.c b/camel/camel-http-stream.c index e9bad5d1a4..53c0241a2b 100644 --- a/camel/camel-http-stream.c +++ b/camel/camel-http-stream.c @@ -30,7 +30,6 @@ #include <ctype.h> #include <errno.h> -#include "camel-net-utils.h" #include "camel-http-stream.h" #include "camel-mime-utils.h" diff --git a/camel/camel-mime-utils.c b/camel/camel-mime-utils.c index 510d07f019..8fe1cc240f 100644 --- a/camel/camel-mime-utils.c +++ b/camel/camel-mime-utils.c @@ -45,12 +45,12 @@ #endif #include <glib.h> -#include <libedataserver/e-iconv.h> -#include <libedataserver/e-time-utils.h> +#include <gal/util/e-iconv.h> +#include <e-util/e-time-utils.h> #include "camel-mime-utils.h" #include "camel-charset-map.h" -#include "camel-net-utils.h" +#include "camel-service.h" /* for camel_gethostbyname() */ #include "camel-utf8.h" #ifndef CLEAN_DATE diff --git a/camel/camel-movemail.c b/camel/camel-movemail.c index 619d3dc33a..9684bf25e6 100644 --- a/camel/camel-movemail.c +++ b/camel/camel-movemail.c @@ -42,11 +42,12 @@ #include "camel-movemail.h" #include "camel-exception.h" + #include "camel-mime-parser.h" #include "camel-mime-filter.h" #include "camel-mime-filter-from.h" + #include "camel-lock-client.h" -#include "camel-i18n.h" #define d(x) diff --git a/camel/camel-multipart-signed.c b/camel/camel-multipart-signed.c index ebd5d275e4..26d3b04993 100644 --- a/camel/camel-multipart-signed.c +++ b/camel/camel-multipart-signed.c @@ -43,13 +43,12 @@ #include "camel-multipart-signed.h" #include "camel-mime-part.h" #include "camel-exception.h" -#include "libedataserver/md5-utils.h" +#include "md5-utils.h" #include "camel-stream-filter.h" #include "camel-seekable-substream.h" #include "camel-mime-filter-crlf.h" #include "camel-mime-filter-canon.h" -#include "camel-i18n.h" #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x)) #include <stdio.h>;*/ @@ -541,6 +540,124 @@ write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) return total; } +/* See rfc3156, section 2 and others */ +/* We do this simply: Anything not base64 must be qp + This is so that we can safely translate any occurance of "From " + into the quoted-printable escaped version safely. */ +static void +prepare_sign(CamelMimePart *mime_part) +{ + CamelDataWrapper *wrapper; + CamelTransferEncoding encoding; + int parts, i; + + wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); + if (!wrapper) + return; + + if (CAMEL_IS_MULTIPART (wrapper)) { + parts = camel_multipart_get_number((CamelMultipart *)wrapper); + for (i = 0; i < parts; i++) + prepare_sign(camel_multipart_get_part((CamelMultipart *)wrapper, i)); + } else if (CAMEL_IS_MIME_MESSAGE (wrapper)) { + prepare_sign((CamelMimePart *)wrapper); + } else { + encoding = camel_mime_part_get_encoding(mime_part); + + if (encoding != CAMEL_TRANSFER_ENCODING_BASE64 + && encoding != CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE) { + camel_mime_part_set_encoding(mime_part, CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE); + } + } +} + +/** + * camel_multipart_signed_sign: + * @mps: + * @context: The CipherContext to use for signing. + * @content: CamelMimePart content you wish to sign/transport. + * @userid: The id of the signing key to use. + * @hash: The algorithm to use. + * @ex: + * + * Sign the part @content, and attach it as the first part + * (CAMEL_MULTIPART_SIGNED_CONTENT) of the multipart @mps. A + * signature object will be created and setup as the second part + * (CAMEL_MULTIPART_SIGNED_SIGNATURE) of the object. Once a part has + * been successfully signed the mutlipart is ready for transmission. + * + * This method should be used to create multipart/signed objects + * which are properly canoncalised before signing, etc. + * + * Return value: -1 on error, setting @ex appropriately. On error + * neither the content or signature parts will be setup. + **/ +int +camel_multipart_signed_sign(CamelMultipartSigned *mps, CamelCipherContext *context, CamelMimePart *content, const char *userid, CamelCipherHash hash, CamelException *ex) +{ + abort(); +#if 0 + CamelMimeFilter *canon_filter; + CamelStream *mem; + CamelStreamFilter *filter; + CamelContentType *mime_type; + CamelMimePart *sigpart; + + /* this needs to be set */ + g_return_val_if_fail(context->sign_protocol != NULL, -1); + + prepare_sign(content); + + mem = camel_stream_mem_new(); + filter = camel_stream_filter_new_with_stream(mem); + + /* Note: see rfc2015 or rfc3156, section 5 */ + canon_filter = camel_mime_filter_canon_new(CAMEL_MIME_FILTER_CANON_STRIP|CAMEL_MIME_FILTER_CANON_CRLF|CAMEL_MIME_FILTER_CANON_FROM); + camel_stream_filter_add(filter, (CamelMimeFilter *)canon_filter); + camel_object_unref((CamelObject *)canon_filter); + + camel_data_wrapper_write_to_stream((CamelDataWrapper *)content, (CamelStream *)filter); + camel_stream_flush((CamelStream *)filter); + camel_object_unref((CamelObject *)filter); + camel_stream_reset(mem); + +#if 0 + printf("-- Signing:\n"); + fwrite(((CamelStreamMem *)mem)->buffer->data, ((CamelStreamMem *)mem)->buffer->len, 1, stdout); + printf("-- end\n"); +#endif + + sigpart = camel_mime_part_new(); + + if (camel_cipher_sign(context, userid, hash, mem, sigpart, ex) == -1) { + camel_object_unref(mem); + camel_object_unref(sigpart); + return -1; + } + + /* setup our mime type and boundary */ + mime_type = camel_content_type_new("multipart", "signed"); + camel_content_type_set_param(mime_type, "micalg", camel_cipher_hash_to_id(context, hash)); + camel_content_type_set_param(mime_type, "protocol", context->sign_protocol); + camel_data_wrapper_set_mime_type_field(CAMEL_DATA_WRAPPER (mps), mime_type); + camel_content_type_unref(mime_type); + camel_multipart_set_boundary((CamelMultipart *)mps, NULL); + + /* just keep the whole raw content. We dont *really* need to do this because + we know how we just proccessed it, but, well, better to be safe than sorry */ + mps->signature = sigpart; + mps->contentraw = mem; + camel_stream_reset(mem); + + /* clear the data-wrapper stream - tells write_to_stream to use the right object */ + if (((CamelDataWrapper *)mps)->stream) { + camel_object_unref((CamelObject *) ((CamelDataWrapper *)mps)->stream); + ((CamelDataWrapper *)mps)->stream = NULL; + } +#endif + return 0; +} + CamelStream * camel_multipart_signed_get_content_stream(CamelMultipartSigned *mps, CamelException *ex) { @@ -573,3 +690,77 @@ camel_multipart_signed_get_content_stream(CamelMultipartSigned *mps, CamelExcept return constream; } + +/** + * camel_multipart_signed_verify: + * @mps: + * @context: + * @ex: + * + * Verify a signed object. This may be used to verify newly signed + * objects as well as those created from external streams or parsers. + * + * Return value: A validity value, or NULL on error, setting @ex + * appropriately. + **/ +CamelCipherValidity * +camel_multipart_signed_verify(CamelMultipartSigned *mps, CamelCipherContext *context, CamelException *ex) +{ + abort(); + + return NULL; +#if 0 + CamelCipherValidity *valid; + CamelMimePart *sigpart; + CamelStream *constream; + + /* we need to be able to verify stuff we just signed as well as stuff we loaded from a stream/parser */ + + if (mps->contentraw) { + constream = mps->contentraw; + camel_object_ref((CamelObject *)constream); + } else { + CamelStream *sub; + CamelMimeFilter *canon_filter; + + if (mps->start1 == -1 && parse_content(mps) == -1) { + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("parse error")); + return NULL; + } + + /* first, prepare our parts */ + sub = camel_seekable_substream_new((CamelSeekableStream *)((CamelDataWrapper *)mps)->stream, mps->start1, mps->end1); + constream = (CamelStream *)camel_stream_filter_new_with_stream(sub); + camel_object_unref((CamelObject *)sub); + + /* Note: see rfc2015 or rfc3156, section 5 */ + canon_filter = camel_mime_filter_canon_new (CAMEL_MIME_FILTER_CANON_CRLF); + camel_stream_filter_add((CamelStreamFilter *)constream, (CamelMimeFilter *)canon_filter); + camel_object_unref((CamelObject *)canon_filter); + } + + /* we do this as a normal mime part so we can have it handle transfer encoding etc */ + sigpart = camel_multipart_get_part((CamelMultipart *)mps, CAMEL_MULTIPART_SIGNED_SIGNATURE); + + /* do the magic, the caller must supply the right context for this kind of object */ + valid = camel_cipher_verify(context, camel_cipher_id_to_hash(context, mps->micalg), constream, sigpart, ex); + +#if 0 + { + CamelStream *sout = camel_stream_fs_new_with_fd(dup(0)); + + camel_stream_printf(sout, "-- Verifying:\n"); + camel_stream_reset(constream); + camel_stream_write_to_stream(constream, sout); + camel_stream_printf(sout, "-- end\n"); + camel_object_unref((CamelObject *)sout); + } +#endif + + camel_object_unref(constream); + + return valid; +#endif +} + + diff --git a/camel/camel-operation.c b/camel/camel-operation.c index 1234163eef..406d576597 100644 --- a/camel/camel-operation.c +++ b/camel/camel-operation.c @@ -36,7 +36,7 @@ #endif #include "camel-operation.h" -#include "libedataserver/e-msgport.h" +#include "e-util/e-msgport.h" #define d(x) diff --git a/camel/camel-sasl-digest-md5.c b/camel/camel-sasl-digest-md5.c index 2a38858dd4..47b3339520 100644 --- a/camel/camel-sasl-digest-md5.c +++ b/camel/camel-sasl-digest-md5.c @@ -20,6 +20,7 @@ * */ + #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -29,15 +30,13 @@ #include <ctype.h> #include <unistd.h> -#include <libedataserver/md5-utils.h> +#include <e-util/md5-utils.h> -#include <libedataserver/e-iconv.h> +#include <gal/util/e-iconv.h> #include "camel-charset-map.h" #include "camel-mime-utils.h" #include "camel-sasl-digest-md5.h" -#include "camel-i18n.h" -#include "camel-net-utils.h" #define d(x) diff --git a/camel/camel-sasl-gssapi.c b/camel/camel-sasl-gssapi.c index e4fa002d5c..1efbefee16 100644 --- a/camel/camel-sasl-gssapi.c +++ b/camel/camel-sasl-gssapi.c @@ -46,7 +46,6 @@ #define GSS_C_OID_KRBV5_DES GSS_C_NO_OID #endif -#include "camel-i18n.h" #include "camel-sasl-gssapi.h" CamelServiceAuthType camel_sasl_gssapi_authtype = { @@ -205,6 +204,7 @@ gssapi_challenge (CamelSasl *sasl, GByteArray *token, CamelException *ex) gss_buffer_desc inbuf, outbuf; GByteArray *challenge = NULL; gss_buffer_t input_token; + struct hostent *h; int conf_state; gss_qop_t qop; gss_OID mech; diff --git a/camel/camel-sasl-kerberos4.c b/camel/camel-sasl-kerberos4.c index 457f3e9afd..fd366e61db 100644 --- a/camel/camel-sasl-kerberos4.c +++ b/camel/camel-sasl-kerberos4.c @@ -33,7 +33,6 @@ #undef _ #include <string.h> -#include "camel-i18n.h" #include "camel-string-utils.h" #include "camel-sasl-kerberos4.h" #include "camel-service.h" diff --git a/camel/camel-service.c b/camel/camel-service.c index 6e79a86363..13190844e6 100644 --- a/camel/camel-service.c +++ b/camel/camel-service.c @@ -32,18 +32,20 @@ #include <stdlib.h> #include <string.h> #include <pthread.h> +#include <netdb.h> #include <errno.h> #include <sys/poll.h> -#include "libedataserver/e-msgport.h" +#include "e-util/e-msgport.h" + +#include "e-util/e-host-utils.h" #include "camel-service.h" #include "camel-session.h" #include "camel-exception.h" #include "camel-operation.h" #include "camel-private.h" -#include "camel-i18n.h" #define d(x) #define w(x) @@ -642,3 +644,417 @@ camel_service_query_auth_types (CamelService *service, CamelException *ex) return ret; } + +/* ********************************************************************** */ +struct _addrinfo_msg { + EMsg msg; + unsigned int cancelled:1; + + /* for host lookup */ + const char *name; + const char *service; + int result; + const struct addrinfo *hints; + struct addrinfo **res; + + /* for host lookup emulation */ +#ifdef NEED_ADDRINFO + struct hostent hostbuf; + int hostbuflen; + char *hostbufmem; +#endif + + /* for name lookup */ + const struct sockaddr *addr; + socklen_t addrlen; + char *host; + int hostlen; + char *serv; + int servlen; + int flags; +}; + +static void +cs_freeinfo(struct _addrinfo_msg *msg) +{ + g_free(msg->host); + g_free(msg->serv); +#ifdef NEED_ADDRINFO + g_free(msg->hostbufmem); +#endif + g_free(msg); +} + +/* returns -1 if cancelled */ +static int +cs_waitinfo(void *(worker)(void *), struct _addrinfo_msg *msg, const char *error, CamelException *ex) +{ + EMsgPort *reply_port; + pthread_t id; + int err, cancel_fd, cancel = 0, fd; + + cancel_fd = camel_operation_cancel_fd(NULL); + if (cancel_fd == -1) { + worker(msg); + return 0; + } + + reply_port = msg->msg.reply_port = e_msgport_new(); + fd = e_msgport_fd(msg->msg.reply_port); + if ((err = pthread_create(&id, NULL, worker, msg)) == 0) { + struct pollfd polls[2]; + int status; + + polls[0].fd = fd; + polls[0].events = POLLIN; + polls[1].fd = cancel_fd; + polls[1].events = POLLIN; + + d(printf("waiting for name return/cancellation in main process\n")); + do { + polls[0].revents = 0; + polls[1].revents = 0; + status = poll(polls, 2, -1); + } while (status == -1 && errno == EINTR); + + if (status == -1 || (polls[1].revents & POLLIN)) { + if (status == -1) + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, "%s: %s", error, g_strerror(errno)); + else + camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); + + /* We cancel so if the thread impl is decent it causes immediate exit. + We detach so we dont need to wait for it to exit if it isn't. + We check the reply port incase we had a reply in the mean time, which we free later */ + d(printf("Cancelling lookup thread and leaving it\n")); + msg->cancelled = 1; + pthread_detach(id); + pthread_cancel(id); + cancel = 1; + } else { + struct _addrinfo_msg *reply = (struct _addrinfo_msg *)e_msgport_get(reply_port); + + g_assert(reply == msg); + d(printf("waiting for child to exit\n")); + pthread_join(id, NULL); + d(printf("child done\n")); + } + } else { + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, "%s: %s: %s", error, _("cannot create thread"), g_strerror(err)); + } + e_msgport_destroy(reply_port); + + return cancel; +} + +#ifdef NEED_ADDRINFO +static void * +cs_getaddrinfo(void *data) +{ + struct _addrinfo_msg *msg = data; + int herr; + struct hostent h; + struct addrinfo *res, *last = NULL; + struct sockaddr_in *sin; + in_port_t port = 0; + int i; + + /* This is a pretty simplistic emulation of getaddrinfo */ + + while ((msg->result = e_gethostbyname_r(msg->name, &h, msg->hostbufmem, msg->hostbuflen, &herr)) == ERANGE) { + pthread_testcancel(); + msg->hostbuflen *= 2; + msg->hostbufmem = g_realloc(msg->hostbufmem, msg->hostbuflen); + } + + /* If we got cancelled, dont reply, just free it */ + if (msg->cancelled) + goto cancel; + + /* FIXME: map error numbers across */ + if (msg->result != 0) + goto reply; + + /* check hints matched */ + if (msg->hints && msg->hints->ai_family && msg->hints->ai_family != h.h_addrtype) { + msg->result = EAI_FAMILY; + goto reply; + } + + /* we only support ipv4 for this interface, even if it could supply ipv6 */ + if (h.h_addrtype != AF_INET) { + msg->result = EAI_FAMILY; + goto reply; + } + + /* check service mapping */ + if (msg->service) { + const char *p = msg->service; + + while (*p) { + if (*p < '0' || *p > '9') + break; + p++; + } + + if (*p) { + const char *socktype = NULL; + struct servent *serv; + + if (msg->hints && msg->hints->ai_socktype) { + if (msg->hints->ai_socktype == SOCK_STREAM) + socktype = "tcp"; + else if (msg->hints->ai_socktype == SOCK_DGRAM) + socktype = "udp"; + } + + serv = getservbyname(msg->service, socktype); + if (serv == NULL) { + msg->result = EAI_NONAME; + goto reply; + } + port = serv->s_port; + } else { + port = htons(strtoul(msg->service, NULL, 10)); + } + } + + for (i=0;h.h_addr_list[i];i++) { + res = g_malloc0(sizeof(*res)); + if (msg->hints) { + res->ai_flags = msg->hints->ai_flags; + if (msg->hints->ai_flags & AI_CANONNAME) + res->ai_canonname = g_strdup(h.h_name); + res->ai_socktype = msg->hints->ai_socktype; + res->ai_protocol = msg->hints->ai_protocol; + } else { + res->ai_flags = 0; + res->ai_socktype = SOCK_STREAM; /* fudge */ + res->ai_protocol = 0; /* fudge */ + } + res->ai_family = AF_INET; + res->ai_addrlen = sizeof(*sin); + res->ai_addr = g_malloc(sizeof(*sin)); + sin = (struct sockaddr_in *)res->ai_addr; + sin->sin_family = AF_INET; + sin->sin_port = port; + memcpy(&sin->sin_addr, h.h_addr_list[i], sizeof(sin->sin_addr)); + + if (last == NULL) { + *msg->res = last = res; + } else { + last->ai_next = res; + last = res; + } + } +reply: + e_msgport_reply((EMsg *)msg); + return NULL; +cancel: + cs_freeinfo(msg); + return NULL; +} +#else +static void * +cs_getaddrinfo(void *data) +{ + struct _addrinfo_msg *info = data; + + info->result = getaddrinfo(info->name, info->service, info->hints, info->res); + + if (info->cancelled) { + g_free(info); + } else { + e_msgport_reply((EMsg *)info); + } + + return NULL; +} +#endif /* NEED_ADDRINFO */ + +struct addrinfo * +camel_getaddrinfo(const char *name, const char *service, const struct addrinfo *hints, CamelException *ex) +{ + struct _addrinfo_msg *msg; + struct addrinfo *res = NULL; +#ifndef ENABLE_IPv6 + struct addrinfo myhints; +#endif + g_return_val_if_fail(name != NULL, NULL); + + if (camel_operation_cancel_check(NULL)) { + camel_exception_set(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); + return NULL; + } + + camel_operation_start_transient(NULL, _("Resolving: %s"), name); + + /* force ipv4 addresses only */ +#ifndef ENABLE_IPv6 + if (hints == NULL) + memset(&myhints, 0, sizeof(myhints)); + else + memcpy (&myhints, hints, sizeof (myhints)); + + myhints.ai_family = AF_INET; + hints = &myhints; +#endif + + msg = g_malloc0(sizeof(*msg)); + msg->name = name; + msg->service = service; + msg->hints = hints; + msg->res = &res; +#ifdef NEED_ADDRINFO + msg->hostbuflen = 1024; + msg->hostbufmem = g_malloc(msg->hostbuflen); +#endif + if (cs_waitinfo(cs_getaddrinfo, msg, _("Host lookup failed"), ex) == 0) { + if (msg->result != 0) + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Host lookup failed: %s: %s"), + name, gai_strerror (msg->result)); + + cs_freeinfo(msg); + } else + res = NULL; + + camel_operation_end(NULL); + + return res; +} + +void +camel_freeaddrinfo(struct addrinfo *host) +{ +#ifdef NEED_ADDRINFO + while (host) { + struct addrinfo *next = host->ai_next; + + g_free(host->ai_canonname); + g_free(host->ai_addr); + g_free(host); + host = next; + } +#else + freeaddrinfo(host); +#endif +} + +#ifdef NEED_ADDRINFO +static void * +cs_getnameinfo(void *data) +{ + struct _addrinfo_msg *msg = data; + int herr; + struct hostent h; + struct sockaddr_in *sin = (struct sockaddr_in *)msg->addr; + + /* FIXME: error code */ + if (msg->addr->sa_family != AF_INET) { + msg->result = -1; + return NULL; + } + + /* FIXME: honour getnameinfo flags: do we care, not really */ + + while ((msg->result = e_gethostbyaddr_r((const char *)&sin->sin_addr, sizeof(sin->sin_addr), AF_INET, &h, + msg->hostbufmem, msg->hostbuflen, &herr)) == ERANGE) { + pthread_testcancel (); + msg->hostbuflen *= 2; + msg->hostbufmem = g_realloc(msg->hostbufmem, msg->hostbuflen); + } + + if (msg->cancelled) + goto cancel; + + if (msg->host) { + g_free(msg->host); + if (msg->result == 0 && h.h_name && h.h_name[0]) { + msg->host = g_strdup(h.h_name); + } else { + unsigned char *in = (unsigned char *)&sin->sin_addr; + + /* sin_addr is always network order which is big-endian */ + msg->host = g_strdup_printf("%u.%u.%u.%u", in[0], in[1], in[2], in[3]); + } + } + + /* we never actually use this anyway */ + if (msg->serv) + sprintf(msg->serv, "%d", sin->sin_port); + + e_msgport_reply((EMsg *)msg); + return NULL; +cancel: + cs_freeinfo(msg); + return NULL; +} +#else +static void * +cs_getnameinfo(void *data) +{ + struct _addrinfo_msg *msg = data; + + /* there doens't appear to be a return code which says host or serv buffers are too short, lengthen them */ + msg->result = getnameinfo(msg->addr, msg->addrlen, msg->host, msg->hostlen, msg->serv, msg->servlen, msg->flags); + + if (msg->cancelled) + cs_freeinfo(msg); + else + e_msgport_reply((EMsg *)msg); + + return NULL; +} +#endif + +int +camel_getnameinfo(const struct sockaddr *sa, socklen_t salen, char **host, char **serv, int flags, CamelException *ex) +{ + struct _addrinfo_msg *msg; + int result; + + if (camel_operation_cancel_check(NULL)) { + camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); + return -1; + } + + camel_operation_start_transient(NULL, _("Resolving address")); + + msg = g_malloc0(sizeof(*msg)); + msg->addr = sa; + msg->addrlen = salen; + if (host) { + msg->hostlen = NI_MAXHOST; + msg->host = g_malloc(msg->hostlen); + msg->host[0] = 0; + } + if (serv) { + msg->servlen = NI_MAXSERV; + msg->serv = g_malloc(msg->servlen); + msg->serv[0] = 0; + } + msg->flags = flags; +#ifdef NEED_ADDRINFO + msg->hostbuflen = 1024; + msg->hostbufmem = g_malloc(msg->hostbuflen); +#endif + cs_waitinfo(cs_getnameinfo, msg, _("Name lookup failed"), ex); + + if ((result = msg->result) != 0) + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Name lookup failed: %s"), + gai_strerror (result)); + + if (host) + *host = g_strdup(msg->host); + if (serv) + *serv = g_strdup(msg->serv); + + g_free(msg->host); + g_free(msg->serv); + g_free(msg); + + camel_operation_end(NULL); + + return result; +} + diff --git a/camel/camel-service.h b/camel/camel-service.h index 8180b2a05e..f49472cc5a 100644 --- a/camel/camel-service.h +++ b/camel/camel-service.h @@ -1,9 +1,10 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* camel-service.h : Abstract class for an email service */ + /* * - * Authors: Bertrand Guiheneuf <bertrand@helixcode.com> - * Michael Zucchi <notzed@ximian.com> + * Author : + * Bertrand Guiheneuf <bertrand@helixcode.com> * * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) * @@ -22,6 +23,7 @@ * USA */ + #ifndef CAMEL_SERVICE_H #define CAMEL_SERVICE_H 1 @@ -31,6 +33,7 @@ extern "C" { #pragma } #endif /* __cplusplus }*/ +#include <netdb.h> #include <camel/camel-object.h> #include <camel/camel-url.h> #include <camel/camel-provider.h> @@ -74,6 +77,7 @@ struct _CamelService { CamelURL *url; }; + typedef struct { CamelObjectClass parent_class; @@ -99,6 +103,7 @@ typedef struct { } CamelServiceClass; + /* query_auth_types returns a GList of these */ typedef struct { char *name; /* user-friendly name */ @@ -108,6 +113,7 @@ typedef struct { gboolean need_password; /* needs a password to authenticate */ } CamelServiceAuthType; + /* public methods */ void camel_service_construct (CamelService *service, CamelSession *session, @@ -129,6 +135,62 @@ CamelProvider * camel_service_get_provider (CamelService *service); GList * camel_service_query_auth_types (CamelService *service, CamelException *ex); +#ifdef NEED_ADDRINFO +/* Some of this is copied from GNU's netdb.h + + Copyright (C) 1996-2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. +*/ +struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + struct sockaddr *ai_addr; + char *ai_canonname; + struct addrinfo *ai_next; +}; + +#define AI_CANONNAME 0x0002 /* Request for canonical name. */ +#define AI_NUMERICHOST 0x0004 /* Don't use name resolution. */ + +/* Error values for `getaddrinfo' function. */ +#define EAI_BADFLAGS -1 /* Invalid value for `ai_flags' field. */ +#define EAI_NONAME -2 /* NAME or SERVICE is unknown. */ +#define EAI_AGAIN -3 /* Temporary failure in name resolution. */ +#define EAI_FAIL -4 /* Non-recoverable failure in name res. */ +#define EAI_NODATA -5 /* No address associated with NAME. */ +#define EAI_FAMILY -6 /* `ai_family' not supported. */ +#define EAI_SOCKTYPE -7 /* `ai_socktype' not supported. */ +#define EAI_SERVICE -8 /* SERVICE not supported for `ai_socktype'. */ +#define EAI_ADDRFAMILY -9 /* Address family for NAME not supported. */ +#define EAI_MEMORY -10 /* Memory allocation failure. */ +#define EAI_SYSTEM -11 /* System error returned in `errno'. */ +#define EAI_OVERFLOW -12 /* Argument buffer overflow. */ + +#define NI_MAXHOST 1025 +#define NI_MAXSERV 32 + +#define NI_NUMERICHOST 1 /* Don't try to look up hostname. */ +#define NI_NUMERICSERV 2 /* Don't convert port number to name. */ +#define NI_NOFQDN 4 /* Only return nodename portion. */ +#define NI_NAMEREQD 8 /* Don't return numeric addresses. */ +#define NI_DGRAM 16 /* Look up UDP service rather than TCP. */ +#endif + +/* new hostname interfaces */ +struct addrinfo *camel_getaddrinfo(const char *name, const char *service, + const struct addrinfo *hints, CamelException *ex); +void camel_freeaddrinfo(struct addrinfo *host); +int camel_getnameinfo(const struct sockaddr *sa, socklen_t salen, char **host, char **serv, + int flags, CamelException *ex); + /* Standard Camel function */ CamelType camel_service_get_type (void); diff --git a/camel/camel-smime-context.c b/camel/camel-smime-context.c index 9e5cc241dc..80b10081a5 100644 --- a/camel/camel-smime-context.c +++ b/camel/camel-smime-context.c @@ -56,7 +56,6 @@ #include "camel-smime-context.h" #include "camel-operation.h" -#include "camel-i18n.h" #define d(x) @@ -239,13 +238,13 @@ sm_signing_cmsmessage(CamelSMIMEContext *context, const char *nick, SECOidTag ha } if ((sigd = NSS_CMSSignedData_Create(cmsg)) == NULL) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS signed data")); + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS signedData")); goto fail; } cinfo = NSS_CMSMessage_GetContentInfo(cmsg); if (NSS_CMSContentInfo_SetContent_SignedData(cmsg, cinfo, sigd) != SECSuccess) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot attach CMS signed data")); + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot attach CMS signedData")); goto fail; } @@ -258,19 +257,19 @@ sm_signing_cmsmessage(CamelSMIMEContext *context, const char *nick, SECOidTag ha signerinfo = NSS_CMSSignerInfo_Create(cmsg, cert, hash); if (signerinfo == NULL) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS Signer information")); + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS SignerInfo")); goto fail; } /* we want the cert chain included for this one */ if (NSS_CMSSignerInfo_IncludeCerts(signerinfo, NSSCMSCM_CertChain, certUsageEmailSigner) != SECSuccess) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot find certificate chain")); + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot find cert chain")); goto fail; } /* SMIME RFC says signing time should always be added */ if (NSS_CMSSignerInfo_AddSigningTime(signerinfo, PR_Now()) != SECSuccess) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot add CMS Signing time")); + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot add CMS SigningTime")); goto fail; } @@ -292,7 +291,7 @@ sm_signing_cmsmessage(CamelSMIMEContext *context, const char *nick, SECOidTag ha p->certdb, p->encrypt_key, certUsageEmailRecipient, PR_FALSE, NULL)) == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Encryption certificate for '%s' does not exist"), p->encrypt_key); + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Encryption cert for '%s' does not exist"), p->encrypt_key); goto fail; } enccert = ekpcert; @@ -304,7 +303,7 @@ sm_signing_cmsmessage(CamelSMIMEContext *context, const char *nick, SECOidTag ha if ((ekpcert = CERT_FindUserCertByUsage( p->certdb, (char *)nick, certUsageEmailRecipient, PR_FALSE, NULL)) == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Encryption certificate for '%s' does not exist"), nick); + camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Encryption cert for '%s' does not exist"), nick); goto fail; } enccert = ekpcert; @@ -327,7 +326,7 @@ sm_signing_cmsmessage(CamelSMIMEContext *context, const char *nick, SECOidTag ha } if (NSS_CMSSignedData_AddSignerInfo(sigd, signerinfo) != SECSuccess) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot add CMS Signer information")); + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot add CMS SignerInfo")); goto fail; } @@ -536,7 +535,7 @@ sm_verify_cmsg(CamelCipherContext *context, NSSCMSMessage *cmsg, CamelStream *ex case SEC_OID_PKCS7_SIGNED_DATA: sigd = (NSSCMSSignedData *)NSS_CMSContentInfo_GetContent(cinfo); if (sigd == NULL) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("No signed data in signature")); + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("No signedData in signature")); goto fail; } @@ -593,13 +592,12 @@ sm_verify_cmsg(CamelCipherContext *context, NSSCMSMessage *cmsg, CamelStream *ex /* check for certs-only message */ nsigners = NSS_CMSSignedData_SignerInfoCount(sigd); if (nsigners == 0) { - /* already imported certs above, not sure what usage we should use here or if this isn't handled above */ if (NSS_CMSSignedData_VerifyCertsOnly(sigd, p->certdb, certUsageEmailSigner) != SECSuccess) { - g_string_printf(description, _("Certificate is the only message, cannot verify certificates")); + g_string_printf(description, _("Certificate only message, cannot verify certificates")); } else { status = NSSCMSVS_GoodSignature; - g_string_printf(description, _("Certificate is the only message, certificates imported and verified")); + g_string_printf(description, _("Certificate only message, certificates imported and verified")); } } else { if (!NSS_CMSSignedData_HasDigests(sigd)) { @@ -805,13 +803,13 @@ sm_encrypt(CamelCipherContext *context, const char *userid, GPtrArray *recipient envd = NSS_CMSEnvelopedData_Create(cmsg, bulkalgtag, bulkkeysize); if (envd == NULL) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS Enveloped data")); + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS EnvelopedData")); goto fail; } cinfo = NSS_CMSMessage_GetContentInfo(cmsg); if (NSS_CMSContentInfo_SetContent_EnvelopedData(cmsg, cinfo, envd) != SECSuccess) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot attach CMS Enveloped data")); + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot attach CMS EnvelopedData")); goto fail; } @@ -826,12 +824,12 @@ sm_encrypt(CamelCipherContext *context, const char *userid, GPtrArray *recipient NSSCMSRecipientInfo *ri = NSS_CMSRecipientInfo_Create(cmsg, recipient_certs[i]); if (ri == NULL) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS Recipient information")); + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS RecipientInfo")); goto fail; } if (NSS_CMSEnvelopedData_AddRecipient(envd, ri) != SECSuccess) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot add CMS Recipient information")); + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot add CMS RecipientInfo")); goto fail; } } diff --git a/camel/camel-tcp-stream-ssl.c b/camel/camel-tcp-stream-ssl.c index a818fbc8b4..39bf89d468 100644 --- a/camel/camel-tcp-stream-ssl.c +++ b/camel/camel-tcp-stream-ssl.c @@ -54,14 +54,13 @@ /* this is commented because otherwise we get an error about the redefinition of MD5Context...yay */ -/*#include <libedataserver/md5-utils.h>*/ +/*#include <e-util/md5-utils.h>*/ #include "camel-tcp-stream-ssl.h" #include "camel-stream-fs.h" #include "camel-session.h" #include "camel-certdb.h" #include "camel-operation.h" -#include "camel-i18n.h" /* from md5-utils.h */ void md5_get_digest (const char *buffer, int buffer_size, unsigned char digest[16]); diff --git a/camel/camel-vee-folder.c b/camel/camel-vee-folder.c index 47d0331be5..d7c29eefb4 100644 --- a/camel/camel-vee-folder.c +++ b/camel/camel-vee-folder.c @@ -30,20 +30,19 @@ #include "camel-exception.h" #include "camel-vee-folder.h" #include "camel-store.h" +#include "camel-folder-summary.h" #include "camel-mime-message.h" #include "camel-folder-search.h" -#include "camel-vee-summary.h" #include "camel-session.h" #include "camel-vee-store.h" /* for open flags */ #include "camel-private.h" #include "camel-debug.h" -#include "camel-i18n.h" -#include "libedataserver/md5-utils.h" +#include "e-util/md5-utils.h" #if defined (DOEPOOLV) || defined (DOESTRV) -#include "libedataserver/e-memory.h" +#include "e-util/e-memory.h" #endif #define d(x) @@ -51,7 +50,6 @@ #define _PRIVATE(o) (((CamelVeeFolder *)(o))->priv) -#if 0 static void vee_refresh_info(CamelFolder *folder, CamelException *ex); static void vee_sync (CamelFolder *folder, gboolean expunge, CamelException *ex); @@ -67,19 +65,21 @@ static void vee_transfer_messages_to(CamelFolder *source, GPtrArray *uids, Camel static GPtrArray *vee_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex); static GPtrArray *vee_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex); +static gboolean vee_set_message_flags (CamelFolder *folder, const char *uid, guint32 flags, guint32 set); +static void vee_set_message_user_flag (CamelFolder *folder, const char *uid, const char *name, gboolean value); +static void vee_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value); static void vee_rename(CamelFolder *folder, const char *new); -#endif static void camel_vee_folder_class_init (CamelVeeFolderClass *klass); static void camel_vee_folder_init (CamelVeeFolder *obj); static void camel_vee_folder_finalise (CamelObject *obj); -static int vee_rebuild_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException *ex); -static void vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source); +static int vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException *ex); +static void vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source, int killun); static void folder_changed(CamelFolder *sub, CamelFolderChangeInfo *changes, CamelVeeFolder *vf); static void subfolder_deleted(CamelFolder *f, void *event_data, CamelVeeFolder *vf); -static void folder_renamed(CamelFolder *f, const char *old, CamelVeeFolder *vf); +static void subfolder_renamed(CamelFolder *f, void *event_data, CamelVeeFolder *vf); static void folder_changed_remove_uid(CamelFolder *sub, const char *uid, const char hash[8], int keep, CamelVeeFolder *vf); @@ -103,21 +103,120 @@ camel_vee_folder_get_type (void) return type; } +static void +camel_vee_folder_class_init (CamelVeeFolderClass *klass) +{ + CamelFolderClass *folder_class = (CamelFolderClass *) klass; + + camel_vee_folder_parent = CAMEL_FOLDER_CLASS(camel_type_get_global_classfuncs (camel_folder_get_type ())); + + folder_class->refresh_info = vee_refresh_info; + folder_class->sync = vee_sync; + folder_class->expunge = vee_expunge; + + folder_class->get_message = vee_get_message; + folder_class->append_message = vee_append_message; + folder_class->transfer_messages_to = vee_transfer_messages_to; + + folder_class->search_by_expression = vee_search_by_expression; + folder_class->search_by_uids = vee_search_by_uids; + + folder_class->set_message_flags = vee_set_message_flags; + folder_class->set_message_user_flag = vee_set_message_user_flag; + folder_class->set_message_user_tag = vee_set_message_user_tag; + + folder_class->rename = vee_rename; + + folder_class->freeze = vee_freeze; + folder_class->thaw = vee_thaw; +} + +static void +camel_vee_folder_init (CamelVeeFolder *obj) +{ + struct _CamelVeeFolderPrivate *p; + CamelFolder *folder = (CamelFolder *)obj; + + p = _PRIVATE(obj) = g_malloc0(sizeof(*p)); + + folder->folder_flags |= (CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | + CAMEL_FOLDER_HAS_SEARCH_CAPABILITY); + + /* FIXME: what to do about user flags if the subfolder doesn't support them? */ + folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | + CAMEL_MESSAGE_DELETED | + CAMEL_MESSAGE_DRAFT | + CAMEL_MESSAGE_FLAGGED | + CAMEL_MESSAGE_SEEN; + + obj->changes = camel_folder_change_info_new(); + obj->search = camel_folder_search_new(); + + p->summary_lock = g_mutex_new(); + p->subfolder_lock = g_mutex_new(); + p->changed_lock = g_mutex_new(); +} + +static void +camel_vee_folder_finalise (CamelObject *obj) +{ + CamelVeeFolder *vf = (CamelVeeFolder *)obj; + struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); + GList *node; + CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; + + /* FIXME: check leaks */ + node = p->folders; + while (node) { + CamelFolder *f = node->data; + + if (vf != folder_unmatched) { + camel_object_unhook_event((CamelObject *)f, "folder_changed", (CamelObjectEventHookFunc) folder_changed, vf); + camel_object_unhook_event((CamelObject *)f, "deleted", (CamelObjectEventHookFunc) subfolder_deleted, vf); + camel_object_unhook_event((CamelObject *)f, "renamed", (CamelObjectEventHookFunc) subfolder_renamed, vf); + /* this updates the vfolder */ + if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0) + vee_folder_remove_folder(vf, f, FALSE); + } + camel_object_unref((CamelObject *)f); + + node = g_list_next(node); + } + + g_free(vf->expression); + g_free(vf->vname); + + g_list_free(p->folders); + g_list_free(p->folders_changed); + + camel_folder_change_info_free(vf->changes); + camel_object_unref((CamelObject *)vf->search); + + g_mutex_free(p->summary_lock); + g_mutex_free(p->subfolder_lock); + g_mutex_free(p->changed_lock); + + g_free(p); +} + void camel_vee_folder_construct (CamelVeeFolder *vf, CamelStore *parent_store, const char *name, guint32 flags) { CamelFolder *folder = (CamelFolder *)vf; - const char *tmp; + char *tmp; vf->flags = flags; - tmp = strrchr(name, '/'); + vf->vname = g_strdup(name); + tmp = strrchr(vf->vname, '/'); if (tmp) tmp++; else - tmp = name; - camel_folder_construct(folder, parent_store, name, tmp); + tmp = vf->vname; + camel_folder_construct(folder, parent_store, vf->vname, tmp); - folder->summary = camel_vee_summary_new(folder); + /* should CamelVeeMessageInfo be subclassable ..? */ + folder->summary = camel_folder_summary_new(); + folder->summary->message_info_size = sizeof(CamelVeeMessageInfo); if (CAMEL_IS_VEE_STORE(parent_store)) vf->parent_vee_store = (CamelVeeStore *)parent_store; @@ -162,7 +261,38 @@ camel_vee_folder_new(CamelStore *parent_store, const char *name, guint32 flags) void camel_vee_folder_set_expression(CamelVeeFolder *vf, const char *query) { - ((CamelVeeFolderClass *)((CamelObject *)vf)->klass)->set_expression(vf, query); + struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); + GList *node; + + CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); + + /* no change, do nothing */ + if ((vf->expression && query && strcmp(vf->expression, query) == 0) + || (vf->expression == NULL && query == NULL)) { + CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); + return; + } + + g_free(vf->expression); + if (query) + vf->expression = g_strdup(query); + + node = p->folders; + while (node) { + CamelFolder *f = node->data; + + if (vee_folder_build_folder(vf, f, NULL) == -1) + break; + + node = node->next; + } + + CAMEL_VEE_FOLDER_LOCK(vf, changed_lock); + g_list_free(p->folders_changed); + p->folders_changed = NULL; + CAMEL_VEE_FOLDER_UNLOCK(vf, changed_lock); + + CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); } /** @@ -219,9 +349,9 @@ camel_vee_folder_add_folder(CamelVeeFolder *vf, CamelFolder *sub) camel_object_hook_event((CamelObject *)sub, "folder_changed", (CamelObjectEventHookFunc)folder_changed, vf); camel_object_hook_event((CamelObject *)sub, "deleted", (CamelObjectEventHookFunc)subfolder_deleted, vf); - camel_object_hook_event((CamelObject *)sub, "renamed", (CamelObjectEventHookFunc)folder_renamed, vf); + camel_object_hook_event((CamelObject *)sub, "renamed", (CamelObjectEventHookFunc)subfolder_renamed, vf); - ((CamelVeeFolderClass *)((CamelObject *)vf)->klass)->add_folder(vf, sub); + vee_folder_build_folder(vf, sub, NULL); } /** @@ -235,6 +365,7 @@ void camel_vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *sub) { struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); + int killun = FALSE; int i; CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; @@ -251,7 +382,7 @@ camel_vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *sub) camel_object_unhook_event((CamelObject *)sub, "folder_changed", (CamelObjectEventHookFunc) folder_changed, vf); camel_object_unhook_event((CamelObject *)sub, "deleted", (CamelObjectEventHookFunc) subfolder_deleted, vf); - camel_object_unhook_event((CamelObject *)sub, "renamed", (CamelObjectEventHookFunc) folder_renamed, vf); + camel_object_unhook_event((CamelObject *)sub, "renamed", (CamelObjectEventHookFunc) subfolder_renamed, vf); p->folders = g_list_remove(p->folders, sub); @@ -270,6 +401,7 @@ camel_vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *sub) /* if folder deleted, then blow it away from unmatched always, and remove all refs to it */ if (sub->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED) { while (g_list_find(up->folders, sub)) { + killun = TRUE; up->folders = g_list_remove(up->folders, sub); camel_object_unref((CamelObject *)sub); @@ -290,29 +422,18 @@ camel_vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *sub) camel_folder_thaw(sub); CAMEL_FOLDER_UNLOCK(folder_unmatched, change_lock); } + if (g_list_find(up->folders, sub) == NULL) { + killun = TRUE; + } } CAMEL_VEE_FOLDER_UNLOCK(folder_unmatched, subfolder_lock); } - ((CamelVeeFolderClass *)((CamelObject *)vf)->klass)->remove_folder(vf, sub); + vee_folder_remove_folder(vf, sub, killun); camel_object_unref((CamelObject *)sub); } -/** - * camel_vee_folder_rebuild_folder: - * @vf: Virtual Folder object - * @sub: source CamelFolder to add to @vf - * @ex: Exception. - * - * Rebuild the folder @sub, if it should be. - **/ -int -camel_vee_folder_rebuild_folder(CamelVeeFolder *vf, CamelFolder *sub, CamelException *ex) -{ - return ((CamelVeeFolderClass *)((CamelObject *)vf)->klass)->rebuild_folder(vf, sub, ex); -} - static void remove_folders(CamelFolder *folder, CamelFolder *foldercopy, CamelVeeFolder *vf) { @@ -334,6 +455,7 @@ camel_vee_folder_set_folders(CamelVeeFolder *vf, GList *folders) GHashTable *remove = g_hash_table_new(NULL, NULL); GList *l; CamelFolder *folder; + int changed; /* setup a table of all folders we have currently */ CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); @@ -351,6 +473,15 @@ camel_vee_folder_set_folders(CamelVeeFolder *vf, GList *folders) if ((folder = g_hash_table_lookup(remove, l->data))) { g_hash_table_remove(remove, folder); camel_object_unref((CamelObject *)folder); + + /* if this was a changed folder, re-update it while we're here */ + CAMEL_VEE_FOLDER_LOCK(vf, changed_lock); + changed = g_list_find(p->folders_changed, folder) != NULL; + if (changed) + p->folders_changed = g_list_remove(p->folders_changed, folder); + CAMEL_VEE_FOLDER_UNLOCK(vf, changed_lock); + if (changed) + vee_folder_build_folder(vf, folder, NULL); } else { camel_vee_folder_add_folder(vf, l->data); } @@ -409,25 +540,21 @@ camel_vee_folder_hash_folder(CamelFolder *folder, char buffer[8]) CamelFolder * camel_vee_folder_get_location(CamelVeeFolder *vf, const CamelVeeMessageInfo *vinfo, char **realuid) { - CamelFolder *folder; - - folder = vinfo->real->summary->folder; - /* locking? yes? no? although the vfolderinfo is valid when obtained the folder in it might not necessarily be so ...? */ - if (CAMEL_IS_VEE_FOLDER(folder)) { - CamelFolder *res; + if (CAMEL_IS_VEE_FOLDER(vinfo->folder)) { + CamelFolder *folder; const CamelVeeMessageInfo *vfinfo; - vfinfo = (CamelVeeMessageInfo *)camel_folder_get_message_info(folder, camel_message_info_uid(vinfo)+8); - res = camel_vee_folder_get_location((CamelVeeFolder *)folder, vfinfo, realuid); - camel_folder_free_message_info(folder, (CamelMessageInfo *)vfinfo); - return res; + vfinfo = (CamelVeeMessageInfo *)camel_folder_get_message_info(vinfo->folder, camel_message_info_uid(vinfo)+8); + folder = camel_vee_folder_get_location((CamelVeeFolder *)vinfo->folder, vfinfo, realuid); + camel_folder_free_message_info(vinfo->folder, (CamelMessageInfo *)vfinfo); + return folder; } else { if (realuid) *realuid = g_strdup(camel_message_info_uid(vinfo)+8); - return folder; + return vinfo->folder; } } @@ -446,7 +573,7 @@ static void vee_refresh_info(CamelFolder *folder, CamelException *ex) while (node) { CamelFolder *f = node->data; - if (camel_vee_folder_rebuild_folder(vf, f, ex) == -1) + if (vee_folder_build_folder(vf, f, ex) == -1) break; node = node->next; @@ -479,7 +606,7 @@ vee_sync(CamelFolder *folder, gboolean expunge, CamelException *ex) /* auto update vfolders shouldn't need a rebuild */ if ((vf->flags & CAMEL_STORE_VEE_FOLDER_AUTO) == 0 - && camel_vee_folder_rebuild_folder(vf, f, ex) == -1) + && vee_folder_build_folder(vf, f, ex) == -1) break; node = node->next; @@ -511,8 +638,8 @@ vee_get_message(CamelFolder *folder, const char *uid, CamelException *ex) mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, uid); if (mi) { - msg = camel_folder_get_message(mi->real->summary->folder, camel_message_info_uid(mi)+8, ex); - camel_message_info_free((CamelMessageInfo *)mi); + msg = camel_folder_get_message(mi->folder, camel_message_info_uid(mi)+8, ex); + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)mi); } else { camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("No such message %s in %s"), uid, @@ -632,11 +759,53 @@ vee_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); g_hash_table_destroy(searched); - g_ptr_array_free(folder_uids, TRUE); + g_ptr_array_free(folder_uids, 0); return result; } +static gboolean +vee_set_message_flags(CamelFolder *folder, const char *uid, guint32 flags, guint32 set) +{ + CamelVeeMessageInfo *mi; + int res = FALSE; + + mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, uid); + if (mi) { + res = camel_folder_set_message_flags(mi->folder, camel_message_info_uid(mi) + 8, flags, set); + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)mi); + res = res || ((CamelFolderClass *)camel_vee_folder_parent)->set_message_flags(folder, uid, flags, set); + } + + return res; +} + +static void +vee_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value) +{ + CamelVeeMessageInfo *mi; + + mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, uid); + if (mi) { + camel_folder_set_message_user_flag(mi->folder, camel_message_info_uid(mi) + 8, name, value); + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)mi); + ((CamelFolderClass *)camel_vee_folder_parent)->set_message_user_flag(folder, uid, name, value); + } +} + +static void +vee_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value) +{ + CamelVeeMessageInfo *mi; + + mi = (CamelVeeMessageInfo *)camel_folder_summary_uid(folder->summary, uid); + if (mi) { + camel_folder_set_message_user_tag(mi->folder, camel_message_info_uid(mi) + 8, name, value); + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)mi); + ((CamelFolderClass *)camel_vee_folder_parent)->set_message_user_tag(folder, uid, name, value); + } +} + static void vee_append_message(CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, char **appended_uid, CamelException *ex) { @@ -651,35 +820,56 @@ vee_transfer_messages_to (CamelFolder *folder, GPtrArray *uids, CamelFolder *des static void vee_rename(CamelFolder *folder, const char *new) { - /*CamelVeeFolder *vf = (CamelVeeFolder *)folder;*/ + CamelVeeFolder *vf = (CamelVeeFolder *)folder; + + g_free(vf->vname); + vf->vname = g_strdup(new); ((CamelFolderClass *)camel_vee_folder_parent)->rename(folder, new); } -static void vee_delete(CamelFolder *folder) -{ - struct _CamelVeeFolderPrivate *p = _PRIVATE(folder); - - /* NB: this is never called on UNMTACHED */ - - CAMEL_VEE_FOLDER_LOCK(folder, subfolder_lock); - while (p->folders) { - CamelFolder *f = p->folders->data; +/* ********************************************************************** * + utility functions */ - camel_object_ref(f); - CAMEL_VEE_FOLDER_UNLOCK(folder, subfolder_lock); +/* must be called with summary_lock held */ +static CamelVeeMessageInfo * +vee_folder_add_info(CamelVeeFolder *vf, CamelFolder *f, CamelMessageInfo *info, const char hash[8]) +{ + CamelVeeMessageInfo *mi; + char *vuid; + const char *uid; + CamelFolder *folder = (CamelFolder *)vf; + CamelMessageInfo *dinfo; - camel_vee_folder_remove_folder((CamelVeeFolder *)folder, f); - camel_object_unref(f); - CAMEL_VEE_FOLDER_LOCK(folder, subfolder_lock); + uid = camel_message_info_uid(info); + vuid = alloca(strlen(uid)+9); + memcpy(vuid, hash, 8); + strcpy(vuid+8, uid); + dinfo = camel_folder_summary_uid(folder->summary, vuid); + if (dinfo) { + d(printf("w:clash, we already have '%s' in summary\n", vuid)); + camel_folder_summary_info_free(folder->summary, dinfo); + return NULL; } - CAMEL_VEE_FOLDER_LOCK(folder, subfolder_lock); - ((CamelFolderClass *)camel_vee_folder_parent)->delete(folder); -} + d(printf("adding vuid %s to %s\n", vuid, vf->vname)); + + mi = (CamelVeeMessageInfo *)camel_folder_summary_info_new(folder->summary); + camel_message_info_dup_to(info, (CamelMessageInfo *)mi); +#ifdef DOEPOOLV + mi->info.strings = e_poolv_set(mi->info.strings, CAMEL_MESSAGE_INFO_UID, vuid, FALSE); +#elif defined (DOESTRV) + mi->info.strings = e_strv_set_ref(mi->info.strings, CAMEL_MESSAGE_INFO_UID, vuid); + mi->info.strings = e_strv_pack(mi->info.strings); +#else + g_free(mi->info.uid); + mi->info.uid = g_strdup(vuid); +#endif + mi->folder = f; + camel_folder_summary_add(folder->summary, (CamelMessageInfo *)mi); -/* ********************************************************************** * - utility functions */ + return mi; +} /* must be called with summary_lock held */ static CamelVeeMessageInfo * @@ -690,14 +880,14 @@ vee_folder_add_uid(CamelVeeFolder *vf, CamelFolder *f, const char *inuid, const info = camel_folder_get_message_info(f, inuid); if (info) { - mi = camel_vee_summary_add((CamelVeeSummary *)((CamelFolder *)vf)->summary, info, hash); + mi = vee_folder_add_info(vf, f, info, hash); camel_folder_free_message_info(f, info); } return mi; } static void -vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source) +vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source, int killun) { int i, count, n, still = FALSE, start, last; char *oldkey; @@ -708,15 +898,10 @@ vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source) void *oldval; CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; GHashTable *unmatched_uids = vf->parent_vee_store ? vf->parent_vee_store->unmatched_uids : NULL; - CamelFolderSummary *ssummary = source->summary; - int killun = FALSE; - + if (vf == folder_unmatched) return; - if ((source->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED)) - killun = TRUE; - CAMEL_VEE_FOLDER_LOCK(vf, summary_lock); if (folder_unmatched != NULL) { @@ -739,7 +924,7 @@ vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source) CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)camel_folder_summary_index(((CamelFolder *)folder_unmatched)->summary, i); if (mi) { - if (mi->real->summary == ssummary) { + if (mi->folder == source) { camel_folder_change_info_remove_uid(folder_unmatched->changes, camel_message_info_uid(mi)); if (last == -1) { last = start = i; @@ -751,7 +936,7 @@ vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source) start = last = i; } } - camel_message_info_free((CamelMessageInfo *)mi); + camel_folder_summary_info_free(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)mi); } } if (last != -1) @@ -765,7 +950,7 @@ vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source) for (i=0;i<count;i++) { CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)camel_folder_summary_index(folder->summary, i); if (mi) { - if (mi->real->summary == ssummary) { + if (mi->folder == source) { const char *uid = camel_message_info_uid(mi); camel_folder_change_info_remove_uid(vf->changes, uid); @@ -800,7 +985,7 @@ vee_folder_remove_folder(CamelVeeFolder *vf, CamelFolder *source) } } } - camel_message_info_free((CamelMessageInfo *)mi); + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)mi); } } @@ -860,7 +1045,7 @@ unmatched_check_uid(char *uidin, void *value, struct _update_data *u) if (mi) { camel_folder_summary_remove(((CamelFolder *)u->folder_unmatched)->summary, (CamelMessageInfo *)mi); camel_folder_change_info_remove_uid(u->folder_unmatched->changes, uid); - camel_message_info_free((CamelMessageInfo *)mi); + camel_folder_summary_info_free(((CamelFolder *)u->folder_unmatched)->summary, (CamelMessageInfo *)mi); } } } @@ -889,7 +1074,7 @@ folder_added_uid(char *uidin, void *value, struct _update_data *u) /* build query contents for a single folder */ static int -vee_rebuild_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException *ex) +vee_folder_build_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException *ex) { GPtrArray *match, *all; GHashTable *allhash, *matchhash; @@ -900,7 +1085,6 @@ vee_rebuild_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException *ex) CamelFolderChangeInfo *vf_changes = NULL, *unmatched_changes = NULL; CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; GHashTable *unmatched_uids = vf->parent_vee_store ? vf->parent_vee_store->unmatched_uids : NULL; - CamelFolderSummary *ssummary = source->summary; if (vf == folder_unmatched) return 0; @@ -945,7 +1129,7 @@ vee_rebuild_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException *ex) CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)camel_folder_summary_index(folder->summary, i); if (mi) { - if (mi->real->summary == ssummary) { + if (mi->folder == source) { char *uid = (char *)camel_message_info_uid(mi), *oldkey; void *oldval; @@ -975,7 +1159,7 @@ vee_rebuild_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException *ex) g_hash_table_remove(matchhash, uid+8); } } - camel_message_info_free((CamelMessageInfo *)mi); + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)mi); } } if (last != -1) @@ -991,7 +1175,7 @@ vee_rebuild_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException *ex) CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *)camel_folder_summary_index(((CamelFolder *)folder_unmatched)->summary, i); if (mi) { - if (mi->real->summary == ssummary) { + if (mi->folder == source) { char *uid = (char *)camel_message_info_uid(mi); if (g_hash_table_lookup(allhash, uid+8) == NULL) { @@ -1003,7 +1187,7 @@ vee_rebuild_folder(CamelVeeFolder *vf, CamelFolder *source, CamelException *ex) g_hash_table_remove(allhash, uid+8); } } - camel_message_info_free((CamelMessageInfo *)mi); + camel_folder_summary_info_free(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)mi); } } @@ -1110,7 +1294,7 @@ folder_changed_remove_uid(CamelFolder *sub, const char *uid, const char hash[8], if (vinfo) { camel_folder_change_info_remove_uid(vf->changes, vuid); camel_folder_summary_remove(folder->summary, (CamelMessageInfo *)vinfo); - camel_message_info_free((CamelMessageInfo *)vinfo); + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)vinfo); } if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !CAMEL_IS_VEE_FOLDER(sub) && folder_unmatched != NULL) { @@ -1165,23 +1349,45 @@ folder_changed_change_uid(CamelFolder *sub, const char *uid, const char hash[8], info = camel_folder_get_message_info(sub, uid); if (info) { if (vinfo) { - camel_folder_change_info_change_uid(vf->changes, vuid); - camel_message_info_free((CamelMessageInfo *)vinfo); + int changed = FALSE; + + if (vinfo->info.flags != info->flags){ + vinfo->info.flags = info->flags; + changed = TRUE; + } + + changed |= camel_flag_list_copy(&vinfo->info.user_flags, &info->user_flags); + changed |= camel_tag_list_copy(&vinfo->info.user_tags, &info->user_tags); + if (changed) + camel_folder_change_info_change_uid(vf->changes, vuid); + + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)vinfo); } if (uinfo) { - camel_folder_change_info_change_uid(folder_unmatched->changes, vuid); - camel_message_info_free((CamelMessageInfo *)uinfo); + int changed = FALSE; + + if (uinfo->info.flags != info->flags){ + uinfo->info.flags = info->flags; + changed = TRUE; + } + + changed |= camel_flag_list_copy(&uinfo->info.user_flags, &info->user_flags); + changed |= camel_tag_list_copy(&uinfo->info.user_tags, &info->user_tags); + if (changed) + camel_folder_change_info_change_uid(folder_unmatched->changes, vuid); + + camel_folder_summary_info_free(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)uinfo); } camel_folder_free_message_info(sub, info); } else { if (vinfo) { folder_changed_remove_uid(sub, uid, hash, FALSE, vf); - camel_message_info_free((CamelMessageInfo *)vinfo); + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)vinfo); } if (uinfo) - camel_message_info_free((CamelMessageInfo *)uinfo); + camel_folder_summary_info_free(((CamelFolder *)folder_unmatched)->summary, (CamelMessageInfo *)uinfo); } } } @@ -1257,7 +1463,7 @@ folder_changed_change(CamelSession *session, CamelSessionThreadMsg *msg) g_ptr_array_add(newchanged, (char *)uid); } else { g_ptr_array_add(always_changed, (char *)uid); - camel_message_info_free((CamelMessageInfo *)vinfo); + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)vinfo); } } changed = newchanged; @@ -1361,7 +1567,7 @@ folder_changed_change(CamelSession *session, CamelSessionThreadMsg *msg) dd(printf(" removing uid '%s' [did match]\n", uid)); folder_changed_remove_uid(sub, uid, hash, TRUE, vf); } - camel_message_info_free((CamelMessageInfo *)vinfo); + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)vinfo); } } g_hash_table_destroy(matches_hash); @@ -1437,7 +1643,7 @@ static CamelSessionThreadOps folder_changed_ops = { }; static void -folder_changed_base(CamelVeeFolder *vf, CamelFolder *sub, CamelFolderChangeInfo *changes) +folder_changed(CamelFolder *sub, CamelFolderChangeInfo *changes, CamelVeeFolder *vf) { struct _folder_changed_msg *m; CamelSession *session = ((CamelService *)((CamelFolder *)vf)->parent_store)->session; @@ -1452,12 +1658,6 @@ folder_changed_base(CamelVeeFolder *vf, CamelFolder *sub, CamelFolderChangeInfo camel_session_thread_queue(session, &m->msg, 0); } -static void -folder_changed(CamelFolder *sub, CamelFolderChangeInfo *changes, CamelVeeFolder *vf) -{ - ((CamelVeeFolderClass *)((CamelObject *)vf)->klass)->folder_changed(vf, sub, changes); -} - /* track vanishing folders */ static void subfolder_deleted(CamelFolder *f, void *event_data, CamelVeeFolder *vf) @@ -1472,7 +1672,6 @@ subfolder_renamed_update(CamelVeeFolder *vf, CamelFolder *sub, char hash[8]) CamelFolderChangeInfo *changes = NULL; CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; GHashTable *unmatched_uids = vf->parent_vee_store ? vf->parent_vee_store->unmatched_uids : NULL; - CamelFolderSummary *ssummary = sub->summary; CAMEL_VEE_FOLDER_LOCK(vf, summary_lock); @@ -1484,7 +1683,7 @@ subfolder_renamed_update(CamelVeeFolder *vf, CamelFolder *sub, char hash[8]) if (mi == NULL) continue; - if (mi->real->summary == ssummary) { + if (mi->folder == sub) { char *uid = (char *)camel_message_info_uid(mi); char *oldkey; void *oldval; @@ -1509,7 +1708,7 @@ subfolder_renamed_update(CamelVeeFolder *vf, CamelFolder *sub, char hash[8]) } } - camel_message_info_free((CamelMessageInfo *)mi); + camel_folder_summary_info_free(((CamelFolder *)vf)->summary, (CamelMessageInfo *)mi); } if (camel_folder_change_info_changed(vf->changes)) { @@ -1526,7 +1725,7 @@ subfolder_renamed_update(CamelVeeFolder *vf, CamelFolder *sub, char hash[8]) } static void -folder_renamed_base(CamelVeeFolder *vf, CamelFolder *f, const char *old) +subfolder_renamed(CamelFolder *f, void *event_data, CamelVeeFolder *vf) { char hash[8]; CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; @@ -1544,12 +1743,6 @@ folder_renamed_base(CamelVeeFolder *vf, CamelFolder *f, const char *old) } static void -folder_renamed(CamelFolder *sub, const char *old, CamelVeeFolder *vf) -{ - ((CamelVeeFolderClass *)((CamelObject *)vf)->klass)->folder_renamed(vf, sub, old); -} - -static void vee_freeze (CamelFolder *folder) { CamelVeeFolder *vfolder = (CamelVeeFolder *)folder; @@ -1594,148 +1787,3 @@ vee_thaw(CamelFolder *folder) /* call parent implementation */ CAMEL_FOLDER_CLASS (camel_vee_folder_parent)->thaw(folder); } - -/* vfolder base implementaitons */ -static void -vee_add_folder(CamelVeeFolder *vf, CamelFolder *sub) -{ - vee_rebuild_folder(vf, sub, NULL); -} - -static void -vee_remove_folder(CamelVeeFolder *vf, CamelFolder *sub) -{ - vee_folder_remove_folder(vf, sub); -} - -static void -vee_set_expression(CamelVeeFolder *vf, const char *query) -{ - struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); - GList *node; - - CAMEL_VEE_FOLDER_LOCK(vf, subfolder_lock); - - /* no change, do nothing */ - if ((vf->expression && query && strcmp(vf->expression, query) == 0) - || (vf->expression == NULL && query == NULL)) { - CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); - return; - } - - g_free(vf->expression); - if (query) - vf->expression = g_strdup(query); - - node = p->folders; - while (node) { - CamelFolder *f = node->data; - - if (camel_vee_folder_rebuild_folder(vf, f, NULL) == -1) - break; - - node = node->next; - } - - CAMEL_VEE_FOLDER_LOCK(vf, changed_lock); - g_list_free(p->folders_changed); - p->folders_changed = NULL; - CAMEL_VEE_FOLDER_UNLOCK(vf, changed_lock); - - CAMEL_VEE_FOLDER_UNLOCK(vf, subfolder_lock); -} - -static void -camel_vee_folder_class_init (CamelVeeFolderClass *klass) -{ - CamelFolderClass *folder_class = (CamelFolderClass *) klass; - - camel_vee_folder_parent = CAMEL_FOLDER_CLASS(camel_type_get_global_classfuncs (camel_folder_get_type ())); - - folder_class->refresh_info = vee_refresh_info; - folder_class->sync = vee_sync; - folder_class->expunge = vee_expunge; - - folder_class->get_message = vee_get_message; - folder_class->append_message = vee_append_message; - folder_class->transfer_messages_to = vee_transfer_messages_to; - - folder_class->search_by_expression = vee_search_by_expression; - folder_class->search_by_uids = vee_search_by_uids; - - folder_class->rename = vee_rename; - folder_class->delete = vee_delete; - - folder_class->freeze = vee_freeze; - folder_class->thaw = vee_thaw; - - klass->set_expression = vee_set_expression; - klass->add_folder = vee_add_folder; - klass->remove_folder = vee_remove_folder; - klass->rebuild_folder = vee_rebuild_folder; - klass->folder_changed = folder_changed_base; - klass->folder_renamed = folder_renamed_base; -} - -static void -camel_vee_folder_init (CamelVeeFolder *obj) -{ - struct _CamelVeeFolderPrivate *p; - CamelFolder *folder = (CamelFolder *)obj; - - p = _PRIVATE(obj) = g_malloc0(sizeof(*p)); - - folder->folder_flags |= (CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | - CAMEL_FOLDER_HAS_SEARCH_CAPABILITY); - - /* FIXME: what to do about user flags if the subfolder doesn't support them? */ - folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | - CAMEL_MESSAGE_DELETED | - CAMEL_MESSAGE_DRAFT | - CAMEL_MESSAGE_FLAGGED | - CAMEL_MESSAGE_SEEN; - - obj->changes = camel_folder_change_info_new(); - obj->search = camel_folder_search_new(); - - p->summary_lock = g_mutex_new(); - p->subfolder_lock = g_mutex_new(); - p->changed_lock = g_mutex_new(); -} - -static void -camel_vee_folder_finalise (CamelObject *obj) -{ - CamelVeeFolder *vf = (CamelVeeFolder *)obj; - struct _CamelVeeFolderPrivate *p = _PRIVATE(vf); - CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; - GList *node; - - /* TODO: there may be other leaks? */ - - /* This may invoke sub-classes with partially destroyed state, they must deal with this */ - if (vf == folder_unmatched) { - for (node = p->folders;node;node = g_list_next(node)) - camel_object_unref(node->data); - } else { - while (p->folders) { - CamelFolder *f = p->folders->data; - - camel_vee_folder_remove_folder(vf, f); - } - } - - g_free(vf->expression); - - g_list_free(p->folders); - g_list_free(p->folders_changed); - - camel_folder_change_info_free(vf->changes); - camel_object_unref((CamelObject *)vf->search); - - g_mutex_free(p->summary_lock); - g_mutex_free(p->subfolder_lock); - g_mutex_free(p->changed_lock); - - g_free(p); -} diff --git a/camel/camel-vee-folder.h b/camel/camel-vee-folder.h index bccdf2c7ab..79f13a7280 100644 --- a/camel/camel-vee-folder.h +++ b/camel/camel-vee-folder.h @@ -1,8 +1,8 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* - * Copyright (C) 2000 Ximian Inc. + * Copyright (C) 2000 Ximian Inc. * - * Authors: Michael Zucchi <notzed@ximian.com> + * Authors: Michael Zucchi <notzed@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 @@ -30,7 +30,6 @@ extern "C" { #include <glib.h> #include <camel/camel-folder.h> -#include <camel/camel-vee-summary.h> #define CAMEL_VEE_FOLDER(obj) CAMEL_CHECK_CAST (obj, camel_vee_folder_get_type (), CamelVeeFolder) #define CAMEL_VEE_FOLDER_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_vee_folder_get_type (), CamelVeeFolderClass) @@ -39,12 +38,19 @@ extern "C" { typedef struct _CamelVeeFolder CamelVeeFolder; typedef struct _CamelVeeFolderClass CamelVeeFolderClass; +/* our message info includes the parent folder */ +typedef struct _CamelVeeMessageInfo { + CamelMessageInfo info; + CamelFolder *folder; +} CamelVeeMessageInfo; + struct _CamelVeeFolder { CamelFolder parent; struct _CamelVeeFolderPrivate *priv; char *expression; /* query expression */ + char *vname; /* local name */ guint32 flags; /* folder open flags */ @@ -58,19 +64,6 @@ struct _CamelVeeFolder { struct _CamelVeeFolderClass { CamelFolderClass parent_class; - - /* TODO: Some of this may need some additional work/thinking through, it works for now*/ - - void (*add_folder)(CamelVeeFolder *, CamelFolder *); - void (*remove_folder)(CamelVeeFolder *, CamelFolder *); - int (*rebuild_folder)(CamelVeeFolder *, CamelFolder *, CamelException *); - - void (*set_expression)(CamelVeeFolder *, const char *); - - /* Called for a folder-changed event on a source folder */ - void (*folder_changed)(CamelVeeFolder *, CamelFolder *sub, CamelFolderChangeInfo *changes); - /* Called for a folder-renamed event on a source folder */ - void (*folder_renamed)(CamelVeeFolder *, CamelFolder *sub, const char *old); }; #define CAMEL_UNMATCHED_NAME "UNMATCHED" @@ -79,12 +72,11 @@ CamelType camel_vee_folder_get_type (void); CamelFolder *camel_vee_folder_new (CamelStore *parent_store, const char *name, guint32 flags); void camel_vee_folder_construct (CamelVeeFolder *vf, CamelStore *parent_store, const char *name, guint32 flags); -CamelFolder *camel_vee_folder_get_location(CamelVeeFolder *vf, const struct _CamelVeeMessageInfo *vinfo, char **realuid); +CamelFolder *camel_vee_folder_get_location(CamelVeeFolder *vf, const CamelVeeMessageInfo *vinfo, char **realuid); void camel_vee_folder_add_folder (CamelVeeFolder *vf, CamelFolder *sub); void camel_vee_folder_remove_folder (CamelVeeFolder *vf, CamelFolder *sub); void camel_vee_folder_set_folders (CamelVeeFolder *vf, GList *folders); -int camel_vee_folder_rebuild_folder(CamelVeeFolder *vf, CamelFolder *sub, CamelException *ex); void camel_vee_folder_set_expression (CamelVeeFolder *vf, const char *expr); void camel_vee_folder_hash_folder (CamelFolder *folder, char buffer[8]); diff --git a/camel/camel-vee-store.c b/camel/camel-vee-store.c index 8068339f28..b562ad4a60 100644 --- a/camel/camel-vee-store.c +++ b/camel/camel-vee-store.c @@ -27,7 +27,6 @@ #include "camel-vee-folder.h" #include "camel-private.h" -#include "camel-i18n.h" #include <string.h> @@ -179,8 +178,8 @@ vee_get_folder (CamelStore *store, const char *folder_name, guint32 flags, Camel vf = (CamelVeeFolder *)camel_vee_folder_new(store, folder_name, flags); if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0) { /* Check that parents exist, if not, create dummy ones */ - name = alloca(strlen(((CamelFolder *)vf)->full_name)+1); - strcpy(name, ((CamelFolder *)vf)->full_name); + name = alloca(strlen(vf->vname)+1); + strcpy(name, vf->vname); p = name; while ( (p = strchr(p, '/'))) { *p = 0; @@ -198,7 +197,7 @@ vee_get_folder (CamelStore *store, const char *folder_name, guint32 flags, Camel *p++='/'; } - change_folder(store, ((CamelFolder *)vf)->full_name, CHANGE_ADD, camel_folder_get_message_count((CamelFolder *)vf)); + change_folder(store, vf->vname, CHANGE_ADD, camel_folder_get_message_count((CamelFolder *)vf)); } return (CamelFolder *)vf; diff --git a/camel/providers/groupwise/camel-gw-listener.c b/camel/providers/groupwise/camel-gw-listener.c index 1f6eaf6267..9da66d6b6d 100644 --- a/camel/providers/groupwise/camel-gw-listener.c +++ b/camel/providers/groupwise/camel-gw-listener.c @@ -162,7 +162,7 @@ lookup_account_info (const char *key) #define SELECTED_TASKS "/apps/evolution/calendar/tasks/selected_tasks" static void -add_esource (const char *conf_key, const char *group_name, const char *source_name, CamelURL *url) +add_esource (const char *conf_key, const char *group_name, const char* source_name, const char *username, const char* relative_uri, const char *soap_port, const char *use_ssl) { ESourceList *source_list; ESourceGroup *group; @@ -170,45 +170,20 @@ add_esource (const char *conf_key, const char *group_name, const char *source_n GConfClient* client; GSList *ids, *temp ; char *source_selection_key; - char *relative_uri; - const char *soap_port; - const char * use_ssl; - const char *poa_address; - const char *offline_sync; - - - poa_address = camel_url_get_param (url, "poa"); - if (!poa_address || strlen (poa_address) ==0) - return; - soap_port = camel_url_get_param (url, "soap_port"); - - if (!soap_port || strlen (soap_port) == 0) - soap_port = "7181"; - use_ssl = camel_url_get_param (url, "soap_ssl"); - if (use_ssl) - use_ssl = "always"; - else - use_ssl = NULL; - - offline_sync = camel_url_get_param (url, "offline_sync"); - client = gconf_client_get_default(); source_list = e_source_list_new_for_gconf (client, conf_key); group = e_source_group_new (group_name, GROUPWISE_URI_PREFIX); - if (!e_source_list_add_group (source_list, group, -1)) + if ( !e_source_list_add_group (source_list, group, -1)) return; - relative_uri = g_strdup_printf ("%s@%s/", url->user, poa_address); - + source = e_source_new (source_name, relative_uri); e_source_set_property (source, "auth", "1"); - e_source_set_property (source, "username", url->user); - e_source_set_property (source, "port", camel_url_get_param (url, "soap_port")); + e_source_set_property (source, "username", username); + e_source_set_property (source, "port", soap_port); e_source_set_property (source, "auth-domain", "Groupwise"); - e_source_set_property (source, "use_ssl", camel_url_get_param (url, "use_ssl")); - e_source_set_property (source, "offline_sync", offline_sync); - // e_source_set_property (source, "offline_sync", ); + e_source_set_property (source, "use_ssl", use_ssl); e_source_group_add_source (group, source, -1); e_source_list_sync (source_list, NULL); @@ -231,7 +206,6 @@ add_esource (const char *conf_key, const char *group_name, const char *source_n g_object_unref (group); g_object_unref (source_list); g_object_unref (client); - g_free (relative_uri); } @@ -308,7 +282,7 @@ remove_esource (const char *conf_key, const char *group_name, char* source_name, /* looks up for e-source with having same info as old_account_info and changes its values passed in new values */ static void -modify_esource (const char* conf_key, GwAccountInfo *old_account_info, const char* new_group_name, CamelURL *new_url) +modify_esource (const char* conf_key, GwAccountInfo *old_account_info, const char* new_group_name, const char *username, const char* new_relative_uri, const char *soap_port, const char *use_ssl) { ESourceList *list; ESourceGroup *group; @@ -320,15 +294,11 @@ modify_esource (const char* conf_key, GwAccountInfo *old_account_info, const cha gboolean found_group; GConfClient* client; const char *poa_address; - char *new_relative_uri; - const char *new_poa_address; - + url = camel_url_new (old_account_info->source_url, NULL); poa_address = camel_url_get_param (url, "poa"); if (!poa_address || strlen (poa_address) ==0) return; - new_poa_address = camel_url_get_param (new_url, "poa"); - old_relative_uri = g_strdup_printf ("%s@%s/", url->user, poa_address); client = gconf_client_get_default (); list = e_source_list_new_for_gconf (client, conf_key); @@ -351,16 +321,13 @@ modify_esource (const char* conf_key, GwAccountInfo *old_account_info, const cha if (strcmp (e_source_peek_relative_uri (source), old_relative_uri) == 0) { - new_relative_uri = g_strdup_printf ("%s@%s/", new_url->user, new_poa_address); e_source_group_set_name (group, new_group_name); e_source_set_relative_uri (source, new_relative_uri); - e_source_set_property (source, "username", new_url->user); - e_source_set_property (source, "port", camel_url_get_param (new_url,"soap_port")); - e_source_set_property (source, "use_ssl", camel_url_get_param (url, "soap_ssl")); - e_source_set_property (source, "offline_sync", camel_url_get_param (url, "offline_sync")); + e_source_set_property (source, "username", username); + e_source_set_property (source, "port", soap_port); + e_source_set_property (source, "use_ssl", use_ssl); e_source_list_sync (list, NULL); found_group = TRUE; - g_free (new_relative_uri); break; } } @@ -371,7 +338,6 @@ modify_esource (const char* conf_key, GwAccountInfo *old_account_info, const cha g_object_unref (client); camel_url_free (url); g_free (old_relative_uri); - } /* add sources for calendar and tasks if the account added is groupwise account @@ -402,8 +368,8 @@ add_calendar_tasks_sources (GwAccountInfo *info) use_ssl = NULL; relative_uri = g_strdup_printf ("%s@%s/", url->user, poa_address); - add_esource ("/apps/evolution/calendar/sources", info->name, _("Calendar"), url); - add_esource ("/apps/evolution/tasks/sources", info->name, _("Tasks"), url); + add_esource ("/apps/evolution/calendar/sources", info->name, _("Calendar"), url->user, relative_uri, soap_port, use_ssl); + add_esource ("/apps/evolution/tasks/sources", info->name, _("Tasks"), url->user, relative_uri, soap_port, use_ssl); camel_url_free (url); g_free (relative_uri); @@ -551,7 +517,7 @@ add_addressbook_sources (EAccount *account) e_source_set_property (source, "auth-domain", "Groupwise"); e_source_set_property (source, "port", soap_port); e_source_set_property(source, "user", url->user); - e_source_set_property (source, "offline_sync", camel_url_get_param (url, "offline_sync")); + if (!e_gw_container_get_is_writable (E_GW_CONTAINER(temp_list->data))) e_source_set_property (source, "completion", "true"); if (e_gw_container_get_is_frequent_contacts (E_GW_CONTAINER(temp_list->data))) @@ -593,7 +559,6 @@ modify_addressbook_sources ( EAccount *account, GwAccountInfo *existing_account_ ESource *source; GConfClient *client; const char *poa_address; - url = camel_url_new (existing_account_info->source_url, NULL); if (url == NULL) { @@ -766,6 +731,7 @@ account_changed (EAccountList *account_listener, EAccount *account) { gboolean is_gw_account; CamelURL *old_url, *new_url; + char *relative_uri; const char *old_soap_port, *new_soap_port; GwAccountInfo *existing_account_info; const char *old_use_ssl, *new_use_ssl; @@ -833,9 +799,11 @@ account_changed (EAccountList *account_listener, EAccount *account) account_added (account_listener, account); } else if (strcmp (existing_account_info->name, account->name)) { - modify_esource ("/apps/evolution/calendar/sources", existing_account_info, account->name, new_url); - modify_esource ("/apps/evolution/tasks/sources", existing_account_info, account->name, new_url); + relative_uri = g_strdup_printf ("%s@%s/", new_url->user, new_poa_address); + modify_esource ("/apps/evolution/calendar/sources", existing_account_info, account->name, new_url->user, relative_uri, new_soap_port, new_use_ssl); + modify_esource ("/apps/evolution/tasks/sources", existing_account_info, account->name, new_url->user, relative_uri, new_soap_port, new_use_ssl); modify_addressbook_sources (account, existing_account_info); + g_free (relative_uri); } diff --git a/camel/providers/imap/camel-imap-command.c b/camel/providers/imap/camel-imap-command.c index eeb3ecd302..fdba581fbb 100644 --- a/camel/providers/imap/camel-imap-command.c +++ b/camel/providers/imap/camel-imap-command.c @@ -43,7 +43,7 @@ #include <camel/camel-private.h> #include <camel/camel-utf8.h> #include <camel/camel-session.h> -#include "camel-i18n.h" + extern int camel_verbose_debug; @@ -499,10 +499,16 @@ imap_read_untagged (CamelImapStore *store, char *line, CamelException *ex) fulllen += str->len; g_ptr_array_add (data, str); - + /* Read the next line. */ - if (camel_imap_store_readline (store, &line, ex) < 0) - goto lose; + do { + if (camel_imap_store_readline (store, &line, ex) < 0) + goto lose; + + /* MAJOR HACK ALERT, gropuwise sometimes sends an extra blank line after literals, check that here */ + if (line[0] == 0) + g_warning("Server sent empty line after a literal, assuming in error"); + } while (line[0] == 0); } /* Now reassemble the data. */ diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c index 6cdd96bcf7..d592b819f1 100644 --- a/camel/providers/imap/camel-imap-folder.c +++ b/camel/providers/imap/camel-imap-folder.c @@ -23,6 +23,7 @@ * USA */ + #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -37,8 +38,8 @@ #include <fcntl.h> #include <ctype.h> -/*#include "libedataserver/e-path.h"*/ -#include "libedataserver/e-time-utils.h" +#include "e-util/e-path.h" +#include "e-util/e-time-utils.h" #include "camel-imap-folder.h" #include "camel-imap-command.h" @@ -69,7 +70,6 @@ #include "camel-string-utils.h" #include "camel-file-utils.h" #include "camel-debug.h" -#include "camel-i18n.h" #define d(x) @@ -237,7 +237,7 @@ camel_imap_folder_new (CamelStore *parent, const char *folder_name, camel_folder_construct (folder, parent, folder_name, short_name); summary_file = g_strdup_printf ("%s/summary", folder_dir); - folder->summary = camel_imap_summary_new (folder, summary_file); + folder->summary = camel_imap_summary_new (summary_file); g_free (summary_file); if (!folder->summary) { camel_object_unref (CAMEL_OBJECT (folder)); @@ -387,7 +387,7 @@ camel_imap_folder_selected (CamelFolder *folder, CamelImapResponse *response, info = camel_folder_summary_index (folder->summary, count - 1); val = strtoul (camel_message_info_uid (info), NULL, 10); - camel_message_info_free(info); + camel_folder_summary_info_free (folder->summary, info); if (uid == 0 || uid != val) imap_folder->need_rescan = TRUE; } @@ -470,7 +470,7 @@ imap_rename (CamelFolder *folder, const char *new) char *folders; folders = g_strconcat (imap_store->storage_path, "/folders", NULL); - folder_dir = imap_path_to_physical (folders, new); + folder_dir = e_path_to_physical (folders, new); g_free (folders); summary_path = g_strdup_printf("%s/summary", folder_dir); @@ -575,7 +575,7 @@ imap_rescan (CamelFolder *folder, int exists, CamelException *ex) ok = camel_imap_command_start (store, folder, ex, "UID FETCH 1:%s (FLAGS)", camel_message_info_uid (info)); - camel_message_info_free(info); + camel_folder_summary_info_free (folder->summary, info); if (!ok) { camel_operation_end (NULL); return; @@ -632,7 +632,7 @@ imap_rescan (CamelFolder *folder, int exists, CamelException *ex) iinfo = (CamelImapMessageInfo *)info; if (strcmp (camel_message_info_uid (info), new[i].uid) != 0) { - camel_message_info_free(info); + camel_folder_summary_info_free(folder->summary, info); seq = i + 1; g_array_append_val (removed, seq); i--; @@ -646,8 +646,8 @@ imap_rescan (CamelFolder *folder, int exists, CamelException *ex) server_set = new[i].flags & ~iinfo->server_flags; server_cleared = iinfo->server_flags & ~new[i].flags; - - iinfo->info.flags = (iinfo->info.flags | server_set) & ~server_cleared; + + info->flags = (info->flags | server_set) & ~server_cleared; iinfo->server_flags = new[i].flags; if (changes == NULL) @@ -655,7 +655,7 @@ imap_rescan (CamelFolder *folder, int exists, CamelException *ex) camel_folder_change_info_change_uid(changes, new[i].uid); } - camel_message_info_free(info); + camel_folder_summary_info_free (folder->summary, info); g_free (new[i].uid); } @@ -697,7 +697,7 @@ static GPtrArray * get_matching (CamelFolder *folder, guint32 flags, guint32 mask, char **set) { GPtrArray *matches; - CamelImapMessageInfo *info; + CamelMessageInfo *info; int i, max, range; GString *gset; @@ -706,11 +706,11 @@ get_matching (CamelFolder *folder, guint32 flags, guint32 mask, char **set) max = camel_folder_summary_count (folder->summary); range = -1; for (i = 0; i < max && !UID_SET_FULL (gset->len, UID_SET_LIMIT); i++) { - info = (CamelImapMessageInfo *)camel_folder_summary_index (folder->summary, i); + info = camel_folder_summary_index (folder->summary, i); if (!info) continue; - if ((info->info.flags & mask) != flags) { - camel_message_info_free((CamelMessageInfo *)info); + if ((info->flags & mask) != flags) { + camel_folder_summary_info_free (folder->summary, info); if (range != -1) { if (range != i - 1) { info = matches->pdata[matches->len - 1]; @@ -758,7 +758,7 @@ imap_sync_online (CamelFolder *folder, CamelException *ex) { CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); CamelImapResponse *response = NULL; - CamelImapMessageInfo *info; + CamelMessageInfo *info; CamelException local_ex; GPtrArray *matches; char *set, *flaglist; @@ -779,33 +779,33 @@ imap_sync_online (CamelFolder *folder, CamelException *ex) */ max = camel_folder_summary_count (folder->summary); for (i = 0; i < max; i++) { - if (!(info = (CamelImapMessageInfo *)camel_folder_summary_index (folder->summary, i))) + if (!(info = camel_folder_summary_index (folder->summary, i))) continue; - if (!(info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) { - camel_message_info_free((CamelMessageInfo *)info); + if (!(info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) { + camel_folder_summary_info_free (folder->summary, info); continue; } /* Note: Cyrus is broken and will not accept an empty-set of flags so... if this is true then we want to unset the previously set flags.*/ - unset = !(info->info.flags & folder->permanent_flags); + unset = !(info->flags & folder->permanent_flags); /* Note: get_matching() uses UID_SET_LIMIT to limit the size of the uid-set string. We don't have to loop here to flush all the matching uids because they will be scooped up later by our parent loop (I think?). -- Jeff */ - matches = get_matching (folder, info->info.flags & (folder->permanent_flags | CAMEL_MESSAGE_FOLDER_FLAGGED), + matches = get_matching (folder, info->flags & (folder->permanent_flags | CAMEL_MESSAGE_FOLDER_FLAGGED), folder->permanent_flags | CAMEL_MESSAGE_FOLDER_FLAGGED, &set); - camel_message_info_free(info); + camel_folder_summary_info_free (folder->summary, info); if (matches == NULL) continue; /* FIXME: since we don't know the previously set flags, if unset is TRUE then just unset all the flags? */ - flaglist = imap_create_flag_list (unset ? folder->permanent_flags : info->info.flags & folder->permanent_flags); + flaglist = imap_create_flag_list (unset ? folder->permanent_flags : info->flags & folder->permanent_flags); /* Note: to `unset' flags, use -FLAGS.SILENT (<flag list>) */ response = camel_imap_command (store, folder, &local_ex, @@ -820,15 +820,16 @@ imap_sync_online (CamelFolder *folder, CamelException *ex) if (!camel_exception_is_set (&local_ex)) { for (j = 0; j < matches->len; j++) { info = matches->pdata[j]; - info->info.flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED; - ((CamelImapMessageInfo *) info)->server_flags = info->info.flags & CAMEL_IMAP_SERVER_FLAGS; + info->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED; + ((CamelImapMessageInfo *) info)->server_flags = + info->flags & CAMEL_IMAP_SERVER_FLAGS; } camel_folder_summary_touch (folder->summary); } for (j = 0; j < matches->len; j++) { info = matches->pdata[j]; - camel_message_info_free(&info->info); + camel_folder_summary_info_free (folder->summary, info); } g_ptr_array_free (matches, TRUE); @@ -1166,11 +1167,10 @@ do_append (CamelFolder *folder, CamelMimeMessage *message, CamelStreamFilter *streamfilter; GByteArray *ba; char *flagstr, *end; - guint32 flags; - - flags = camel_message_info_flags(info); - if (flags) - flagstr = imap_create_flag_list (flags); + + /* create flag string param */ + if (info && info->flags) + flagstr = imap_create_flag_list (info->flags); else flagstr = NULL; @@ -1357,7 +1357,7 @@ imap_transfer_offline (CamelFolder *source, GPtrArray *uids, camel_imap_summary_add_offline_uncached (dest->summary, destuid, mi); camel_imap_message_cache_copy (sc, uid, dc, destuid, ex); - camel_message_info_free(mi); + camel_folder_summary_info_free (source->summary, mi); camel_folder_change_info_add_uid (changes, destuid); if (transferred_uids) @@ -1968,12 +1968,12 @@ imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex) { CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapMessageInfo *mi; + CamelMessageInfo *mi; CamelMimeMessage *msg = NULL; CamelStream *stream = NULL; int retry; - mi = (CamelImapMessageInfo *)camel_folder_summary_uid (folder->summary, uid); + mi = camel_folder_summary_uid (folder->summary, uid); if (mi == NULL) { camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message: %s\n %s"), uid, _("No such message")); @@ -2001,11 +2001,11 @@ imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex) /* If the message is small or only 1 part, or server doesn't do 4v1 (properly) fetch it in one piece. */ if (store->server_level < IMAP_LEVEL_IMAP4REV1 || store->braindamaged - || mi->info.size < IMAP_SMALL_BODY_SIZE - || (!content_info_incomplete(mi->info.content) && !mi->info.content->childs)) { + || mi->size < IMAP_SMALL_BODY_SIZE + || (!content_info_incomplete(mi->content) && !mi->content->childs)) { msg = get_message_simple (imap_folder, uid, NULL, ex); } else { - if (content_info_incomplete (mi->info.content)) { + if (content_info_incomplete (mi->content)) { /* For larger messages, fetch the structure and build a message * with offline parts. (We check mi->content->type rather than * mi->content because camel_folder_summary_info_new always creates @@ -2038,7 +2038,7 @@ imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex) } if (body) - imap_parse_body ((const char **) &body, folder, mi->info.content); + imap_parse_body ((const char **) &body, folder, mi->content); if (fetch_data) g_datalist_clear (&fetch_data); @@ -2049,7 +2049,7 @@ imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex) if (camel_debug_start("imap:folder")) { printf("Folder get message '%s' folder info ->\n", uid); - camel_message_info_dump((CamelMessageInfo *)mi); + camel_message_info_dump(mi); camel_debug_end(); } @@ -2059,10 +2059,10 @@ imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex) * fall back to fetching the entire thing and * let the mailer's "bad MIME" code handle it. */ - if (content_info_incomplete (mi->info.content)) + if (content_info_incomplete (mi->content)) msg = get_message_simple (imap_folder, uid, NULL, ex); else - msg = get_message (imap_folder, uid, mi->info.content, ex); + msg = get_message (imap_folder, uid, mi->content, ex); } } while (msg == NULL && retry < 2 @@ -2072,7 +2072,7 @@ done: /* FIXME, this shouldn't be done this way. */ if (msg) camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Source", store->base_url); fail: - camel_message_info_free(&mi->info); + camel_folder_summary_info_free (folder->summary, mi); return msg; } @@ -2201,7 +2201,7 @@ add_message_from_data (CamelFolder *folder, GPtrArray *messages, { CamelMimeMessage *msg; CamelStream *stream; - CamelImapMessageInfo *mi; + CamelMessageInfo *mi; const char *idate; int seq; @@ -2221,14 +2221,14 @@ add_message_from_data (CamelFolder *folder, GPtrArray *messages, return; } - mi = (CamelImapMessageInfo *)camel_folder_summary_info_new_from_message (folder->summary, msg); + mi = camel_folder_summary_info_new_from_message (folder->summary, msg); camel_object_unref (CAMEL_OBJECT (msg)); if ((idate = g_datalist_get_data (&data, "INTERNALDATE"))) - mi->info.date_received = decode_internaldate (idate); + mi->date_received = decode_internaldate (idate); - if (mi->info.date_received == -1) - mi->info.date_received = mi->info.date_sent; + if (mi->date_received == -1) + mi->date_received = mi->date_sent; messages->pdata[seq - first] = mi; } @@ -2253,7 +2253,7 @@ imap_update_summary (CamelFolder *folder, int exists, int i, seq, first, size, got; CamelImapResponseType type; const char *header_spec; - CamelImapMessageInfo *mi, *info; + CamelMessageInfo *mi, *info; CamelStream *stream; char *uid, *resp; GData *data; @@ -2272,9 +2272,9 @@ imap_update_summary (CamelFolder *folder, int exists, seq = camel_folder_summary_count (folder->summary); first = seq + 1; if (seq > 0) { - mi = (CamelImapMessageInfo *)camel_folder_summary_index (folder->summary, seq - 1); + mi = camel_folder_summary_index (folder->summary, seq - 1); uidval = strtoul(camel_message_info_uid (mi), NULL, 10); - camel_message_info_free(&mi->info); + camel_folder_summary_info_free (folder->summary, mi); } else uidval = 0; @@ -2433,23 +2433,24 @@ imap_update_summary (CamelFolder *folder, int exists, continue; } - mi = (CamelImapMessageInfo *)camel_message_info_clone(pmi); + mi = camel_message_info_new (); + camel_message_info_dup_to (pmi, mi); } uid = g_datalist_get_data (&data, "UID"); if (uid) - mi->info.uid = g_strdup (uid); + camel_message_info_set_uid (mi, g_strdup (uid)); flags = GPOINTER_TO_INT (g_datalist_get_data (&data, "FLAGS")); if (flags) { ((CamelImapMessageInfo *)mi)->server_flags = flags; /* "or" them in with the existing flags that may * have been set by summary_info_new_from_message. */ - mi->info.flags |= flags; + mi->flags |= flags; } size = GPOINTER_TO_INT (g_datalist_get_data (&data, "RFC822.SIZE")); if (size) - mi->info.size = size; + mi->size = size; g_datalist_clear (&data); } @@ -2473,7 +2474,7 @@ imap_update_summary (CamelFolder *folder, int exists, i + first); break; } - info = (CamelImapMessageInfo *)camel_folder_summary_uid(folder->summary, uid); + info = camel_folder_summary_uid(folder->summary, uid); if (info) { for (seq = 0; seq < camel_folder_summary_count (folder->summary); seq++) { if (folder->summary->messages->pdata[seq] == info) @@ -2485,20 +2486,20 @@ imap_update_summary (CamelFolder *folder, int exists, _("Unexpected server response: Identical UIDs provided for messages %d and %d"), seq + 1, i + first); - camel_message_info_free(&info->info); + camel_folder_summary_info_free(folder->summary, info); break; } - camel_folder_summary_add (folder->summary, (CamelMessageInfo *)mi); + camel_folder_summary_add (folder->summary, mi); camel_folder_change_info_add_uid (changes, camel_message_info_uid (mi)); - if ((mi->info.flags & CAMEL_IMAP_MESSAGE_RECENT)) + if ((mi->flags & CAMEL_IMAP_MESSAGE_RECENT)) camel_folder_change_info_recent_uid(changes, camel_message_info_uid (mi)); } for ( ; i < messages->len; i++) { if ((mi = messages->pdata[i])) - camel_message_info_free(&mi->info); + camel_folder_summary_info_free(folder->summary, mi); } g_ptr_array_free (messages, TRUE); @@ -2516,7 +2517,7 @@ imap_update_summary (CamelFolder *folder, int exists, if (messages) { for (i = 0; i < messages->len; i++) { if (messages->pdata[i]) - camel_message_info_free(messages->pdata[i]); + camel_folder_summary_info_free (folder->summary, messages->pdata[i]); } g_ptr_array_free (messages, TRUE); } @@ -2552,7 +2553,7 @@ camel_imap_folder_changed (CamelFolder *folder, int exists, camel_imap_message_cache_remove (imap_folder->cache, camel_message_info_uid (info)); CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock); camel_folder_summary_remove (folder->summary, info); - camel_message_info_free(info); + camel_folder_summary_info_free(folder->summary, info); } } diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c index 5811b0f691..3f92c2f40a 100644 --- a/camel/providers/imap/camel-imap-store.c +++ b/camel/providers/imap/camel-imap-store.c @@ -24,6 +24,7 @@ * */ + #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -34,6 +35,8 @@ #include <unistd.h> #include <errno.h> +#include "e-util/e-path.h" + #include "camel-imap-store.h" #include "camel-imap-store-summary.h" #include "camel-imap-folder.h" @@ -56,11 +59,11 @@ #include "camel-sasl.h" #include "camel-utf8.h" #include "camel-string-utils.h" + #include "camel-imap-private.h" #include "camel-private.h" + #include "camel-debug.h" -#include "camel-i18n.h" -#include "camel-net-utils.h" #define d(x) @@ -502,52 +505,87 @@ imap_get_capability (CamelService *service, CamelException *ex) } enum { - MODE_CLEAR, - MODE_SSL, - MODE_TLS, + USE_SSL_NEVER, + USE_SSL_ALWAYS, + USE_SSL_WHEN_POSSIBLE }; #define SSL_PORT_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3) #define STARTTLS_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_TLS) static gboolean -connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, CamelException *ex) +connect_to_server (CamelService *service, int ssl_mode, int try_starttls, CamelException *ex) { CamelImapStore *store = (CamelImapStore *) service; CamelImapResponse *response; CamelStream *tcp_stream; CamelSockOptData sockopt; gboolean force_imap4 = FALSE; - int clean_quit, ret; + int clean_quit; + int ret; char *buf; + struct addrinfo *ai, hints = { 0 }; + char *serv; + const char *port = NULL; + + /* FIXME: this connect stuff is duplicated everywhere */ + + if (service->url->port) { + serv = g_alloca(16); + sprintf(serv, "%d", service->url->port); + } else { + serv = "imap"; + port = IMAP_PORT; + } - if (ssl_mode != MODE_CLEAR) { + if (ssl_mode != USE_SSL_NEVER) { #ifdef HAVE_SSL - if (ssl_mode == MODE_TLS) { + if (try_starttls) { tcp_stream = camel_tcp_stream_ssl_new_raw (service->session, service->url->host, STARTTLS_FLAGS); } else { + if (service->url->port == 0) { + serv = "imaps"; + port = IMAPS_PORT; + } tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, SSL_PORT_FLAGS); } #else - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s: %s"), - service->url->host, _("SSL unavailable")); + if (!try_starttls && service->url->port == 0) { + serv = "imaps"; + port = IMAPS_PORT; + } + camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, + _("Could not connect to %s (port %s): %s"), + service->url->host, serv, + _("SSL unavailable")); return FALSE; #endif /* HAVE_SSL */ } else { tcp_stream = camel_tcp_stream_raw_new (); } + + hints.ai_socktype = SOCK_STREAM; + ai = camel_getaddrinfo(service->url->host, serv, &hints, ex); + if (ai == NULL && port != NULL && camel_exception_get_id(ex) != CAMEL_EXCEPTION_USER_CANCEL) { + camel_exception_clear(ex); + ai = camel_getaddrinfo(service->url->host, port, &hints, ex); + } + if (ai == NULL) { + camel_object_unref(tcp_stream); + return FALSE; + } - if ((ret = camel_tcp_stream_connect ((CamelTcpStream *) tcp_stream, ai)) == -1) { + ret = camel_tcp_stream_connect(CAMEL_TCP_STREAM(tcp_stream), ai); + camel_freeaddrinfo(ai); + if (ret == -1) { if (errno == EINTR) camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Connection cancelled")); else camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s: %s"), - service->url->host, - g_strerror (errno)); + _("Could not connect to %s (port %s): %s"), + service->url->host, serv, g_strerror (errno)); camel_object_unref (tcp_stream); @@ -591,7 +629,7 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam if (!strncmp(buf, "* PREAUTH", 9)) store->preauthed = TRUE; - if (strstr (buf, "Courier-IMAP")) { + if (strstr (buf, "Courier-IMAP") || getenv("CAMEL_IMAP_BRAINDAMAGED")) { /* Courier-IMAP is braindamaged. So far this flag only * works around the fact that Courier-IMAP is known to * give invalid BODY responses seemingly because its @@ -642,18 +680,32 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam store->server_level = IMAP_LEVEL_IMAP4; } - if (ssl_mode != MODE_TLS) { - /* we're done */ - return TRUE; +#ifdef HAVE_SSL + if (ssl_mode == USE_SSL_WHEN_POSSIBLE) { + if (store->capabilities & IMAP_CAPABILITY_STARTTLS) + goto starttls; + } else if (ssl_mode == USE_SSL_ALWAYS) { + if (try_starttls) { + if (store->capabilities & IMAP_CAPABILITY_STARTTLS) { + /* attempt to toggle STARTTLS mode */ + goto starttls; + } else { + /* server doesn't support STARTTLS, abort */ + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + _("Failed to connect to IMAP server %s in secure mode: %s"), + service->url->host, _("SSL/TLS extension not supported.")); + /* we have the possibility of quitting cleanly here */ + clean_quit = TRUE; + goto exception; + } + } } +#endif /* HAVE_SSL */ - if (!(store->capabilities & IMAP_CAPABILITY_STARTTLS)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to IMAP server %s in secure mode: %s"), - service->url->host, _("STARTTLS not supported")); - - goto exception; - } + return TRUE; + +#ifdef HAVE_SSL + starttls: /* as soon as we send a STARTTLS command, all hope is lost of a clean QUIT if problems arise */ clean_quit = FALSE; @@ -718,6 +770,7 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam store->connected = FALSE; return FALSE; +#endif /* HAVE_SSL */ } static gboolean @@ -865,70 +918,60 @@ connect_to_server_process (CamelService *service, const char *cmd, CamelExceptio static struct { char *value; - char *serv; - char *port; int mode; } ssl_options[] = { - { "", "imaps", IMAPS_PORT, MODE_SSL }, /* really old (1.x) */ - { "always", "imaps", IMAPS_PORT, MODE_SSL }, - { "when-possible", "imap", IMAP_PORT, MODE_TLS }, - { "never", "imap", IMAP_PORT, MODE_CLEAR }, - { NULL, "imap", IMAP_PORT, MODE_CLEAR }, + { "", USE_SSL_ALWAYS }, + { "always", USE_SSL_ALWAYS }, + { "when-possible", USE_SSL_WHEN_POSSIBLE }, + { "never", USE_SSL_NEVER }, + { NULL, USE_SSL_NEVER }, }; static gboolean connect_to_server_wrapper (CamelService *service, CamelException *ex) { - const char *command, *ssl_mode; - struct addrinfo hints, *ai; - int mode, ret, i; - char *serv; - const char *port; - - if ((command = camel_url_get_param (service->url, "command"))) + const char *command; +#ifdef HAVE_SSL + const char *use_ssl; + int i, ssl_mode; +#endif + command = camel_url_get_param (service->url, "command"); + if (command) return connect_to_server_process (service, command, ex); - - if ((ssl_mode = camel_url_get_param (service->url, "use_ssl"))) { + +#ifdef HAVE_SSL + use_ssl = camel_url_get_param (service->url, "use_ssl"); + if (use_ssl) { for (i = 0; ssl_options[i].value; i++) - if (!strcmp (ssl_options[i].value, ssl_mode)) + if (!strcmp (ssl_options[i].value, use_ssl)) break; - mode = ssl_options[i].mode; - serv = ssl_options[i].serv; - port = ssl_options[i].port; + ssl_mode = ssl_options[i].mode; + } else + ssl_mode = USE_SSL_NEVER; + + if (ssl_mode == USE_SSL_ALWAYS) { + /* First try the ssl port */ + if (!connect_to_server (service, ssl_mode, FALSE, ex)) { + if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_SERVICE_UNAVAILABLE) { + /* The ssl port seems to be unavailable, lets try STARTTLS */ + camel_exception_clear (ex); + return connect_to_server (service, ssl_mode, TRUE, ex); + } else { + return FALSE; + } + } + + return TRUE; + } else if (ssl_mode == USE_SSL_WHEN_POSSIBLE) { + /* If the server supports STARTTLS, use it */ + return connect_to_server (service, ssl_mode, TRUE, ex); } else { - mode = MODE_CLEAR; - serv = "imap"; - port = IMAP_PORT; - } - - if (service->url->port) { - serv = g_alloca (16); - sprintf (serv, "%d", service->url->port); - port = NULL; - } - - memset (&hints, 0, sizeof (hints)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = PF_UNSPEC; - ai = camel_getaddrinfo(service->url->host, serv, &hints, ex); - if (ai == NULL && port != NULL && camel_exception_get_id(ex) != CAMEL_EXCEPTION_USER_CANCEL) { - camel_exception_clear (ex); - ai = camel_getaddrinfo(service->url->host, port, &hints, ex); - } - if (ai == NULL) - return FALSE; - - if (!(ret = connect_to_server (service, ai, mode, ex)) && mode == MODE_SSL) { - camel_exception_clear (ex); - ret = connect_to_server (service, ai, MODE_TLS, ex); - } else if (!ret && mode == MODE_TLS) { - camel_exception_clear (ex); - ret = connect_to_server (service, ai, MODE_CLEAR, ex); + /* User doesn't care about SSL */ + return connect_to_server (service, ssl_mode, FALSE, ex); } - - camel_freeaddrinfo (ai); - - return ret; +#else + return connect_to_server (service, USE_SSL_NEVER, FALSE, ex); +#endif } extern CamelServiceAuthType camel_imap_password_authtype; @@ -1041,7 +1084,7 @@ imap_forget_folder (CamelImapStore *imap_store, const char *folder_name, CamelEx name = folder_name; storage_path = g_strdup_printf ("%s/folders", imap_store->storage_path); - folder_dir = imap_path_to_physical (storage_path, folder_name); + folder_dir = e_path_to_physical (storage_path, folder_name); g_free (storage_path); if (access (folder_dir, F_OK) != 0) { g_free (folder_dir); @@ -1049,7 +1092,7 @@ imap_forget_folder (CamelImapStore *imap_store, const char *folder_name, CamelEx } summary_file = g_strdup_printf ("%s/summary", folder_dir); - summary = camel_imap_summary_new (NULL, summary_file); + summary = camel_imap_summary_new (summary_file); if (!summary) { g_free (summary_file); g_free (folder_dir); @@ -1599,17 +1642,14 @@ imap_disconnect_online (CamelService *service, gboolean clean, CamelException *e static gboolean imap_summary_is_dirty (CamelFolderSummary *summary) { - CamelImapMessageInfo *info; + CamelMessageInfo *info; int max, i; - int found = FALSE; - + max = camel_folder_summary_count (summary); - for (i = 0; i < max && !found; i++) { - info = (CamelImapMessageInfo *)camel_folder_summary_index (summary, i); - if (info) { - found = info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED; - camel_message_info_free(info); - } + for (i = 0; i < max; i++) { + info = camel_folder_summary_index (summary, i); + if (info && (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) + return TRUE; } return FALSE; @@ -1982,7 +2022,7 @@ get_folder_online (CamelStore *store, const char *folder_name, guint32 flags, Ca } storage_path = g_strdup_printf("%s/folders", imap_store->storage_path); - folder_dir = imap_path_to_physical (storage_path, folder_name); + folder_dir = e_path_to_physical (storage_path, folder_name); g_free(storage_path); new_folder = camel_imap_folder_new (store, folder_name, folder_dir, ex); g_free (folder_dir); @@ -2025,7 +2065,7 @@ get_folder_offline (CamelStore *store, const char *folder_name, folder_name = "INBOX"; storage_path = g_strdup_printf("%s/folders", imap_store->storage_path); - folder_dir = imap_path_to_physical (storage_path, folder_name); + folder_dir = e_path_to_physical (storage_path, folder_name); g_free(storage_path); if (!folder_dir || access (folder_dir, F_OK) != 0) { g_free (folder_dir); @@ -2195,8 +2235,8 @@ rename_folder (CamelStore *store, const char *old_name, const char *new_name_in, manage_subscriptions(store, new_name_in, TRUE); storage_path = g_strdup_printf("%s/folders", imap_store->storage_path); - oldpath = imap_path_to_physical (storage_path, old_name); - newpath = imap_path_to_physical (storage_path, new_name_in); + oldpath = e_path_to_physical (storage_path, old_name); + newpath = e_path_to_physical (storage_path, new_name_in); g_free(storage_path); /* So do we care if this didn't work? Its just a cache? */ @@ -2631,7 +2671,7 @@ fill_fi(CamelStore *store, CamelFolderInfo *fi, guint32 flags) /* This is a lot of work for one path! */ storage_path = g_strdup_printf("%s/folders", ((CamelImapStore *)store)->storage_path); - folder_dir = imap_path_to_physical(storage_path, fi->full_name); + folder_dir = e_path_to_physical(storage_path, fi->full_name); path = g_strdup_printf("%s/summary", folder_dir); s = (CamelFolderSummary *)camel_object_new(camel_imap_summary_get_type()); camel_folder_summary_set_build_content(s, TRUE); @@ -3037,7 +3077,7 @@ get_folder_info_offline (CamelStore *store, const char *top, /* A kludge to avoid having to pass a struct to the callback */ g_ptr_array_add (folders, imap_store); storage_path = g_strdup_printf("%s/folders", imap_store->storage_path); - if (!imap_path_find_folders (storage_path, get_one_folder_offline, folders)) { + if (!e_path_find_folders (storage_path, get_one_folder_offline, folders)) { camel_disco_store_check_online (CAMEL_DISCO_STORE (imap_store), ex); fi = NULL; } else { diff --git a/camel/providers/imap4/camel-imap4-engine.c b/camel/providers/imap4/camel-imap4-engine.c index d6f17532ee..adbf862747 100644 --- a/camel/providers/imap4/camel-imap4-engine.c +++ b/camel/providers/imap4/camel-imap4-engine.c @@ -28,7 +28,6 @@ #include <camel/camel-sasl.h> #include <camel/camel-stream-buffer.h> -#include <camel/camel-i18n.h> #include "camel-imap4-summary.h" #include "camel-imap4-command.h" @@ -115,6 +114,22 @@ camel_imap4_engine_init (CamelIMAP4Engine *engine, CamelIMAP4EngineClass *klass) } static void +imap4_namespace_clear (CamelIMAP4Namespace **namespace) +{ + CamelIMAP4Namespace *node, *next; + + node = *namespace; + while (node != NULL) { + next = node->next; + g_free (node->path); + g_free (node); + node = next; + } + + *namespace = NULL; +} + +static void camel_imap4_engine_finalize (CamelObject *object) { CamelIMAP4Engine *engine = (CamelIMAP4Engine *) object; @@ -129,9 +144,9 @@ camel_imap4_engine_finalize (CamelObject *object) g_hash_table_foreach (engine->authtypes, (GHFunc) g_free, NULL); g_hash_table_destroy (engine->authtypes); - camel_imap4_namespace_clear (&engine->namespaces.personal); - camel_imap4_namespace_clear (&engine->namespaces.other); - camel_imap4_namespace_clear (&engine->namespaces.shared); + imap4_namespace_clear (&engine->namespaces.personal); + imap4_namespace_clear (&engine->namespaces.other); + imap4_namespace_clear (&engine->namespaces.shared); if (engine->folder) camel_object_unref (engine->folder); @@ -148,7 +163,6 @@ camel_imap4_engine_finalize (CamelObject *object) /** * camel_imap4_engine_new: * @service: service - * @reconnect: reconnect callback function * * Returns a new imap4 engine **/ @@ -334,16 +348,6 @@ camel_imap4_engine_namespace (CamelIMAP4Engine *engine, CamelException *ex) } -/** - * camel_imap4_engine_select_folder: - * @engine: IMAP4 engine - * @folder: folder to select - * @ex: exception - * - * Convenience function to select @folder. - * - * Returns 0 on success or -1 on fail. - **/ int camel_imap4_engine_select_folder (CamelIMAP4Engine *engine, CamelFolder *folder, CamelException *ex) { @@ -435,15 +439,11 @@ static struct { { "IMAP4", CAMEL_IMAP4_CAPABILITY_IMAP4 }, { "IMAP4REV1", CAMEL_IMAP4_CAPABILITY_IMAP4REV1 }, { "STATUS", CAMEL_IMAP4_CAPABILITY_STATUS }, - { "NAMESPACE", CAMEL_IMAP4_CAPABILITY_NAMESPACE }, /* rfc2342 */ - { "UIDPLUS", CAMEL_IMAP4_CAPABILITY_UIDPLUS }, /* rfc2359 */ - { "LITERAL+", CAMEL_IMAP4_CAPABILITY_LITERALPLUS }, /* rfc2088 */ + { "NAMESPACE", CAMEL_IMAP4_CAPABILITY_NAMESPACE }, + { "UIDPLUS", CAMEL_IMAP4_CAPABILITY_UIDPLUS }, + { "LITERAL+", CAMEL_IMAP4_CAPABILITY_LITERALPLUS }, { "LOGINDISABLED", CAMEL_IMAP4_CAPABILITY_LOGINDISABLED }, { "STARTTLS", CAMEL_IMAP4_CAPABILITY_STARTTLS }, - { "QUOTA", CAMEL_IMAP4_CAPABILITY_QUOTA }, /* rfc2087 */ - { "ACL", CAMEL_IMAP4_CAPABILITY_ACL }, /* rfc2086 */ - { "IDLE", CAMEL_IMAP4_CAPABILITY_IDLE }, /* rfc2177 */ - { "MULTIAPPEND", CAMEL_IMAP4_CAPABILITY_MULTIAPPEND }, /* rfc3502 */ { NULL, 0 } }; @@ -469,7 +469,7 @@ engine_parse_capability (CamelIMAP4Engine *engine, int sentinel, CamelException return -1; while (token.token == CAMEL_IMAP4_TOKEN_ATOM) { - if (!g_ascii_strncasecmp ("AUTH=", token.v.atom, 5)) { + if (!strncasecmp ("AUTH=", token.v.atom, 5)) { CamelServiceAuthType *auth; if ((auth = camel_sasl_authtype (token.v.atom + 5)) != NULL) @@ -563,9 +563,9 @@ engine_parse_namespace (CamelIMAP4Engine *engine, CamelException *ex) camel_imap4_token_t token; int i, n = 0; - camel_imap4_namespace_clear (&engine->namespaces.personal); - camel_imap4_namespace_clear (&engine->namespaces.other); - camel_imap4_namespace_clear (&engine->namespaces.shared); + imap4_namespace_clear (&engine->namespaces.personal); + imap4_namespace_clear (&engine->namespaces.other); + imap4_namespace_clear (&engine->namespaces.shared); if (camel_imap4_engine_next_token (engine, &token, ex) == -1) return -1; @@ -604,19 +604,8 @@ engine_parse_namespace (CamelIMAP4Engine *engine, CamelException *ex) goto exception; } - switch (token.token) { - case CAMEL_IMAP4_TOKEN_NIL: - node->sep = '\0'; - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - if (strlen (token.v.qstring) == 1) { - node->sep = *token.v.qstring; - break; - } else { - /* invalid, fall thru */ - } - default: - d(fprintf (stderr, "Expected to find a nil or a valid qstring token as second element in NAMESPACE pair\n")); + if (token.token != CAMEL_IMAP4_TOKEN_QSTRING || strlen (token.v.qstring) > 1) { + d(fprintf (stderr, "Expected to find a qstring token as second element in NAMESPACE pair\n")); camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); g_free (node->path); g_free (node); @@ -624,6 +613,7 @@ engine_parse_namespace (CamelIMAP4Engine *engine, CamelException *ex) goto exception; } + node->sep = *token.v.qstring; tail->next = node; tail = node; @@ -682,7 +672,7 @@ engine_parse_namespace (CamelIMAP4Engine *engine, CamelException *ex) exception: for (i = 0; i <= n; i++) - camel_imap4_namespace_clear (&namespaces[i]); + imap4_namespace_clear (&namespaces[i]); return -1; } @@ -723,15 +713,6 @@ static struct { }; -/** - * camel_imap4_engine_parse_resp_code: - * @engine: IMAP4 engine - * @ex: exception - * - * Parses a RESP-CODE - * - * Returns 0 on success or -1 on fail. - **/ int camel_imap4_engine_parse_resp_code (CamelIMAP4Engine *engine, CamelException *ex) { @@ -900,34 +881,26 @@ camel_imap4_engine_parse_resp_code (CamelIMAP4Engine *engine, CamelException *ex if (camel_imap4_engine_next_token (engine, &token, ex) == -1) return -1; - if (token.token != CAMEL_IMAP4_TOKEN_ATOM && token.token != CAMEL_IMAP4_TOKEN_NUMBER) { - d(fprintf (stderr, "Expected an atom or numeric token as the second argument to the COPYUID RESP-CODE\n")); + if (token.token != CAMEL_IMAP4_TOKEN_ATOM) { + d(fprintf (stderr, "Expected an atom token as the second argument to the COPYUID RESP-CODE\n")); camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); goto exception; } - if (resp != NULL) { - if (token.token == CAMEL_IMAP4_TOKEN_NUMBER) - resp->v.copyuid.srcset = g_strdup_printf ("%u", token.v.number); - else - resp->v.copyuid.srcset = g_strdup (token.v.atom); - } + if (resp != NULL) + resp->v.copyuid.srcset = g_strdup (token.v.atom); if (camel_imap4_engine_next_token (engine, &token, ex) == -1) return -1; - if (token.token != CAMEL_IMAP4_TOKEN_ATOM && token.token != CAMEL_IMAP4_TOKEN_NUMBER) { - d(fprintf (stderr, "Expected an atom or numeric token as the third argument to the APPENDUID RESP-CODE\n")); + if (token.token != CAMEL_IMAP4_TOKEN_ATOM) { + d(fprintf (stderr, "Expected an atom token as the third argument to the APPENDUID RESP-CODE\n")); camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); goto exception; } - if (resp != NULL) { - if (token.token == CAMEL_IMAP4_TOKEN_NUMBER) - resp->v.copyuid.destset = g_strdup_printf ("%u", token.v.number); - else - resp->v.copyuid.destset = g_strdup (token.v.atom); - } + if (resp != NULL) + resp->v.copyuid.destset = g_strdup (token.v.atom); break; default: @@ -986,17 +959,8 @@ camel_imap4_engine_parse_resp_code (CamelIMAP4Engine *engine, CamelException *ex } -/** - * camel_imap4_engine_handle_untagged_1: - * @engine: IMAP4 engine - * @token: IMAP4 token - * @ex: exception - * - * Handles a single untagged response - * - * Returns -1 on error or one of - * CAMEL_IMAP4_UNTAGGED_[OK,NO,BAD,PREAUTH,HANDLED] on success - **/ + +/* returns -1 on error, or one of CAMEL_IMAP4_UNTAGGED_[OK,NO,BAD,PREAUTH,HANDLED] on success */ int camel_imap4_engine_handle_untagged_1 (CamelIMAP4Engine *engine, camel_imap4_token_t *token, CamelException *ex) { @@ -1149,13 +1113,6 @@ camel_imap4_engine_handle_untagged_1 (CamelIMAP4Engine *engine, camel_imap4_toke } -/** - * camel_imap4_engine_handle_untagged: - * @engine: IMAP4 engine - * @ex: exception - * - * Handle a stream of untagged responses. - **/ void camel_imap4_engine_handle_untagged (CamelIMAP4Engine *engine, CamelException *ex) { @@ -1254,7 +1211,6 @@ engine_state_change (CamelIMAP4Engine *engine, CamelIMAP4Command *ic) return retval; } - /** * camel_imap4_engine_iterate: * @engine: IMAP4 engine @@ -1421,13 +1377,6 @@ camel_imap4_engine_prequeue (CamelIMAP4Engine *engine, CamelFolder *folder, cons } -/** - * camel_imap4_engine_dequeue: - * @engine: IMAP4 engine - * @ic: IMAP4 command - * - * Removes @ic from the processing queue. - **/ void camel_imap4_engine_dequeue (CamelIMAP4Engine *engine, CamelIMAP4Command *ic) { @@ -1444,18 +1393,6 @@ camel_imap4_engine_dequeue (CamelIMAP4Engine *engine, CamelIMAP4Command *ic) } -/** - * camel_imap4_engine_next_token: - * @engine: IMAP4 engine - * @token: IMAP4 token - * @ex: exception - * - * Wraps camel_imap4_stream_next_token() to set an exception on - * failure and updates the engine state to DISCONNECTED if the stream - * gets disconencted. - * - * Returns 0 on success or -1 on fail. - **/ int camel_imap4_engine_next_token (CamelIMAP4Engine *engine, camel_imap4_token_t *token, CamelException *ex) { @@ -1473,15 +1410,6 @@ camel_imap4_engine_next_token (CamelIMAP4Engine *engine, camel_imap4_token_t *to } -/** - * camel_imap4_engine_eat_line: - * @engine: IMAP4 engine - * @ex: exception - * - * Gobbles up the remainder of the response line. - * - * Returns 0 on success or -1 on fail - **/ int camel_imap4_engine_eat_line (CamelIMAP4Engine *engine, CamelException *ex) { @@ -1514,19 +1442,6 @@ camel_imap4_engine_eat_line (CamelIMAP4Engine *engine, CamelException *ex) } -/** - * camel_imap4_engine_line: - * @engine: IMAP4 engine - * @line: line pointer - * @len: length pointer - * @ex: exception - * - * Reads in a single line of input from the IMAP4 server and updates - * @line to point to the line buffer. @len is set to the length of the - * line buffer. @line must be free'd using g_free(). - * - * Returns 0 on success or -1 on fail - **/ int camel_imap4_engine_line (CamelIMAP4Engine *engine, unsigned char **line, size_t *len, CamelException *ex) { @@ -1569,20 +1484,6 @@ camel_imap4_engine_line (CamelIMAP4Engine *engine, unsigned char **line, size_t } -/** - * camel_imap4_engine_literal: - * @engine: IMAP4 engine - * @literal: literal pointer - * @len: len pointer - * @ex: exception - * - * Reads in an entire literal string and updates @literal to point to - * it. @len is set to the length of the literal. @literal will also - * conveniently be terminated with a nul-byte. @literal must be free'd - * using g_free(). - * - * Returns 0 on success or -1 on fail. - **/ int camel_imap4_engine_literal (CamelIMAP4Engine *engine, unsigned char **literal, size_t *len, CamelException *ex) { @@ -1626,55 +1527,6 @@ camel_imap4_engine_literal (CamelIMAP4Engine *engine, unsigned char **literal, s } -/** - * camel_imap4_engine_nstring: - * @engine: IMAP4 engine - * @nstring: nstring pointer - * @ex: exception - * - * Reads in an nstring (NIL, atom, qstring or literal) and updates - * @nstring to point to it. @nstring must be free'd using g_free(). - * - * Returns 0 on success or -1 on fail. - **/ -int -camel_imap4_engine_nstring (CamelIMAP4Engine *engine, unsigned char **nstring, CamelException *ex) -{ - camel_imap4_token_t token; - size_t n; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - switch (token.token) { - case CAMEL_IMAP4_TOKEN_NIL: - *nstring = NULL; - break; - case CAMEL_IMAP4_TOKEN_ATOM: - *nstring = g_strdup (token.v.atom); - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - *nstring = g_strdup (token.v.qstring); - break; - case CAMEL_IMAP4_TOKEN_LITERAL: - if (camel_imap4_engine_literal (engine, nstring, &n, ex) == -1) - return -1; - break; - default: - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - return 0; -} - - -/** - * camel_imap4_resp_code_free: - * @rcode: RESP-CODE - * - * Free's the RESP-CODE - **/ void camel_imap4_resp_code_free (CamelIMAP4RespCode *rcode) { diff --git a/camel/providers/imap4/camel-imap4-store.c b/camel/providers/imap4/camel-imap4-store.c index 2e7308d75d..0d33f43c5d 100644 --- a/camel/providers/imap4/camel-imap4-store.c +++ b/camel/providers/imap4/camel-imap4-store.c @@ -34,9 +34,6 @@ #include <camel/camel-private.h> -#include <camel/camel-i18n.h> -#include <camel/camel-net-utils.h> - #include "camel-imap4-store.h" #include "camel-imap4-engine.h" #include "camel-imap4-folder.h" @@ -44,9 +41,7 @@ #include "camel-imap4-command.h" #include "camel-imap4-utils.h" #include "camel-imap4-summary.h" -#include "camel-imap4-store-summary.h" -#define d(x) x static void camel_imap4_store_class_init (CamelIMAP4StoreClass *klass); static void camel_imap4_store_init (CamelIMAP4Store *store, CamelIMAP4StoreClass *klass); @@ -148,7 +143,6 @@ static void camel_imap4_store_init (CamelIMAP4Store *store, CamelIMAP4StoreClass *klass) { store->engine = NULL; - store->summary = NULL; } static void @@ -156,11 +150,6 @@ camel_imap4_store_finalize (CamelObject *object) { CamelIMAP4Store *store = (CamelIMAP4Store *) object; - if (store->summary) { - camel_store_summary_save ((CamelStoreSummary *) store->summary); - camel_object_unref (store->summary); - } - if (store->engine) camel_object_unref (store->engine); @@ -172,7 +161,6 @@ static void imap4_construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex) { CamelIMAP4Store *store = (CamelIMAP4Store *) service; - char *buf; CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); if (camel_exception_is_set (ex)) @@ -180,20 +168,6 @@ imap4_construct (CamelService *service, CamelSession *session, CamelProvider *pr store->storage_path = camel_session_get_storage_path (session, service, ex); store->engine = camel_imap4_engine_new (service, imap4_reconnect); - - /* setup/load the summary */ - buf = g_alloca (strlen (store->storage_path) + 32); - sprintf (buf, "%s/.summary", store->storage_path); - store->summary = camel_imap4_store_summary_new (); - camel_store_summary_set_filename ((CamelStoreSummary *) store->summary, buf); - - buf = camel_url_to_string (service->url, CAMEL_URL_HIDE_ALL); - url = camel_url_new (buf, NULL); - g_free (buf); - camel_store_summary_set_uri_base ((CamelStoreSummary *) store->summary, url); - camel_url_free (url); - - camel_store_summary_load ((CamelStoreSummary *) store->summary); } static char * @@ -226,7 +200,7 @@ connect_to_server (CamelIMAP4Engine *engine, struct addrinfo *ai, int ssl_mode, if (ssl_mode != MODE_CLEAR) { #ifdef HAVE_SSL if (ssl_mode == MODE_TLS) { - tcp_stream = camel_tcp_stream_ssl_new_raw (service->session, service->url->host, STARTTLS_FLAGS); + tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, STARTTLS_FLAGS); } else { tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, SSL_PORT_FLAGS); } @@ -262,8 +236,6 @@ connect_to_server (CamelIMAP4Engine *engine, struct addrinfo *ai, int ssl_mode, if (camel_imap4_engine_capability (engine, ex) == -1) return FALSE; - camel_imap4_store_summary_set_capabilities (((CamelIMAP4Store *) service)->summary, engine->capa); - if (ssl_mode != MODE_TLS) { /* we're done */ return TRUE; @@ -320,9 +292,9 @@ connect_to_server_wrapper (CamelIMAP4Engine *engine, CamelException *ex) struct addrinfo *ai, hints; const char *ssl_mode; int mode, ret, i; - const char *port; char *serv; - + const char *port; + if ((ssl_mode = camel_url_get_param (service->url, "use_ssl"))) { for (i = 0; ssl_options[i].value; i++) if (!strcmp (ssl_options[i].value, ssl_mode)) @@ -353,13 +325,7 @@ connect_to_server_wrapper (CamelIMAP4Engine *engine, CamelException *ex) if (ai == NULL) return FALSE; - if (!(ret = connect_to_server (engine, ai, mode, ex)) && mode == MODE_SSL) { - camel_exception_clear (ex); - ret = connect_to_server (engine, ai, MODE_TLS, ex); - } else if (!ret && mode == MODE_TLS) { - camel_exception_clear (ex); - ret = connect_to_server (engine, ai, MODE_CLEAR, ex); - } + ret = connect_to_server (engine, ai, mode, ex); camel_freeaddrinfo (ai); @@ -389,7 +355,7 @@ sasl_auth (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, const unsigned char if (!(challenge = camel_sasl_challenge_base64 (sasl, (const char *) linebuf, ex))) return -1; - d(fprintf (stderr, "sending : %s\r\n", challenge)); + fprintf (stderr, "sending : %s\r\n", challenge); if (camel_stream_printf (engine->ostream, "%s\r\n", challenge) == -1) { g_free (challenge); @@ -437,7 +403,7 @@ imap4_try_authenticate (CamelIMAP4Engine *engine, gboolean reprompt, const char CamelServiceAuthType *mech; mech = g_hash_table_lookup (engine->authtypes, service->url->authmech); - sasl = camel_sasl_new ("imap", mech->authproto, service); + sasl = camel_sasl_new ("imap4", mech->authproto, service); ic = camel_imap4_engine_prequeue (engine, NULL, "AUTHENTICATE %s\r\n", service->url->authmech); ic->plus = sasl_auth; @@ -501,8 +467,6 @@ imap4_reconnect (CamelIMAP4Engine *engine, CamelException *ex) g_free (errmsg); errmsg = g_strdup (lex.desc); camel_exception_clear (&lex); - g_free (service->url->passwd); - service->url->passwd = NULL; reprompt = TRUE; } g_free (errmsg); @@ -515,25 +479,16 @@ imap4_reconnect (CamelIMAP4Engine *engine, CamelException *ex) if (camel_imap4_engine_namespace (engine, ex) == -1) return FALSE; - camel_imap4_store_summary_set_namespaces (((CamelIMAP4Store *) service)->summary, &engine->namespaces); - return TRUE; } static gboolean imap4_connect (CamelService *service, CamelException *ex) { - CamelIMAP4Store *store = (CamelIMAP4Store *) service; gboolean retval; - if (!camel_session_is_online (service->session)) - return TRUE; - CAMEL_SERVICE_LOCK (service, connect_lock); - if (store->engine->state == CAMEL_IMAP4_ENGINE_DISCONNECTED) - retval = imap4_reconnect (store->engine, ex); - else - retval = TRUE; + retval = imap4_reconnect (((CamelIMAP4Store *) service)->engine, ex); CAMEL_SERVICE_UNLOCK (service, connect_lock); return retval; @@ -546,18 +501,13 @@ imap4_disconnect (CamelService *service, gboolean clean, CamelException *ex) CamelIMAP4Command *ic; int id; - if (!camel_session_is_online (service->session)) - return TRUE; - - CAMEL_SERVICE_LOCK (store, connect_lock); - if (clean && store->engine->state != CAMEL_IMAP4_ENGINE_DISCONNECTED) { + if (clean && !store->engine->istream->disconnected) { ic = camel_imap4_engine_queue (store->engine, NULL, "LOGOUT\r\n"); while ((id = camel_imap4_engine_iterate (store->engine)) < ic->id && id != -1) ; camel_imap4_command_unref (ic); } - CAMEL_SERVICE_UNLOCK (store, connect_lock); return 0; } @@ -572,9 +522,6 @@ imap4_query_auth_types (CamelService *service, CamelException *ex) GList *sasl_types, *t, *next; gboolean connected; - if (!camel_session_is_online (service->session)) - return NULL; - CAMEL_SERVICE_LOCK (store, connect_lock); connected = connect_to_server_wrapper (store->engine, ex); CAMEL_SERVICE_UNLOCK (store, connect_lock); @@ -595,30 +542,83 @@ imap4_query_auth_types (CamelService *service, CamelException *ex) return g_list_prepend (sasl_types, &camel_imap4_password_authtype); } + +static char +imap4_get_path_delim (CamelIMAP4Engine *engine, const char *full_name) +{ + /* FIXME: move this to utils so imap4-folder.c can share */ + CamelIMAP4Namespace *namespace; + const char *slash; + size_t len; + char *top; + + if ((slash = strchr (full_name, '/'))) + len = (slash - full_name); + else + len = strlen (full_name); + + top = g_alloca (len + 1); + memcpy (top, full_name, len); + top[len] = '\0'; + + if (!g_ascii_strcasecmp (top, "INBOX")) + top = "INBOX"; + + retry: + namespace = engine->namespaces.personal; + while (namespace != NULL) { + if (!strcmp (namespace->path, top)) + return namespace->sep; + namespace = namespace->next; + } + + namespace = engine->namespaces.other; + while (namespace != NULL) { + if (!strcmp (namespace->path, top)) + return namespace->sep; + namespace = namespace->next; + } + + namespace = engine->namespaces.shared; + while (namespace != NULL) { + if (!strcmp (namespace->path, top)) + return namespace->sep; + namespace = namespace->next; + } + + if (top[0] != '\0') { + /* look for a default namespace? */ + top[0] = '\0'; + goto retry; + } + + return '/'; +} + static char * imap4_folder_utf7_name (CamelStore *store, const char *folder_name, char wildcard) { char *real_name, *p; - char sep = '\0'; + char sep; int len; - if (*folder_name) { - sep = camel_imap4_get_path_delim (((CamelIMAP4Store *) store)->summary, folder_name); - - if (sep != '/') { - p = real_name = g_alloca (strlen (folder_name) + 1); - strcpy (real_name, folder_name); - while (*p != '\0') { - if (*p == '/') - *p = sep; - p++; - } - - folder_name = real_name; + sep = imap4_get_path_delim (((CamelIMAP4Store *) store)->engine, folder_name); + + if (sep != '/') { + p = real_name = g_alloca (strlen (folder_name) + 1); + strcpy (real_name, folder_name); + while (*p != '\0') { + if (*p == '/') + *p = sep; + p++; } + folder_name = real_name; + } + + if (*folder_name) real_name = camel_utf8_utf7 (folder_name); - } else + else real_name = g_strdup (""); if (wildcard) { @@ -639,7 +639,6 @@ static CamelFolder * imap4_get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex) { CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelSession *session = ((CamelService *) store)->session; CamelFolder *folder = NULL; camel_imap4_list_t *list; CamelIMAP4Command *ic; @@ -651,18 +650,6 @@ imap4_get_folder (CamelStore *store, const char *folder_name, guint32 flags, Cam CAMEL_SERVICE_LOCK (store, connect_lock); - if (!camel_session_is_online (session)) { - if ((flags & CAMEL_STORE_FOLDER_CREATE) != 0) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create IMAP folders in offline mode.")); - } else { - folder = camel_imap4_folder_new (store, folder_name, ex); - } - - CAMEL_SERVICE_UNLOCK (store, connect_lock); - - return folder; - } - /* make sure the folder exists - try LISTing it? */ utf7_name = imap4_folder_utf7_name (store, folder_name, '\0'); ic = camel_imap4_engine_queue (engine, NULL, "LIST \"\" %S\r\n", utf7_name); @@ -740,7 +727,6 @@ imap4_create_folder (CamelStore *store, const char *parent_name, const char *fol * contain subfolders - delete them and re-create with the * proper hint */ CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelSession *session = ((CamelService *) store)->session; CamelFolderInfo *fi = NULL; CamelIMAP4Command *ic; char *utf7_name; @@ -750,7 +736,7 @@ imap4_create_folder (CamelStore *store, const char *parent_name, const char *fol char sep; int id; - sep = camel_imap4_get_path_delim (((CamelIMAP4Store *) store)->summary, parent_name); + sep = imap4_get_path_delim (engine, parent_name); c = folder_name; while (*c != '\0') { @@ -765,11 +751,6 @@ imap4_create_folder (CamelStore *store, const char *parent_name, const char *fol c++; } - if (!camel_session_is_online (session)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create IMAP folders in offline mode.")); - return NULL; - } - if (parent_name != NULL && *parent_name) name = g_strdup_printf ("%s/%s", parent_name, folder_name); else @@ -807,8 +788,6 @@ imap4_create_folder (CamelStore *store, const char *parent_name, const char *fol fi->unread = -1; fi->total = -1; - camel_imap4_store_summary_note_info (((CamelIMAP4Store *) store)->summary, fi); - camel_object_trigger_event (store, "folder_created", fi); break; case CAMEL_IMAP4_RESULT_NO: @@ -841,7 +820,6 @@ static void imap4_delete_folder (CamelStore *store, const char *folder_name, CamelException *ex) { CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelSession *session = ((CamelService *) store)->session; CamelFolder *selected = (CamelFolder *) engine->folder; CamelIMAP4Command *ic, *ic0 = NULL; CamelFolderInfo *fi; @@ -858,11 +836,6 @@ imap4_delete_folder (CamelStore *store, const char *folder_name, CamelException return; } - if (!camel_session_is_online (session)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot delete IMAP folders in offline mode.")); - return; - } - CAMEL_SERVICE_LOCK (store, connect_lock); if (selected && !strcmp (folder_name, selected->full_name)) @@ -909,8 +882,6 @@ imap4_delete_folder (CamelStore *store, const char *folder_name, CamelException fi->unread = -1; fi->total = -1; - camel_imap4_store_summary_unnote_info (((CamelIMAP4Store *) store)->summary, fi); - camel_object_trigger_event (store, "folder_deleted", fi); camel_folder_info_free (fi); @@ -937,7 +908,6 @@ static void imap4_rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex) { CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelSession *session = ((CamelService *) store)->session; char *old_uname, *new_uname; CamelIMAP4Command *ic; int id; @@ -950,11 +920,6 @@ imap4_rename_folder (CamelStore *store, const char *old_name, const char *new_na return; } - if (!camel_session_is_online (session)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot rename IMAP folders in offline mode.")); - return; - } - CAMEL_SERVICE_LOCK (store, connect_lock); old_uname = imap4_folder_utf7_name (store, old_name, '\0'); @@ -977,7 +942,6 @@ imap4_rename_folder (CamelStore *store, const char *old_name, const char *new_na switch (ic->result) { case CAMEL_IMAP4_RESULT_OK: /* FIXME: need to update state on the renamed folder object */ - /* FIXME: need to update cached summary info too */ break; case CAMEL_IMAP4_RESULT_NO: /* FIXME: would be good to save the NO reason into the err message */ @@ -1091,11 +1055,6 @@ imap4_build_folder_info (CamelStore *store, const char *top, guint32 flags, GPtr url = camel_url_copy (engine->url); - if (!strcmp (top, "") && (flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE)) { - /* clear the folder-info cache */ - camel_store_summary_clear ((CamelStoreSummary *) ((CamelIMAP4Store *) store)->summary); - } - for (i = 0; i < array->len; i++) { list = array->pdata[i]; fi = g_malloc0 (sizeof (CamelFolderInfo)); @@ -1116,20 +1075,34 @@ imap4_build_folder_info (CamelStore *store, const char *top, guint32 flags, GPtr fi->flags = list->flags; fi->unread = -1; fi->total = -1; - - /* SELECTED folder, just get it from the folder */ - if (folder && !strcmp (folder->full_name, fi->full_name)) { - camel_object_get(folder, NULL, CAMEL_FOLDER_TOTAL, &fi->total, CAMEL_FOLDER_UNREAD, &fi->unread, 0); - } else if (!(flags & CAMEL_STORE_FOLDER_INFO_FAST)) { - imap4_status (store, fi); + + if (!(flags & CAMEL_STORE_FOLDER_INFO_FAST)) { + if (folder && !strcmp (folder->full_name, fi->full_name)) { + /* can't STATUS this folder since it is SELECTED, besides - it would be wasteful */ + CamelMessageInfo *info; + int index; + + fi->total = camel_folder_summary_count (folder->summary); + + fi->unread = 0; + for (index = 0; index < fi->total; index++) { + if (!(info = camel_folder_summary_index (folder->summary, index))) + continue; + + if ((info->flags & CAMEL_MESSAGE_SEEN) == 0) + fi->unread++; + + camel_folder_summary_info_free (folder->summary, info); + } + } else { + imap4_status (store, fi); + } } g_free (list->name); g_free (list); array->pdata[i] = fi; - - camel_imap4_store_summary_note_info (((CamelIMAP4Store *) store)->summary, fi); } fi = camel_folder_info_build (array, top, '/', TRUE); @@ -1138,8 +1111,6 @@ imap4_build_folder_info (CamelStore *store, const char *top, guint32 flags, GPtr g_ptr_array_free (array, TRUE); - camel_store_summary_save ((CamelStoreSummary *) ((CamelIMAP4Store *) store)->summary); - return fi; } @@ -1147,7 +1118,6 @@ static CamelFolderInfo * imap4_get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex) { CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelSession *session = ((CamelService *) store)->session; CamelIMAP4Command *ic, *ic0 = NULL; CamelFolderInfo *fi = NULL; camel_imap4_list_t *list; @@ -1157,30 +1127,23 @@ imap4_get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelE char wildcard; int id, i; - if (top == NULL) - top = ""; - CAMEL_SERVICE_LOCK (store, connect_lock); - if (!camel_session_is_online (session) || engine->state == CAMEL_IMAP4_ENGINE_DISCONNECTED) { - fi = camel_imap4_store_summary_get_folder_info (((CamelIMAP4Store *) store)->summary, top, flags); - if (fi == NULL && camel_session_is_online (session)) { - /* folder info hasn't yet been cached and the store hasn't been - * connected yet, but the network is available so we can connect - * and query the server. */ - goto check_online; - } - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return fi; + if (engine->state == CAMEL_IMAP4_ENGINE_DISCONNECTED) { + if (!camel_service_connect ((CamelService *) store, ex)) + return NULL; + + engine = ((CamelIMAP4Store *) store)->engine; } - check_online: - if (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) cmd = "LSUB"; else cmd = "LIST"; + if (top == NULL) + top = ""; + wildcard = (flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) ? '*' : '%'; pattern = imap4_folder_utf7_name (store, top, wildcard); array = g_ptr_array_new (); @@ -1268,7 +1231,6 @@ static void imap4_subscribe_folder (CamelStore *store, const char *folder_name, CamelException *ex) { CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelSession *session = ((CamelService *) store)->session; CamelIMAP4Command *ic; CamelFolderInfo *fi; char *utf7_name; @@ -1276,11 +1238,6 @@ imap4_subscribe_folder (CamelStore *store, const char *folder_name, CamelExcepti const char *p; int id; - if (!camel_session_is_online (session)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot subscribe to IMAP folders in offline mode.")); - return; - } - CAMEL_SERVICE_LOCK (store, connect_lock); utf7_name = imap4_folder_utf7_name (store, folder_name, '\0'); @@ -1314,8 +1271,6 @@ imap4_subscribe_folder (CamelStore *store, const char *folder_name, CamelExcepti fi->unread = -1; fi->total = -1; - camel_imap4_store_summary_note_info (((CamelIMAP4Store *) store)->summary, fi); - camel_object_trigger_event (store, "folder_subscribed", fi); camel_folder_info_free (fi); break; @@ -1341,7 +1296,6 @@ static void imap4_unsubscribe_folder (CamelStore *store, const char *folder_name, CamelException *ex) { CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelSession *session = ((CamelService *) store)->session; CamelIMAP4Command *ic; CamelFolderInfo *fi; char *utf7_name; @@ -1349,11 +1303,6 @@ imap4_unsubscribe_folder (CamelStore *store, const char *folder_name, CamelExcep const char *p; int id; - if (!camel_session_is_online (session)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot unsubscribe from IMAP folders in offline mode.")); - return; - } - CAMEL_SERVICE_LOCK (store, connect_lock); utf7_name = imap4_folder_utf7_name (store, folder_name, '\0'); @@ -1387,8 +1336,6 @@ imap4_unsubscribe_folder (CamelStore *store, const char *folder_name, CamelExcep fi->unread = -1; fi->total = -1; - camel_imap4_store_summary_unnote_info (((CamelIMAP4Store *) store)->summary, fi); - camel_object_trigger_event (store, "folder_unsubscribed", fi); camel_folder_info_free (fi); break; @@ -1414,14 +1361,10 @@ static void imap4_noop (CamelStore *store, CamelException *ex) { CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelSession *session = ((CamelService *) store)->session; CamelFolder *folder = (CamelFolder *) engine->folder; CamelIMAP4Command *ic; int id; - if (!camel_session_is_online (session)) - return; - CAMEL_SERVICE_LOCK (store, connect_lock); if (folder) { diff --git a/camel/providers/imapp/camel-imapp-store.c b/camel/providers/imapp/camel-imapp-store.c index 03f835da7a..c1c9f50649 100644 --- a/camel/providers/imapp/camel-imapp-store.c +++ b/camel/providers/imapp/camel-imapp-store.c @@ -48,7 +48,6 @@ #ifdef HAVE_SSL #include "camel/camel-tcp-stream-ssl.h" #endif -#include "camel/camel-i18n.h" #include "camel-imapp-store-summary.h" #include "camel-imapp-store.h" @@ -57,7 +56,6 @@ #include "camel-imapp-exception.h" #include "camel-imapp-utils.h" #include "camel-imapp-driver.h" -#include "camel-net-utils.h" /* Specified in RFC 2060 section 2.1 */ #define IMAP_PORT 143 @@ -811,7 +809,7 @@ static int store_resp_fetch(CamelIMAPPEngine *ie, guint32 id, void *data) if (strcmp(finfo->uid, camel_message_info_uid(info)) != 0) { printf("summary at index %d has uid %s expected %s\n", id, camel_message_info_uid(info), finfo->uid); /* uid mismatch??? try do it based on uid instead? try to reorder? i dont know? */ - camel_message_info_free(info); + camel_folder_summary_info_free(((CamelFolder *)istore->selected)->summary, info); info = camel_folder_summary_uid(((CamelFolder *)istore->selected)->summary, finfo->uid); } } @@ -860,7 +858,7 @@ static int store_resp_fetch(CamelIMAPPEngine *ie, guint32 id, void *data) CamelMimeParser *mp; if (pending == NULL) - camel_message_info_free(info); + camel_folder_summary_info_free(((CamelFolder *)istore->selected)->summary, info); mp = camel_mime_parser_new(); camel_mime_parser_init_with_stream(mp, finfo->header); info = camel_folder_summary_info_new_from_parser(((CamelFolder *)istore->selected)->summary, mp); @@ -873,7 +871,7 @@ static int store_resp_fetch(CamelIMAPPEngine *ie, guint32 id, void *data) /* FIXME: use a dlist */ e_dlist_remove((EDListNode *)pending); g_hash_table_remove(istore->pending_fetch_table, camel_message_info_uid(pending->info)); - camel_message_info_free(pending->info); + camel_folder_summary_info_free(((CamelFolder *)istore->selected)->summary, pending->info); /*e_memchunk_free(istore->pending_fetch_chunks, pending);*/ } } else if (finfo->got & FETCH_FLAGS) { @@ -885,7 +883,7 @@ static int store_resp_fetch(CamelIMAPPEngine *ie, guint32 id, void *data) } } else { if (pending == NULL) - camel_message_info_free(info); + camel_folder_summary_info_free(((CamelFolder *)istore->selected)->summary, info); printf("got unexpected fetch response?\n"); imap_dump_fetch(finfo); } @@ -975,7 +973,7 @@ camel_imapp_store_folder_selected(CamelIMAPPStore *store, CamelIMAPPFolder *fold if (info) { printf("message info [%d] =\n", i); camel_message_info_dump(info); - camel_message_info_free(info); + camel_folder_summary_info_free(((CamelFolder *)istore->selected)->summary, info); } } } CAMEL_CATCH (e) { diff --git a/camel/providers/local/camel-local-folder.c b/camel/providers/local/camel-local-folder.c index 70673d9687..b86d23221a 100644 --- a/camel/providers/local/camel-local-folder.c +++ b/camel/providers/local/camel-local-folder.c @@ -20,6 +20,7 @@ * */ + #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -47,7 +48,6 @@ #include "camel-stream-filter.h" #include "camel-mime-filter-from.h" #include "camel-exception.h" -#include "camel-i18n.h" #include "camel-local-private.h" diff --git a/camel/providers/local/camel-maildir-folder.c b/camel/providers/local/camel-maildir-folder.c index b74f6e5ace..ba42b75f28 100644 --- a/camel/providers/local/camel-maildir-folder.c +++ b/camel/providers/local/camel-maildir-folder.c @@ -39,7 +39,6 @@ #include "camel-data-wrapper.h" #include "camel-mime-message.h" #include "camel-exception.h" -#include "camel-i18n.h" #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ @@ -153,7 +152,7 @@ camel_maildir_folder_new(CamelStore *parent_store, const char *full_name, guint3 static CamelLocalSummary *maildir_create_summary(CamelLocalFolder *lf, const char *path, const char *folder, CamelIndex *index) { - return (CamelLocalSummary *)camel_maildir_summary_new((CamelFolder *)lf, path, folder, index); + return (CamelLocalSummary *)camel_maildir_summary_new(path, folder, index); } static void @@ -251,7 +250,7 @@ static CamelMimeMessage *maildir_get_message(CamelFolder * folder, const gchar * /* what do we do if the message flags (and :info data) changes? filename mismatch - need to recheck I guess */ name = g_strdup_printf("%s/cur/%s", lf->folder_path, camel_maildir_info_filename(mdi)); - camel_message_info_free(info); + camel_folder_summary_info_free(folder->summary, info); if ((message_stream = camel_stream_fs_new_with_name(name, O_RDONLY, 0)) == NULL) { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, diff --git a/camel/providers/local/camel-mbox-folder.c b/camel/providers/local/camel-mbox-folder.c index d213b444fc..fa8f0b645d 100644 --- a/camel/providers/local/camel-mbox-folder.c +++ b/camel/providers/local/camel-mbox-folder.c @@ -42,7 +42,6 @@ #include "camel-stream-filter.h" #include "camel-mime-filter-from.h" #include "camel-exception.h" -#include "camel-i18n.h" #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ @@ -56,6 +55,13 @@ static CamelLocalFolderClass *parent_class = NULL; static int mbox_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex); static void mbox_unlock(CamelLocalFolder *lf); +#ifdef STATUS_PINE +static gboolean mbox_set_message_flags(CamelFolder *folder, const char *uid, guint32 flags, guint32 set); +#endif + +static void mbox_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value); +static void mbox_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value); + static void mbox_append_message(CamelFolder *folder, CamelMimeMessage * message, const CamelMessageInfo * info, char **appended_uid, CamelException *ex); static CamelMimeMessage *mbox_get_message(CamelFolder *folder, const gchar * uid, CamelException *ex); static CamelLocalSummary *mbox_create_summary(CamelLocalFolder *lf, const char *path, const char *folder, CamelIndex *index); @@ -76,6 +82,12 @@ camel_mbox_folder_class_init(CamelMboxFolderClass * camel_mbox_folder_class) camel_folder_class->append_message = mbox_append_message; camel_folder_class->get_message = mbox_get_message; +#ifdef STATUS_PINE + camel_folder_class->set_message_flags = mbox_set_message_flags; +#endif + camel_folder_class->set_message_user_flag = mbox_set_message_user_flag; + camel_folder_class->set_message_user_tag = mbox_set_message_user_tag; + lclass->get_full_path = camel_mbox_folder_get_full_path; lclass->get_meta_path = camel_mbox_folder_get_meta_path; lclass->create_summary = mbox_create_summary; @@ -194,7 +206,7 @@ camel_mbox_folder_get_meta_path (CamelLocalFolder *lf, const char *toplevel_dir, static CamelLocalSummary *mbox_create_summary(CamelLocalFolder *lf, const char *path, const char *folder, CamelIndex *index) { - return (CamelLocalSummary *)camel_mbox_summary_new((CamelFolder *)lf, path, folder, index); + return (CamelLocalSummary *)camel_mbox_summary_new(path, folder, index); } static int mbox_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex) @@ -408,7 +420,7 @@ retry: g_assert(info->frompos != -1); frompos = info->frompos; - camel_message_info_free((CamelMessageInfo *)info); + camel_folder_summary_info_free(folder->summary, (CamelMessageInfo *)info); /* we use an fd instead of a normal stream here - the reason is subtle, camel_mime_part will cache the whole message in memory if the stream is non-seekable (which it is when built from a parser @@ -480,3 +492,66 @@ fail: return message; } + +#ifdef STATUS_PINE +static gboolean +mbox_set_message_flags(CamelFolder *folder, const char *uid, guint32 flags, guint32 set) +{ + /* Basically, if anything could change the Status line, presume it does */ + if (((CamelMboxSummary *)folder->summary)->xstatus + && (flags & (CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_FLAGGED|CAMEL_MESSAGE_ANSWERED|CAMEL_MESSAGE_DELETED))) { + flags |= CAMEL_MESSAGE_FOLDER_XEVCHANGE|CAMEL_MESSAGE_FOLDER_FLAGGED; + set |= CAMEL_MESSAGE_FOLDER_XEVCHANGE|CAMEL_MESSAGE_FOLDER_FLAGGED; + } + + return ((CamelFolderClass *)parent_class)->set_message_flags(folder, uid, flags, set); +} +#endif + +static void +mbox_set_message_user_flag(CamelFolder *folder, const char *uid, const char *name, gboolean value) +{ + CamelMessageInfo *info; + + g_return_if_fail(folder->summary != NULL); + + info = camel_folder_summary_uid(folder->summary, uid); + if (info == NULL) + return; + + if (camel_flag_set(&info->user_flags, name, value)) { + CamelFolderChangeInfo *changes = camel_folder_change_info_new(); + + info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED|CAMEL_MESSAGE_FOLDER_XEVCHANGE; + camel_folder_summary_touch(folder->summary); + + camel_folder_change_info_change_uid(changes, uid); + camel_object_trigger_event(folder, "folder_changed", changes); + camel_folder_change_info_free(changes); + } + camel_folder_summary_info_free(folder->summary, info); +} + +static void +mbox_set_message_user_tag(CamelFolder *folder, const char *uid, const char *name, const char *value) +{ + CamelMessageInfo *info; + + g_return_if_fail(folder->summary != NULL); + + info = camel_folder_summary_uid(folder->summary, uid); + if (info == NULL) + return; + + if (camel_tag_set(&info->user_tags, name, value)) { + CamelFolderChangeInfo *changes = camel_folder_change_info_new(); + + info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED|CAMEL_MESSAGE_FOLDER_XEVCHANGE; + camel_folder_summary_touch(folder->summary); + + camel_folder_change_info_change_uid(changes, uid); + camel_object_trigger_event (folder, "folder_changed", changes); + camel_folder_change_info_free(changes); + } + camel_folder_summary_info_free(folder->summary, info); +} diff --git a/camel/providers/local/camel-mbox-store.c b/camel/providers/local/camel-mbox-store.c index a9e581cdd7..1277407dbb 100644 --- a/camel/providers/local/camel-mbox-store.c +++ b/camel/providers/local/camel-mbox-store.c @@ -37,7 +37,6 @@ #include "camel-text-index.h" #include "camel-exception.h" #include "camel-url.h" -#include "camel-i18n.h" #define d(x) @@ -618,7 +617,7 @@ fill_fi(CamelStore *store, CamelFolderInfo *fi, guint32 flags) path = camel_mbox_folder_get_meta_path(NULL, root, fi->full_name, ".ev-summary"); folderpath = camel_mbox_folder_get_full_path(NULL, root, fi->full_name); - mbs = (CamelMboxSummary *)camel_mbox_summary_new(NULL, path, folderpath, NULL); + mbs = (CamelMboxSummary *)camel_mbox_summary_new(path, folderpath, NULL); if (camel_folder_summary_header_load((CamelFolderSummary *)mbs) != -1) { fi->unread = ((CamelFolderSummary *)mbs)->unread_count; fi->total = ((CamelFolderSummary *)mbs)->saved_count; diff --git a/camel/providers/local/camel-mh-folder.c b/camel/providers/local/camel-mh-folder.c index 1b054a4547..78456b6daf 100644 --- a/camel/providers/local/camel-mh-folder.c +++ b/camel/providers/local/camel-mh-folder.c @@ -39,7 +39,6 @@ #include "camel-data-wrapper.h" #include "camel-mime-message.h" #include "camel-exception.h" -#include "camel-i18n.h" #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ @@ -117,7 +116,7 @@ camel_mh_folder_new(CamelStore *parent_store, const char *full_name, guint32 fla static CamelLocalSummary *mh_create_summary(CamelLocalFolder *lf, const char *path, const char *folder, CamelIndex *index) { - return (CamelLocalSummary *)camel_mh_summary_new((CamelFolder *)lf, path, folder, index); + return (CamelLocalSummary *)camel_mh_summary_new(path, folder, index); } static void @@ -205,7 +204,7 @@ static CamelMimeMessage *mh_get_message(CamelFolder * folder, const gchar * uid, } /* we only need it to check the message exists */ - camel_message_info_free(info); + camel_folder_summary_info_free(folder->summary, info); name = g_strdup_printf("%s/%s", lf->folder_path, uid); if ((message_stream = camel_stream_fs_new_with_name(name, O_RDONLY, 0)) == NULL) { diff --git a/camel/providers/local/camel-spool-folder.c b/camel/providers/local/camel-spool-folder.c index c4c7da91b6..6a1bbf798a 100644 --- a/camel/providers/local/camel-spool-folder.c +++ b/camel/providers/local/camel-spool-folder.c @@ -44,8 +44,8 @@ #include "camel-session.h" #include "camel-file-utils.h" #include "camel-lock-client.h" + #include "camel-local-private.h" -#include "camel-i18n.h" #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ @@ -160,7 +160,7 @@ spool_get_meta_path(CamelLocalFolder *lf, const char *toplevel_dir, const char * static CamelLocalSummary * spool_create_summary(CamelLocalFolder *lf, const char *path, const char *folder, CamelIndex *index) { - return (CamelLocalSummary *)camel_spool_summary_new((CamelFolder *)lf, folder); + return (CamelLocalSummary *)camel_spool_summary_new(folder); } static int diff --git a/camel/providers/local/camel-spool-store.c b/camel/providers/local/camel-spool-store.c index 3dc21886c8..2e3d9ea777 100644 --- a/camel/providers/local/camel-spool-store.c +++ b/camel/providers/local/camel-spool-store.c @@ -41,7 +41,6 @@ #include "camel-exception.h" #include "camel-url.h" #include "camel-private.h" -#include "camel-i18n.h" #define d(x) diff --git a/camel/providers/nntp/camel-nntp-folder.c b/camel/providers/nntp/camel-nntp-folder.c index de0f4cd222..ffb1b29742 100644 --- a/camel/providers/nntp/camel-nntp-folder.c +++ b/camel/providers/nntp/camel-nntp-folder.c @@ -49,7 +49,6 @@ #include "camel/camel-multipart.h" #include "camel/camel-mime-part.h" #include "camel/camel-stream-buffer.h" -#include "camel/camel-i18n.h" #include "camel/camel-private.h" #include "camel-nntp-summary.h" @@ -511,7 +510,7 @@ camel_nntp_folder_new (CamelStore *parent, const char *folder_name, CamelExcepti g_free(root); root = g_strdup_printf("%s.ev-summary", nntp_folder->storage_path); - folder->summary = (CamelFolderSummary *) camel_nntp_summary_new (folder, root); + folder->summary = (CamelFolderSummary *) camel_nntp_summary_new (root); g_free(root); camel_folder_summary_load (folder->summary); diff --git a/camel/providers/nntp/camel-nntp-private.h b/camel/providers/nntp/camel-nntp-private.h index 520c9db134..253d4e2031 100644 --- a/camel/providers/nntp/camel-nntp-private.h +++ b/camel/providers/nntp/camel-nntp-private.h @@ -35,7 +35,7 @@ extern "C" { #include <config.h> #endif -#include "libedataserver/e-msgport.h" +#include "e-util/e-msgport.h" struct _CamelNNTPStorePrivate { int dummy; diff --git a/camel/providers/nntp/camel-nntp-store.c b/camel/providers/nntp/camel-nntp-store.c index f9daad8515..3e911ec1c5 100644 --- a/camel/providers/nntp/camel-nntp-store.c +++ b/camel/providers/nntp/camel-nntp-store.c @@ -53,8 +53,6 @@ #include "camel-nntp-folder.h" #include "camel-nntp-private.h" #include "camel-nntp-resp-codes.h" -#include "camel-i18n.h" -#include "camel-net-utils.h" #define w(x) #define dd(x) (camel_debug("nntp")?(x):0) @@ -85,6 +83,12 @@ nntp_can_work_offline(CamelDiscoStore *store) return TRUE; } +enum { + USE_SSL_NEVER, + USE_SSL_ALWAYS, + USE_SSL_WHEN_POSSIBLE +}; + static struct { const char *name; int type; @@ -149,17 +153,8 @@ xover_setup(CamelNNTPStore *store, CamelException *ex) return ret; } -enum { - MODE_CLEAR, - MODE_SSL, - MODE_TLS, -}; - -#define SSL_PORT_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3) -#define STARTTLS_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_TLS) - static gboolean -connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, CamelException *ex) +connect_to_server (CamelService *service, int ssl_mode, CamelException *ex) { CamelNNTPStore *store = (CamelNNTPStore *) service; CamelDiscoStore *disco_store = (CamelDiscoStore*) service; @@ -169,6 +164,9 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam unsigned int len; int ret; char *path; + struct addrinfo *ai, hints = { 0 }; + char *serv; + const char *port = NULL; CAMEL_SERVICE_LOCK(store, connect_lock); @@ -185,34 +183,50 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam camel_data_cache_set_expire_age (store->cache, 60*60*24*14); camel_data_cache_set_expire_access (store->cache, 60*60*24*5); } + + if (service->url->port) { + serv = g_alloca(16); + sprintf(serv, "%d", service->url->port); + } else { + serv = "nntp"; + port = NNTP_PORT; + } - if (ssl_mode != MODE_CLEAR) { #ifdef HAVE_SSL - if (ssl_mode == MODE_TLS) { - tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, STARTTLS_FLAGS); - } else { - tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, SSL_PORT_FLAGS); + if (ssl_mode != USE_SSL_NEVER) { + if (service->url->port == 0) { + serv = "nntps"; + port = NNTPS_PORT; } -#else - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s: %s"), - service->url->host, _("SSL unavailable")); - - goto fail; -#endif /* HAVE_SSL */ + tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3); } else { tcp_stream = camel_tcp_stream_raw_new (); } +#else + tcp_stream = camel_tcp_stream_raw_new (); +#endif /* HAVE_SSL */ + + hints.ai_socktype = SOCK_STREAM; + ai = camel_getaddrinfo(service->url->host, serv, &hints, ex); + if (ai == NULL && port != NULL && camel_exception_get_id(ex) != CAMEL_EXCEPTION_USER_CANCEL) { + camel_exception_clear(ex); + ai = camel_getaddrinfo(service->url->host, port, &hints, ex); + } + if (ai == NULL) { + camel_object_unref(tcp_stream); + goto fail; + } - if ((ret = camel_tcp_stream_connect ((CamelTcpStream *) tcp_stream, ai)) == -1) { + ret = camel_tcp_stream_connect(CAMEL_TCP_STREAM(tcp_stream), ai); + camel_freeaddrinfo(ai); + if (ret == -1) { if (errno == EINTR) camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Connection cancelled")); else camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s: %s"), - service->url->host, - g_strerror (errno)); + _("Could not connect to %s (port %s): %s"), + service->url->host, serv, g_strerror (errno)); camel_object_unref (tcp_stream); @@ -254,11 +268,11 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam if (service->url->user != NULL && camel_nntp_try_authenticate(store, ex) != NNTP_AUTH_ACCEPTED) goto fail; - - /* set 'reader' mode & ignore return code, also ping the server, inn goes offline very quickly otherwise */ + + /* set 'reader' mode & ignore return code, also ping the server, inn goes offline very quickly otherwise */ if (camel_nntp_raw_command_auth (store, ex, (char **) &buf, "mode reader") == -1 || camel_nntp_raw_command_auth (store, ex, (char **) &buf, "date") == -1) - goto fail; + goto fail; if (xover_setup(store, ex) == -1) goto fail; @@ -279,61 +293,54 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam static struct { char *value; - char *serv; - char *port; int mode; } ssl_options[] = { - { "", "nntps", NNTPS_PORT, MODE_SSL }, /* really old (1.x) */ - { "always", "nntps", NNTPS_PORT, MODE_SSL }, - { "when-possible", "nntp", NNTP_PORT, MODE_TLS }, - { "never", "nntp", NNTP_PORT, MODE_CLEAR }, - { NULL, "nntp", NNTP_PORT, MODE_CLEAR }, + { "", USE_SSL_ALWAYS }, + { "always", USE_SSL_ALWAYS }, + { "when-possible", USE_SSL_WHEN_POSSIBLE }, + { "never", USE_SSL_NEVER }, + { NULL, USE_SSL_NEVER }, }; static gboolean nntp_connect_online (CamelService *service, CamelException *ex) { - struct addrinfo hints, *ai; - const char *ssl_mode; - int mode, ret, i; - char *serv; - const char *port; +#ifdef HAVE_SSL + const char *use_ssl; + int i, ssl_mode; - if ((ssl_mode = camel_url_get_param (service->url, "use_ssl"))) { + use_ssl = camel_url_get_param (service->url, "use_ssl"); + if (use_ssl) { for (i = 0; ssl_options[i].value; i++) - if (!strcmp (ssl_options[i].value, ssl_mode)) + if (!strcmp (ssl_options[i].value, use_ssl)) break; - mode = ssl_options[i].mode; - serv = ssl_options[i].serv; - port = ssl_options[i].port; + ssl_mode = ssl_options[i].mode; + } else + ssl_mode = USE_SSL_NEVER; + + if (ssl_mode == USE_SSL_ALWAYS) { + /* Connect via SSL */ + return connect_to_server (service, ssl_mode, ex); + } else if (ssl_mode == USE_SSL_WHEN_POSSIBLE) { + /* If the server supports SSL, use it */ + if (!connect_to_server (service, ssl_mode, ex)) { + if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_SERVICE_UNAVAILABLE) { + /* The ssl port seems to be unavailable, fall back to plain NNTP */ + camel_exception_clear (ex); + return connect_to_server (service, USE_SSL_NEVER, ex); + } else { + return FALSE; + } + } + + return TRUE; } else { - mode = MODE_CLEAR; - serv = "nntp"; - port = NNTP_PORT; + /* User doesn't care about SSL */ + return connect_to_server (service, ssl_mode, ex); } - - if (service->url->port) { - serv = g_alloca (16); - sprintf (serv, "%d", service->url->port); - port = NULL; - } - - memset (&hints, 0, sizeof (hints)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = PF_UNSPEC; - ai = camel_getaddrinfo(service->url->host, serv, &hints, ex); - if (ai == NULL && port != NULL && camel_exception_get_id(ex) != CAMEL_EXCEPTION_USER_CANCEL) { - camel_exception_clear (ex); - ai = camel_getaddrinfo(service->url->host, port, &hints, ex); - } - if (ai == NULL) - return FALSE; - - ret = connect_to_server (service, ai, mode, ex); - - camel_freeaddrinfo (ai); - - return ret; +#else + return connect_to_server (service, USE_SSL_NEVER, ex); +#endif } static gboolean diff --git a/camel/providers/nntp/camel-nntp-stream.c b/camel/providers/nntp/camel-nntp-stream.c index 244b67acb1..74bee9ced5 100644 --- a/camel/providers/nntp/camel-nntp-stream.c +++ b/camel/providers/nntp/camel-nntp-stream.c @@ -60,8 +60,6 @@ stream_fill(CamelNNTPStream *is) is->end[0] = '\n'; return is->end - is->ptr; } else { - if (left == 0) - errno = ECONNRESET; dd(printf("NNTP_STREAM_FILL(ERROR): %d - '%s'\n", left, strerror(errno))); return -1; } diff --git a/camel/providers/nntp/camel-nntp-summary.c b/camel/providers/nntp/camel-nntp-summary.c index e6c02b95af..02589e632e 100644 --- a/camel/providers/nntp/camel-nntp-summary.c +++ b/camel/providers/nntp/camel-nntp-summary.c @@ -36,7 +36,6 @@ #include "camel/camel-stream-null.h" #include "camel/camel-operation.h" #include "camel/camel-data-cache.h" -#include "camel/camel-i18n.h" #include "camel/camel-debug.h" #include "camel-nntp-summary.h" @@ -60,7 +59,7 @@ struct _CamelNNTPSummaryPrivate { #define _PRIVATE(o) (((CamelNNTPSummary *)(o))->priv) -static CamelMessageInfo * message_info_new_from_header (CamelFolderSummary *, struct _camel_header_raw *); +static CamelMessageInfo * message_info_new (CamelFolderSummary *, struct _camel_header_raw *); static int summary_header_load(CamelFolderSummary *, FILE *); static int summary_header_save(CamelFolderSummary *, FILE *); @@ -94,7 +93,7 @@ camel_nntp_summary_class_init(CamelNNTPSummaryClass *klass) camel_nntp_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS(camel_type_get_global_classfuncs(camel_folder_summary_get_type())); - sklass->message_info_new_from_header = message_info_new_from_header; + sklass->message_info_new = message_info_new; sklass->summary_header_load = summary_header_load; sklass->summary_header_save = summary_header_save; } @@ -108,7 +107,7 @@ camel_nntp_summary_init(CamelNNTPSummary *obj) p = _PRIVATE(obj) = g_malloc0(sizeof(*p)); /* subclasses need to set the right instance data sizes */ - s->message_info_size = sizeof(CamelMessageInfoBase); + s->message_info_size = sizeof(CamelMessageInfo); s->content_info_size = sizeof(CamelMessageContentInfo); /* and a unique file version */ @@ -124,12 +123,10 @@ camel_nntp_summary_finalise(CamelObject *obj) } CamelNNTPSummary * -camel_nntp_summary_new(struct _CamelFolder *folder, const char *path) +camel_nntp_summary_new(const char *path) { CamelNNTPSummary *cns = (CamelNNTPSummary *)camel_object_new(camel_nntp_summary_get_type()); - ((CamelFolderSummary *)cns)->folder = folder; - camel_folder_summary_set_filename((CamelFolderSummary *)cns, path); camel_folder_summary_set_build_content((CamelFolderSummary *)cns, FALSE); @@ -137,9 +134,9 @@ camel_nntp_summary_new(struct _CamelFolder *folder, const char *path) } static CamelMessageInfo * -message_info_new_from_header(CamelFolderSummary *s, struct _camel_header_raw *h) +message_info_new(CamelFolderSummary *s, struct _camel_header_raw *h) { - CamelMessageInfoBase *mi; + CamelMessageInfo *mi; CamelNNTPSummary *cns = (CamelNNTPSummary *)s; /* error to call without this setup */ @@ -149,13 +146,13 @@ message_info_new_from_header(CamelFolderSummary *s, struct _camel_header_raw *h) /* we shouldn't be here if we already have this uid */ g_assert(camel_folder_summary_uid(s, cns->priv->uid) == NULL); - mi = (CamelMessageInfoBase *)((CamelFolderSummaryClass *)camel_nntp_summary_parent)->message_info_new_from_header(s, h); + mi = ((CamelFolderSummaryClass *)camel_nntp_summary_parent)->message_info_new(s, h); if (mi) { - mi->uid = g_strdup(cns->priv->uid); + camel_message_info_set_uid(mi, cns->priv->uid); cns->priv->uid = NULL; } - return (CamelMessageInfo *)mi; + return mi; } static int @@ -209,7 +206,7 @@ static int add_range_xover(CamelNNTPSummary *cns, CamelNNTPStore *store, unsigned int high, unsigned int low, CamelFolderChangeInfo *changes, CamelException *ex) { CamelFolderSummary *s; - CamelMessageInfoBase *mi; + CamelMessageInfo *mi; struct _camel_header_raw *headers = NULL; char *line, *tab; int len, ret; @@ -273,16 +270,16 @@ add_range_xover(CamelNNTPSummary *cns, CamelNNTPStore *store, unsigned int high, /* truncated line? ignore? */ if (xover == NULL) { - mi = (CamelMessageInfoBase *)camel_folder_summary_uid(s, cns->priv->uid); + mi = camel_folder_summary_uid(s, cns->priv->uid); if (mi == NULL) { - mi = (CamelMessageInfoBase *)camel_folder_summary_add_from_header(s, headers); + mi = camel_folder_summary_add_from_header(s, headers); if (mi) { mi->size = size; cns->high = n; camel_folder_change_info_add_uid(changes, camel_message_info_uid(mi)); } } else { - camel_message_info_free(mi); + camel_folder_summary_info_free(s, mi); } } @@ -354,7 +351,7 @@ add_range_head(CamelNNTPSummary *cns, CamelNNTPStore *store, unsigned int high, camel_folder_change_info_add_uid(changes, camel_message_info_uid(mi)); } else { /* already have, ignore */ - camel_message_info_free(mi); + camel_folder_summary_info_free(s, mi); } if (cns->priv->uid) { g_free(cns->priv->uid); @@ -447,7 +444,7 @@ camel_nntp_summary_check(CamelNNTPSummary *cns, CamelNNTPStore *store, char *lin i--; } - camel_message_info_free(mi); + camel_folder_summary_info_free(s, mi); } } cns->low = f; @@ -475,12 +472,12 @@ update: count = camel_folder_summary_count(s); for (i = 0; i < count; i++) { - CamelMessageInfoBase *mi = (CamelMessageInfoBase *)camel_folder_summary_index(s, i); + CamelMessageInfo *mi = camel_folder_summary_index(s, i); if (mi) { if ((mi->flags & CAMEL_MESSAGE_SEEN) == 0) unread++; - camel_message_info_free(mi); + camel_folder_summary_info_free(s, mi); } } diff --git a/camel/providers/pop3/camel-pop3-store.c b/camel/providers/pop3/camel-pop3-store.c index 46a1fd3fe6..f7117b1b31 100644 --- a/camel/providers/pop3/camel-pop3-store.c +++ b/camel/providers/pop3/camel-pop3-store.c @@ -45,7 +45,7 @@ #include "camel-session.h" #include "camel-exception.h" #include "camel-url.h" -#include "libedataserver/md5-utils.h" +#include "e-util/md5-utils.h" #include "camel-pop3-engine.h" #include "camel-sasl.h" #include "camel-data-cache.h" @@ -54,12 +54,9 @@ #ifdef HAVE_SSL #include "camel-tcp-stream-ssl.h" #endif -#include "camel-i18n.h" -#include "camel-net-utils.h" /* Specified in RFC 1939 */ -#define POP3_PORT "110" -#define POP3S_PORT "995" +#define POP3_PORT 110 static CamelStoreClass *parent_class = NULL; @@ -137,16 +134,16 @@ finalize (CamelObject *object) } enum { - MODE_CLEAR, - MODE_SSL, - MODE_TLS, + USE_SSL_NEVER, + USE_SSL_ALWAYS, + USE_SSL_WHEN_POSSIBLE }; #define SSL_PORT_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3) #define STARTTLS_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_TLS) static gboolean -connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, CamelException *ex) +connect_to_server (CamelService *service, int ssl_mode, int try_starttls, CamelException *ex) { CamelPOP3Store *store = CAMEL_POP3_STORE (service); CamelStream *tcp_stream; @@ -154,34 +151,67 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam guint32 flags = 0; int clean_quit; int ret; - - if (ssl_mode != MODE_CLEAR) { + struct addrinfo *ai, hints = { 0 }; + char *serv; + const char *port = NULL; + + if (service->url->port) { + serv = g_alloca(16); + sprintf(serv, "%d", service->url->port); + } else { + serv = "pop3"; + port = "110"; + } + + if (ssl_mode != USE_SSL_NEVER) { #ifdef HAVE_SSL - if (ssl_mode == MODE_TLS) { + if (try_starttls) { tcp_stream = camel_tcp_stream_ssl_new_raw (service->session, service->url->host, STARTTLS_FLAGS); } else { + if (service->url->port == 0) { + serv = "pop3s"; + port = "995"; + } tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, SSL_PORT_FLAGS); } #else + if (!try_starttls && service->url->port == 0) { + serv = "pop3s"; + port = "995"; + } + camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s: %s"), - service->url->host, _("SSL unavailable")); + _("Could not connect to %s (port %s): %s"), + service->url->host, serv, + _("SSL unavailable")); return FALSE; #endif /* HAVE_SSL */ } else { tcp_stream = camel_tcp_stream_raw_new (); } + + hints.ai_socktype = SOCK_STREAM; + ai = camel_getaddrinfo(service->url->host, serv, &hints, ex); + if (ai == NULL && port != NULL && camel_exception_get_id(ex) != CAMEL_EXCEPTION_USER_CANCEL) { + camel_exception_clear(ex); + ai = camel_getaddrinfo(service->url->host, port, &hints, ex); + } + if (ai == NULL) { + camel_object_unref(tcp_stream); + return FALSE; + } - if ((ret = camel_tcp_stream_connect ((CamelTcpStream *) tcp_stream, ai)) == -1) { + ret = camel_tcp_stream_connect(CAMEL_TCP_STREAM(tcp_stream), ai); + camel_freeaddrinfo(ai); + if (ret == -1) { if (errno == EINTR) camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Connection cancelled")); else camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s: %s"), - service->url->host, - g_strerror (errno)); + _("Could not connect to POP server %s (port %s): %s"), + service->url->host, serv, g_strerror (errno)); camel_object_unref (tcp_stream); @@ -199,24 +229,41 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam if (!(store->engine = camel_pop3_engine_new (tcp_stream, flags))) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to read a valid greeting from POP server %s"), - service->url->host); - camel_object_unref (tcp_stream); + _("Failed to read a valid greeting from POP server %s (port %s)"), + service->url->host, serv); return FALSE; } - if (ssl_mode != MODE_TLS) { - camel_object_unref (tcp_stream); - return TRUE; +#ifdef HAVE_SSL + if (store->engine) { + if (ssl_mode == USE_SSL_WHEN_POSSIBLE) { + if (store->engine->capa & CAMEL_POP3_CAP_STLS) + goto starttls; + } else if (ssl_mode == USE_SSL_ALWAYS) { + if (try_starttls) { + if (store->engine->capa & CAMEL_POP3_CAP_STLS) { + /* attempt to toggle STARTTLS mode */ + goto starttls; + } else { + /* server doesn't support STARTTLS, abort */ + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + _("Failed to connect to POP server %s in secure mode: %s"), + service->url->host, _("SSL/TLS extension not supported.")); + /* we have the possibility of quitting cleanly here */ + clean_quit = TRUE; + goto stls_exception; + } + } + } } +#endif /* HAVE_SSL */ - if (!(store->engine->capa & CAMEL_POP3_CAP_STLS)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to POP server %s in secure mode: %s"), - service->url->host, _("STLS not supported")); - goto stls_exception; - } + camel_object_unref (tcp_stream); + return store->engine != NULL; + +#ifdef HAVE_SSL + starttls: /* as soon as we send a STLS command, all hope is lost of a clean QUIT if problems arise */ clean_quit = FALSE; @@ -237,6 +284,8 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam /* Okay, now toggle SSL/TLS mode */ ret = camel_tcp_stream_ssl_enable_ssl (CAMEL_TCP_STREAM_SSL (tcp_stream)); + camel_object_unref (CAMEL_OBJECT (tcp_stream)); + if (ret == -1) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to connect to POP server %s in secure mode: %s"), @@ -244,8 +293,6 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam goto stls_exception; } - camel_object_unref (tcp_stream); - /* rfc2595, section 4 states that after a successful STLS command, the client MUST discard prior CAPA responses */ camel_pop3_engine_reget_capabilities (store->engine); @@ -266,71 +313,59 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam store->engine = NULL; return FALSE; +#endif /* HAVE_SSL */ } static struct { char *value; - char *serv; - char *port; int mode; } ssl_options[] = { - { "", "pop3s", POP3S_PORT, MODE_SSL }, /* really old (1.x) */ - { "always", "pop3s", POP3S_PORT, MODE_SSL }, - { "when-possible", "pop3", POP3_PORT, MODE_TLS }, - { "never", "pop3", POP3_PORT, MODE_CLEAR }, - { NULL, "pop3", POP3_PORT, MODE_CLEAR }, + { "", USE_SSL_ALWAYS }, + { "always", USE_SSL_ALWAYS }, + { "when-possible", USE_SSL_WHEN_POSSIBLE }, + { "never", USE_SSL_NEVER }, + { NULL, USE_SSL_NEVER }, }; static gboolean connect_to_server_wrapper (CamelService *service, CamelException *ex) { - struct addrinfo hints, *ai; - const char *ssl_mode; - int mode, ret, i; - char *serv; - const char *port; - - if ((ssl_mode = camel_url_get_param (service->url, "use_ssl"))) { +#ifdef HAVE_SSL + const char *use_ssl; + int i, ssl_mode; + + use_ssl = camel_url_get_param (service->url, "use_ssl"); + if (use_ssl) { for (i = 0; ssl_options[i].value; i++) - if (!strcmp (ssl_options[i].value, ssl_mode)) + if (!strcmp (ssl_options[i].value, use_ssl)) break; - mode = ssl_options[i].mode; - serv = ssl_options[i].serv; - port = ssl_options[i].port; + ssl_mode = ssl_options[i].mode; + } else + ssl_mode = USE_SSL_NEVER; + + if (ssl_mode == USE_SSL_ALWAYS) { + /* First try the ssl port */ + if (!connect_to_server (service, ssl_mode, FALSE, ex)) { + if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_SERVICE_UNAVAILABLE) { + /* The ssl port seems to be unavailable, lets try STARTTLS */ + camel_exception_clear (ex); + return connect_to_server (service, ssl_mode, TRUE, ex); + } else { + return FALSE; + } + } + + return TRUE; + } else if (ssl_mode == USE_SSL_WHEN_POSSIBLE) { + /* If the server supports STARTTLS, use it */ + return connect_to_server (service, ssl_mode, TRUE, ex); } else { - mode = MODE_CLEAR; - serv = "pop3"; - port = POP3S_PORT; + /* User doesn't care about SSL */ + return connect_to_server (service, ssl_mode, FALSE, ex); } - - if (service->url->port) { - serv = g_alloca (16); - sprintf (serv, "%d", service->url->port); - port = NULL; - } - - memset (&hints, 0, sizeof (hints)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = PF_UNSPEC; - ai = camel_getaddrinfo(service->url->host, serv, &hints, ex); - if (ai == NULL && port != NULL && camel_exception_get_id(ex) != CAMEL_EXCEPTION_USER_CANCEL) { - camel_exception_clear (ex); - ai = camel_getaddrinfo(service->url->host, port, &hints, ex); - } - if (ai == NULL) - return FALSE; - - if (!(ret = connect_to_server (service, ai, mode, ex)) && mode == MODE_SSL) { - camel_exception_clear (ex); - ret = connect_to_server (service, ai, MODE_TLS, ex); - } else if (!ret && mode == MODE_TLS) { - camel_exception_clear (ex); - ret = connect_to_server (service, ai, MODE_CLEAR, ex); - } - - camel_freeaddrinfo (ai); - - return ret; +#else + return connect_to_server (service, USE_SSL_NEVER, FALSE, ex); +#endif } extern CamelServiceAuthType camel_pop3_password_authtype; diff --git a/camel/providers/smtp/camel-smtp-transport.c b/camel/providers/smtp/camel-smtp-transport.c index 065d79fdac..ea8ca26e49 100644 --- a/camel/providers/smtp/camel-smtp-transport.c +++ b/camel/providers/smtp/camel-smtp-transport.c @@ -55,15 +55,13 @@ #include "camel-session.h" #include "camel-exception.h" #include "camel-sasl.h" -#include "camel-i18n.h" -#include "camel-net-utils.h" + extern int camel_verbose_debug; #define d(x) (camel_verbose_debug ? (x) : 0) /* Specified in RFC 821 */ -#define SMTP_PORT "25" -#define SMTPS_PORT "465" +#define SMTP_PORT 25 /* camel smtp transport class prototypes */ static gboolean smtp_send_to (CamelTransport *transport, CamelMimeMessage *message, @@ -147,7 +145,18 @@ smtp_construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex) { + CamelSmtpTransport *smtp_transport = CAMEL_SMTP_TRANSPORT (service); + const char *use_ssl; + CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); + + if ((use_ssl = camel_url_get_param (url, "use_ssl"))) { + /* Note: previous versions would use "" to toggle use_ssl to 'on' */ + if (!*use_ssl || !strcmp (use_ssl, "always")) + smtp_transport->flags |= CAMEL_SMTP_TRANSPORT_USE_SSL_ALWAYS; + else if (!strcmp (use_ssl, "when-possible")) + smtp_transport->flags |= CAMEL_SMTP_TRANSPORT_USE_SSL_WHEN_POSSIBLE; + } } static const char * @@ -219,56 +228,82 @@ smtp_error_string (int error) } } -enum { - MODE_CLEAR, - MODE_SSL, - MODE_TLS, -}; - #define SSL_PORT_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3) #define STARTTLS_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_TLS) static gboolean -connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, CamelException *ex) +connect_to_server (CamelService *service, int try_starttls, CamelException *ex) { CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service); CamelStream *tcp_stream; char *respbuf = NULL; int ret; + struct addrinfo *ai, hints = { 0 }; + char *serv; + const char *port = NULL; if (!CAMEL_SERVICE_CLASS (parent_class)->connect (service, ex)) return FALSE; /* set some smtp transport defaults */ - transport->flags = 0; + transport->flags &= CAMEL_SMTP_TRANSPORT_USE_SSL; /* reset all but ssl flags */ transport->authtypes = NULL; + + if (service->url->port) { + serv = g_alloca(16); + sprintf(serv, "%d", service->url->port); + } else { + serv = "smtp"; + port = "25"; + } - if (ssl_mode != MODE_CLEAR) { + if (transport->flags & CAMEL_SMTP_TRANSPORT_USE_SSL) { #ifdef HAVE_SSL - if (ssl_mode == MODE_TLS) { - tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, STARTTLS_FLAGS); + if (try_starttls) { + tcp_stream = camel_tcp_stream_ssl_new_raw (service->session, service->url->host, STARTTLS_FLAGS); } else { + if (service->url->port == 0) { + serv = "smtps"; + port = "465"; + } tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, SSL_PORT_FLAGS); } #else - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s: %s"), - service->url->host, _("SSL unavailable")); + if (!try_starttls && service->url->port == 0) { + serv = "smtps"; + port = "465"; + } + camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, + _("Could not connect to %s (port %s): %s"), + service->url->host, serv, + _("SSL unavailable")); + return FALSE; #endif /* HAVE_SSL */ } else { tcp_stream = camel_tcp_stream_raw_new (); } + + hints.ai_socktype = SOCK_STREAM; + ai = camel_getaddrinfo(service->url->host, serv, &hints, ex); + /* fallback to numerical port if the system is misconfigured */ + if (ai == NULL && port != NULL && camel_exception_get_id(ex) != CAMEL_EXCEPTION_USER_CANCEL) { + camel_exception_clear(ex); + ai = camel_getaddrinfo(service->url->host, port, &hints, ex); + } + if (ai == NULL) { + camel_object_unref(tcp_stream); + return FALSE; + } - if ((ret = camel_tcp_stream_connect ((CamelTcpStream *) tcp_stream, ai)) == -1) { - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Connection cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s: %s"), - service->url->host, g_strerror (errno)); + ret = camel_tcp_stream_connect(CAMEL_TCP_STREAM(tcp_stream), ai); + camel_freeaddrinfo(ai); + if (ret == -1) { + camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, + _("Could not connect to %s (port %s): %s"), + service->url->host, serv, + g_strerror (errno)); camel_object_unref (tcp_stream); @@ -312,19 +347,30 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam /* clear any EHLO/HELO exception and assume that any SMTP errors encountered were non-fatal */ camel_exception_clear (ex); - if (ssl_mode != MODE_TLS) { - /* we're done */ - return TRUE; +#ifdef HAVE_SSL + if (transport->flags & CAMEL_SMTP_TRANSPORT_USE_SSL_WHEN_POSSIBLE) { + /* try_starttls is always TRUE here */ + if (transport->flags & CAMEL_SMTP_TRANSPORT_STARTTLS) + goto starttls; + } else if (transport->flags & CAMEL_SMTP_TRANSPORT_USE_SSL_ALWAYS) { + if (try_starttls) { + if (transport->flags & CAMEL_SMTP_TRANSPORT_STARTTLS) { + goto starttls; + } else { + /* server doesn't support STARTTLS, abort */ + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + _("Failed to connect to SMTP server %s in secure mode: %s"), + service->url->host, _("server does not appear to support SSL")); + goto exception_cleanup; + } + } } +#endif /* HAVE_SSL */ - if (!(transport->flags & CAMEL_SMTP_TRANSPORT_STARTTLS)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to SMTP server %s in secure mode: %s"), - service->url->host, _("STARTTLS not supported")); - - goto exception_cleanup; - } + return TRUE; +#ifdef HAVE_SSL + starttls: d(fprintf (stderr, "sending : STARTTLS\r\n")); if (camel_stream_write (tcp_stream, "STARTTLS\r\n", 10) == -1) { camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM, @@ -374,68 +420,38 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam transport->connected = FALSE; return FALSE; +#endif /* HAVE_SSL */ } -static struct { - char *value; - char *serv; - char *port; - int mode; -} ssl_options[] = { - { "", "smtps", SMTPS_PORT, MODE_SSL }, /* really old (1.x) */ - { "always", "smtps", SMTPS_PORT, MODE_SSL }, - { "when-possible", "smtp", SMTP_PORT, MODE_TLS }, - { "never", "smtp", SMTP_PORT, MODE_CLEAR }, - { NULL, "smtp", SMTP_PORT, MODE_CLEAR }, -}; - static gboolean connect_to_server_wrapper (CamelService *service, CamelException *ex) { - struct addrinfo hints, *ai; - const char *ssl_mode; - int mode, ret, i; - char *serv; - const char *port; - - if ((ssl_mode = camel_url_get_param (service->url, "use_ssl"))) { - for (i = 0; ssl_options[i].value; i++) - if (!strcmp (ssl_options[i].value, ssl_mode)) - break; - mode = ssl_options[i].mode; - serv = ssl_options[i].serv; - port = ssl_options[i].port; - } else { - mode = MODE_CLEAR; - serv = "smtp"; - port = SMTP_PORT; - } - - if (service->url->port) { - serv = g_alloca (16); - sprintf (serv, "%d", service->url->port); - port = NULL; - } +#ifdef HAVE_SSL + CamelSmtpTransport *transport = (CamelSmtpTransport *) service; - memset (&hints, 0, sizeof (hints)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = PF_UNSPEC; - ai = camel_getaddrinfo(service->url->host, serv, &hints, ex); - if (ai == NULL && port != NULL && camel_exception_get_id(ex) != CAMEL_EXCEPTION_USER_CANCEL) { - camel_exception_clear (ex); - ai = camel_getaddrinfo(service->url->host, port, &hints, ex); + if (transport->flags & CAMEL_SMTP_TRANSPORT_USE_SSL_ALWAYS) { + /* First try connecting to the SSL port */ + if (!connect_to_server (service, FALSE, ex)) { + if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_SERVICE_UNAVAILABLE) { + /* Seems the SSL port is unavailable, lets try STARTTLS */ + camel_exception_clear (ex); + return connect_to_server (service, TRUE, ex); + } else { + return FALSE; + } + } + + return TRUE; + } else if (transport->flags & CAMEL_SMTP_TRANSPORT_USE_SSL_WHEN_POSSIBLE) { + /* If the server supports STARTTLS, use it */ + return connect_to_server (service, TRUE, ex); + } else { + /* User doesn't care about SSL */ + return connect_to_server (service, FALSE, ex); } - if (ai == NULL) - return FALSE; - - if (!(ret = connect_to_server (service, ai, mode, ex)) && mode == MODE_SSL) - ret = connect_to_server (service, ai, MODE_TLS, ex); - else if (!ret && mode == MODE_TLS) - ret = connect_to_server (service, ai, MODE_CLEAR, ex); - - camel_freeaddrinfo (ai); - - return ret; +#else + return connect_to_server (service, FALSE, ex); +#endif } static gboolean diff --git a/camel/providers/smtp/camel-smtp-transport.h b/camel/providers/smtp/camel-smtp-transport.h index 7b5ad88f12..87fcafb58b 100644 --- a/camel/providers/smtp/camel-smtp-transport.h +++ b/camel/providers/smtp/camel-smtp-transport.h @@ -43,7 +43,13 @@ extern "C" { #define CAMEL_SMTP_TRANSPORT_ENHANCEDSTATUSCODES (1 << 2) #define CAMEL_SMTP_TRANSPORT_STARTTLS (1 << 3) -#define CAMEL_SMTP_TRANSPORT_AUTH_EQUAL (1 << 4) /* set if we are using authtypes from a broken AUTH= */ +#define CAMEL_SMTP_TRANSPORT_USE_SSL_ALWAYS (1 << 4) +#define CAMEL_SMTP_TRANSPORT_USE_SSL_WHEN_POSSIBLE (1 << 5) + +#define CAMEL_SMTP_TRANSPORT_USE_SSL (CAMEL_SMTP_TRANSPORT_USE_SSL_ALWAYS | \ + CAMEL_SMTP_TRANSPORT_USE_SSL_WHEN_POSSIBLE) + +#define CAMEL_SMTP_TRANSPORT_AUTH_EQUAL (1 << 6) /* set if we are using authtypes from a broken AUTH= */ typedef struct { CamelTransport parent_object; diff --git a/camel/tests/data/messages/.cvsignore b/camel/tests/data/messages/.cvsignore deleted file mode 100644 index e358dd1903..0000000000 --- a/camel/tests/data/messages/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -*.msg diff --git a/camel/tests/lib/folders.c b/camel/tests/lib/folders.c index 5104da6c12..e93d8caf2e 100644 --- a/camel/tests/lib/folders.c +++ b/camel/tests/lib/folders.c @@ -12,15 +12,13 @@ test_folder_counts(CamelFolder *folder, int total, int unread) { GPtrArray *s; int i, myunread; - int gettotal, getunread; CamelMessageInfo *info; push("test folder counts %d total %d unread", total, unread); /* first, use the standard functions */ - camel_object_get(folder, NULL, CAMEL_FOLDER_TOTAL, &gettotal, CAMEL_FOLDER_UNREAD, &getunread, 0); - check(gettotal == total); - check(getunread == unread); + check(camel_folder_get_message_count(folder) == total); + check(camel_folder_get_unread_message_count(folder) == total); /* next, use the summary */ s = camel_folder_get_summary(folder); @@ -29,7 +27,7 @@ test_folder_counts(CamelFolder *folder, int total, int unread) myunread = s->len; for (i=0;i<s->len;i++) { info = s->pdata[i]; - if (camel_message_info_flags(info) & CAMEL_MESSAGE_SEEN) + if (info->flags & CAMEL_MESSAGE_SEEN) myunread--; } check(unread == myunread); @@ -42,7 +40,7 @@ test_folder_counts(CamelFolder *folder, int total, int unread) myunread = s->len; for (i=0;i<s->len;i++) { info = camel_folder_get_message_info(folder, s->pdata[i]); - if (camel_message_info_flags(info) & CAMEL_MESSAGE_SEEN) + if (info->flags & CAMEL_MESSAGE_SEEN) myunread--; camel_folder_free_message_info(folder, info); } @@ -72,7 +70,7 @@ test_message_info(CamelMimeMessage *msg, const CamelMessageInfo *info) /* FIXME: testing from/cc/to, etc is more tricky */ - check(camel_message_info_date_sent(info) == camel_mime_message_get_date(msg, NULL)); + check(info->date_sent == camel_mime_message_get_date(msg, NULL)); /* date received isn't set for messages that haven't been sent anywhere ... */ /*check(info->date_received == camel_mime_message_get_date_received(msg, NULL));*/ @@ -471,7 +469,7 @@ test_folder_message_ops(CamelSession *session, const char *name, int local, cons push("deleting first message & expunging"); camel_folder_delete_message(folder, uids->pdata[0]); - test_folder_counts(folder, 10, 9); + test_folder_counts(folder, 10, 10); camel_folder_expunge(folder, ex); check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); test_folder_not_message(folder, uids->pdata[0]); @@ -500,7 +498,7 @@ test_folder_message_ops(CamelSession *session, const char *name, int local, cons push("deleting last message & expunging"); camel_folder_delete_message(folder, uids->pdata[8]); /* sync? */ - test_folder_counts(folder, 9, 8); + test_folder_counts(folder, 9, 9); camel_folder_expunge(folder, ex); check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); test_folder_not_message(folder, uids->pdata[8]); @@ -531,7 +529,7 @@ test_folder_message_ops(CamelSession *session, const char *name, int local, cons camel_folder_delete_message(folder, uids->pdata[j]); } /* sync? */ - test_folder_counts(folder, 8, 0); + test_folder_counts(folder, 8, 8); camel_folder_expunge(folder, ex); check_msg(!camel_exception_is_set(ex), "%s", camel_exception_get_description(ex)); for (j=0;j<8;j++) { |