diff options
Diffstat (limited to 'camel/providers')
165 files changed, 0 insertions, 49775 deletions
diff --git a/camel/providers/.cvsignore b/camel/providers/.cvsignore deleted file mode 100644 index 3dda72986f..0000000000 --- a/camel/providers/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -Makefile.in -Makefile diff --git a/camel/providers/Makefile.am b/camel/providers/Makefile.am deleted file mode 100644 index 0444da4382..0000000000 --- a/camel/providers/Makefile.am +++ /dev/null @@ -1,18 +0,0 @@ -## Process this file with automake to produce Makefile.in - -if ENABLE_NNTP -NNTP_DIR=nntp -endif - -if ENABLE_IMAPP -IMAPP_DIR=imapp -endif - -if ENABLE_IMAP4 -IMAP4_DIR=imap4 -endif - -SUBDIRS = pop3 sendmail smtp imap $(NNTP_DIR) local $(IMAPP_DIR) $(IMAP4_DIR) -# groupwise - - diff --git a/camel/providers/groupwise/.cvsignore b/camel/providers/groupwise/.cvsignore deleted file mode 100644 index 282522db03..0000000000 --- a/camel/providers/groupwise/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -Makefile -Makefile.in diff --git a/camel/providers/groupwise/Makefile.am b/camel/providers/groupwise/Makefile.am deleted file mode 100644 index b15259532c..0000000000 --- a/camel/providers/groupwise/Makefile.am +++ /dev/null @@ -1,28 +0,0 @@ -## Process this file with automake to produce Makefile.in - -libcamelimapincludedir = $(privincludedir)/camel - -camel_provider_LTLIBRARIES = libcamelgroupwise.la -camel_provider_DATA = libcamelgroupwise.urls - -INCLUDES = \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/servers/groupwise \ - -I$(top_srcdir) \ - -I$(top_srcdir)/camel/providers/imap \ - -I$(top_srcdir)/camel/providers/smtp \ - $(CAMEL_GROUPWISE_CFLAGS) \ - -DCAMEL_PROVIDERDIR=\"$(camel_providerdir)\" \ - -DG_LOG_DOMAIN=\"camel-groupwise-provider\" - -libcamelgroupwise_la_SOURCES = \ - camel-groupwise-provider.c \ - camel-gw-listener.c \ - camel-gw-listener.h -libcamelgroupwise_la_LIBADD = $(CAMEL_GROUPWISE_LIBS) - -libcamelgroupwise_la_LDFLAGS = -avoid-version -module - -EXTRA_DIST = libcamelgroupwise.urls - diff --git a/camel/providers/groupwise/camel-groupwise-provider.c b/camel/providers/groupwise/camel-groupwise-provider.c deleted file mode 100644 index 1162347c42..0000000000 --- a/camel/providers/groupwise/camel-groupwise-provider.c +++ /dev/null @@ -1,207 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-groupwise-provider.c: Groupwise provider registration code */ - -/* - * Authors: Jeffrey Stedfast <fejj@ximian.com> - * Sivaiah Nallagatla <snallagatla@novell.com> - * Rodrigo Moya <rodrigo@ximian.com> - * - * Copyright 2003 Novell, Inc. (www.novell.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <gmodule.h> -#include "camel-imap-store.h" -#include "camel-provider.h" -#include "camel-session.h" -#include "camel-smtp-transport.h" -#include "camel-url.h" -#include "camel-sasl.h" -#include "camel-gw-listener.h" -#include "camel-i18n.h" - -static void add_hash (guint *hash, char *s); -static guint groupwise_url_hash (gconstpointer key); -static gint check_equal (char *s1, char *s2); -static gint groupwise_url_equal (gconstpointer a, gconstpointer b); -static void free_groupwise_listener ( void ); - -static CamelGwListener *config_listener = NULL; - -CamelProviderConfEntry groupwise_conf_entries[] = { - /* override the labels/defaults of the standard settings */ - - { CAMEL_PROVIDER_CONF_SECTION_START, "mailcheck", NULL, - N_("Checking for new mail") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "check_all", NULL, - N_("Check for new messages in all folders"), "1" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - - { CAMEL_PROVIDER_CONF_SECTION_START, "general", NULL, N_("Options") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter", NULL, - N_("Apply filters to new messages in Inbox on this server"), "0" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter_junk", NULL, - N_("Check new messages for Junk contents"), "0" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter_junk_inbox", "filter_junk", - N_("Only check for Junk messages in the INBOX folder"), "0" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "offline_sync", NULL, - N_("Automatically synchronize account locally"), "0" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - - /* extra Groupwise configuration settings */ - {CAMEL_PROVIDER_CONF_SECTION_START, "soapport", NULL, - N_("Address Book and Calendar") }, - - { CAMEL_PROVIDER_CONF_ENTRY , "poa", NULL, - N_("Post Office Agent:"), NULL }, - - { CAMEL_PROVIDER_CONF_ENTRY, "soap_port", NULL, - N_("Post Office Agent SOAP Port:"), "7181" }, - - { CAMEL_PROVIDER_CONF_CHECKBOX, "soap_ssl", NULL, - N_("Use Secure Connection (SSL)"), "0"}, - - { CAMEL_PROVIDER_CONF_HIDDEN, "auth-domain", NULL, - NULL, "Groupwise" }, - - { CAMEL_PROVIDER_CONF_SECTION_END }, - - { CAMEL_PROVIDER_CONF_END } -}; - - -static CamelProvider groupwise_provider = { - "groupwise", - N_("Novell GroupWise"), - - N_("For accessing Novell Groupwise servers"), - - "mail", - - CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE | - CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_SUPPORTS_SSL, - - CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH, - - groupwise_conf_entries, - - /* ... */ -}; - -CamelServiceAuthType camel_groupwise_password_authtype = { - N_("Password"), - - N_("This option will connect to the IMAP server using a " - "plaintext password."), - - "", - TRUE -}; - -static int -groupwise_auto_detect_cb (CamelURL *url, GHashTable **auto_detected, - CamelException *ex) -{ - *auto_detected = g_hash_table_new (g_str_hash, g_str_equal); - - g_hash_table_insert (*auto_detected, g_strdup ("poa"), - g_strdup (url->host)); - - return 0; -} - -void -camel_provider_module_init(void) -{ - CamelProvider *imap_provider; - CamelException ex = CAMEL_EXCEPTION_INITIALISER; - - imap_provider = camel_provider_get("imap://", &ex); - groupwise_provider.url_hash = groupwise_url_hash; - groupwise_provider.url_equal = groupwise_url_equal; - groupwise_provider.auto_detect = groupwise_auto_detect_cb; - groupwise_provider.authtypes = g_list_prepend (groupwise_provider.authtypes, &camel_groupwise_password_authtype); - if (imap_provider != NULL) { - groupwise_provider.object_types[CAMEL_PROVIDER_STORE] = imap_provider->object_types [CAMEL_PROVIDER_STORE]; - camel_provider_register(&groupwise_provider); - } else { - camel_exception_clear(&ex); - } - - if (!config_listener) { - config_listener = camel_gw_listener_new (); - g_atexit ( free_groupwise_listener ); - } -} - -void free_groupwise_listener ( void ) -{ - g_object_unref (config_listener); -} - -static void -add_hash (guint *hash, char *s) -{ - if (s) - *hash ^= g_str_hash(s); -} - -static guint -groupwise_url_hash (gconstpointer key) -{ - const CamelURL *u = (CamelURL *)key; - guint hash = 0; - - add_hash (&hash, u->user); - add_hash (&hash, u->authmech); - add_hash (&hash, u->host); - hash ^= u->port; - - return hash; -} - -static gint -check_equal (char *s1, char *s2) -{ - if (s1 == NULL) { - if (s2 == NULL) - return TRUE; - else - return FALSE; - } - - if (s2 == NULL) - return FALSE; - - return strcmp (s1, s2) == 0; -} - -static gint -groupwise_url_equal (gconstpointer a, gconstpointer b) -{ - const CamelURL *u1 = a, *u2 = b; - - return check_equal (u1->user, u2->user) - && check_equal (u1->authmech, u2->authmech) - && check_equal (u1->host, u2->host) - && u1->port == u2->port; -} diff --git a/camel/providers/groupwise/camel-gw-listener.c b/camel/providers/groupwise/camel-gw-listener.c deleted file mode 100644 index 1f6eaf6267..0000000000 --- a/camel/providers/groupwise/camel-gw-listener.c +++ /dev/null @@ -1,921 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors : - * - * Sivaiah Nallagatla <snallagatla@novell.com> - * - * Copyright 2003, Novell, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "camel-gw-listener.h" -#include <string.h> -#include "camel-i18n.h" -#include <e-gw-connection.h> -#include <e-passwords.h> -#include "widgets/misc/e-error.h" - -/*stores some info about all currently existing groupwise accounts - list of GwAccountInfo structures */ - -static GList *groupwise_accounts = NULL; - -struct _CamelGwListenerPrivate { - GConfClient *gconf_client; - /* we get notification about mail account changes form this object */ - EAccountList *account_list; -}; - -struct _GwAccountInfo { - char *uid; - char *name; - char *source_url; -}; - -typedef struct _GwAccountInfo GwAccountInfo; - -#define GROUPWISE_URI_PREFIX "groupwise://" -#define GROUPWISE_PREFIX_LENGTH 12 - -#define PARENT_TYPE G_TYPE_OBJECT - -static GObjectClass *parent_class = NULL; - -static void dispose (GObject *object); -static void finalize (GObject *object); - - -static void -camel_gw_listener_class_init (CamelGwListenerClass *class) -{ - GObjectClass *object_class; - - parent_class = g_type_class_ref (PARENT_TYPE); - object_class = G_OBJECT_CLASS (class); - - /* virtual method override */ - object_class->dispose = dispose; - object_class->finalize = finalize; -} - -static void -camel_gw_listener_init (CamelGwListener *config_listener, CamelGwListenerClass *class) -{ - config_listener->priv = g_new0 (CamelGwListenerPrivate, 1); -} - -static void -dispose (GObject *object) -{ - CamelGwListener *config_listener = CAMEL_GW_LISTENER (object); - - g_object_unref (config_listener->priv->gconf_client); - g_object_unref (config_listener->priv->account_list); - - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -finalize (GObject *object) -{ - CamelGwListener *config_listener = CAMEL_GW_LISTENER (object); - GList *list; - GwAccountInfo *info; - - if (config_listener->priv) { - g_free (config_listener->priv); - } - - for ( list = g_list_first (groupwise_accounts); list ; list = g_list_next (list) ) { - - info = (GwAccountInfo *) (list->data); - - if (info) { - - g_free (info->uid); - g_free (info->name); - g_free (info->source_url); - g_free (info); - } - } - - g_list_free (groupwise_accounts); -} - -/*determines whehter the passed in account is groupwise or not by looking at source url */ - -static gboolean -is_groupwise_account (EAccount *account) -{ - if (account->source->url != NULL) { - return (strncmp (account->source->url, GROUPWISE_URI_PREFIX, GROUPWISE_PREFIX_LENGTH ) == 0); - } else { - return FALSE; - } -} - -/* looks up for an existing groupwise account info in the groupwise_accounts list based on uid */ - -static GwAccountInfo* -lookup_account_info (const char *key) -{ - GList *list; - GwAccountInfo *info ; - int found = 0; - - if (!key) - return NULL; - - info = NULL; - - for (list = g_list_first (groupwise_accounts); list; list = g_list_next (list)) { - info = (GwAccountInfo *) (list->data); - found = (strcmp (info->uid, key) == 0); - if (found) - break; - } - if (found) - return info; - return NULL; -} - -#define CALENDAR_SOURCES "/apps/evolution/calendar/sources" -#define TASKS_SOURCES "/apps/evolution/tasks/sources" -#define SELECTED_CALENDARS "/apps/evolution/calendar/display/selected_calendars" -#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) -{ - ESourceList *source_list; - ESourceGroup *group; - ESource *source; - 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)) - 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, "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_group_add_source (group, source, -1); - e_source_list_sync (source_list, NULL); - - if (!strcmp (conf_key, CALENDAR_SOURCES)) - source_selection_key = SELECTED_CALENDARS; - else if (!strcmp (conf_key, TASKS_SOURCES)) - source_selection_key = SELECTED_TASKS; - else source_selection_key = NULL; - if (source_selection_key) { - ids = gconf_client_get_list (client, source_selection_key , GCONF_VALUE_STRING, NULL); - ids = g_slist_append (ids, g_strdup (e_source_peek_uid (source))); - gconf_client_set_list (client, source_selection_key, GCONF_VALUE_STRING, ids, NULL); - temp = ids; - for (; temp != NULL; temp = g_slist_next (temp)) - g_free (temp->data); - g_slist_free (ids); - } - - g_object_unref (source); - g_object_unref (group); - g_object_unref (source_list); - g_object_unref (client); - g_free (relative_uri); -} - - -static void -remove_esource (const char *conf_key, const char *group_name, char* source_name, const char* relative_uri) -{ - ESourceList *list; - ESourceGroup *group; - ESource *source; - GSList *groups; - GSList *sources; - gboolean found_group; - GConfClient* client; - GSList *ids; - GSList *node_tobe_deleted; - char *source_selection_key; - - client = gconf_client_get_default(); - list = e_source_list_new_for_gconf (client, conf_key); - groups = e_source_list_peek_groups (list); - - found_group = FALSE; - - for ( ; groups != NULL && !found_group; groups = g_slist_next (groups)) { - - group = E_SOURCE_GROUP (groups->data); - - if (strcmp (e_source_group_peek_name (group), group_name) == 0 && - strcmp (e_source_group_peek_base_uri (group), GROUPWISE_URI_PREFIX ) == 0) { - - sources = e_source_group_peek_sources (group); - - for( ; sources != NULL; sources = g_slist_next (sources)) { - - source = E_SOURCE (sources->data); - - if (strcmp (e_source_peek_relative_uri (source), relative_uri) == 0) { - - if (!strcmp (conf_key, CALENDAR_SOURCES)) - source_selection_key = SELECTED_CALENDARS; - else if (!strcmp (conf_key, TASKS_SOURCES)) - source_selection_key = SELECTED_TASKS; - else source_selection_key = NULL; - if (source_selection_key) { - ids = gconf_client_get_list (client, source_selection_key , - GCONF_VALUE_STRING, NULL); - node_tobe_deleted = g_slist_find_custom (ids, e_source_peek_uid (source), (GCompareFunc) strcmp); - if (node_tobe_deleted) { - g_free (node_tobe_deleted->data); - ids = g_slist_delete_link (ids, node_tobe_deleted); - } - gconf_client_set_list (client, source_selection_key, - GCONF_VALUE_STRING, ids, NULL); - - } - e_source_list_remove_group (list, group); - e_source_list_sync (list, NULL); - found_group = TRUE; - break; - - } - } - - } - - - } - - g_object_unref (list); - g_object_unref (client); - -} - -/* 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) -{ - ESourceList *list; - ESourceGroup *group; - ESource *source; - GSList *groups; - GSList *sources; - char *old_relative_uri; - CamelURL *url; - 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); - groups = e_source_list_peek_groups (list); - - found_group = FALSE; - - for ( ; groups != NULL && !found_group; groups = g_slist_next (groups)) { - - group = E_SOURCE_GROUP (groups->data); - - if (strcmp (e_source_group_peek_name (group), old_account_info->name) == 0 && - strcmp (e_source_group_peek_base_uri (group), GROUPWISE_URI_PREFIX) == 0) { - - sources = e_source_group_peek_sources (group); - - for ( ; sources != NULL; sources = g_slist_next (sources)) { - - source = E_SOURCE (sources->data); - - 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_list_sync (list, NULL); - found_group = TRUE; - g_free (new_relative_uri); - break; - } - } - } - } - - g_object_unref (list); - 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 - adds the new account info to groupwise_accounts list */ - -static void -add_calendar_tasks_sources (GwAccountInfo *info) -{ - CamelURL *url; - char *relative_uri; - const char *soap_port; - const char * use_ssl; - const char *poa_address; - - url = camel_url_new (info->source_url, NULL); - 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; - - 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); - - camel_url_free (url); - g_free (relative_uri); - -} - -/* removes calendar and tasks sources if the account removed is groupwise account - removes the the account info from groupwise_account list */ - -static void -remove_calendar_tasks_sources (GwAccountInfo *info) -{ - CamelURL *url; - char *relative_uri; - const char *soap_port; - const char *poa_address; - - url = camel_url_new (info->source_url, NULL); - - 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"; - - relative_uri = g_strdup_printf ("%s@%s/", url->user, poa_address); - remove_esource ("/apps/evolution/calendar/sources", info->name, _("Calendar"), relative_uri); - remove_esource ("/apps/evolution/tasks/sources", info->name, _("Checklist"), relative_uri); - camel_url_free (url); - g_free (relative_uri); - -} - -static GList* -get_addressbook_names_from_server (char *source_url) -{ - char *key; - EGwConnection *cnc; - char *password; - GList *book_list; - int status; - const char *soap_port; - CamelURL *url; - gboolean remember; - char *failed_auth; - char *prompt; - char *uri; - const char *use_ssl; - const char *poa_address; - guint32 flags = E_PASSWORDS_REMEMBER_FOREVER; - - url = camel_url_new (source_url, NULL); - if (url == NULL) { - return NULL; - } - poa_address = camel_url_get_param (url, "poa"); - if (!poa_address || strlen (poa_address) ==0) - return NULL; - - 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"; - key = g_strdup_printf ("groupwise://%s@%s/", url->user, poa_address); - if (use_ssl) - uri = g_strdup_printf ("https://%s:%s/soap", poa_address, soap_port); - else - uri = g_strdup_printf ("http://%s:%s/soap", poa_address, soap_port); - - failed_auth = ""; - cnc = NULL; - do { - prompt = g_strdup_printf (_("%sEnter password for %s (user %s)"), - failed_auth, poa_address, url->user); - - password = e_passwords_ask_password (prompt, "Groupwise", key, prompt, - E_PASSWORDS_REMEMBER_FOREVER|E_PASSWORDS_SECRET, &remember, - NULL); - g_free (prompt); - - if (!password) - break; - cnc = e_gw_connection_new (uri, url->user, password); - failed_auth = _("Failed to authenticate.\n"); - flags |= E_PASSWORDS_REPROMPT; - } while (cnc == NULL); - - if (E_IS_GW_CONNECTION(cnc)) { - book_list = NULL; - status = e_gw_connection_get_address_book_list (cnc, &book_list); - if (status == E_GW_CONNECTION_STATUS_OK) - return book_list; - - - } - e_error_run (NULL, "mail:gw-accountsetup-error", poa_address, NULL); - return NULL; -} - - -static gboolean -add_addressbook_sources (EAccount *account) -{ - CamelURL *url; - ESourceList *list; - ESourceGroup *group; - ESource *source; - char *base_uri; - const char *soap_port; - GList *books_list, *temp_list; - GConfClient* client; - const char* use_ssl; - const char *poa_address; - - - url = camel_url_new (account->source->url, NULL); - if (url == NULL) { - return FALSE; - } - - poa_address = camel_url_get_param (url, "poa"); - if (!poa_address || strlen (poa_address) ==0) - return FALSE; - - 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"); - base_uri = g_strdup_printf ("groupwise://%s@%s", url->user, poa_address); - client = gconf_client_get_default (); - list = e_source_list_new_for_gconf (client, "/apps/evolution/addressbook/sources" ); - group = e_source_group_new (account->name, base_uri); - books_list = get_addressbook_names_from_server (account->source->url); - temp_list = books_list; - if (!temp_list) - return FALSE; - for (; temp_list != NULL; temp_list = g_list_next (temp_list)) { - const char *book_name = e_gw_container_get_name (E_GW_CONTAINER(temp_list->data)); - source = e_source_new (book_name, g_strconcat (";",book_name, NULL)); - e_source_set_property (source, "auth", "plain/password"); - 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))) - e_source_set_property (source, "completion", "true"); - e_source_set_property (source, "use_ssl", use_ssl); - e_source_group_add_source (group, source, -1); - g_object_unref (source); - g_object_unref (E_GW_CONTAINER(temp_list->data)); - - } - - g_list_free (books_list); - - - e_source_list_add_group (list, group, -1); - e_source_list_sync (list, NULL); - g_object_unref (group); - g_object_unref (list); - g_object_unref (client); - g_free (base_uri); - - return TRUE; -} - -static void -modify_addressbook_sources ( EAccount *account, GwAccountInfo *existing_account_info ) -{ - CamelURL *url; - ESourceList *list; - ESourceGroup *group; - GSList *groups; - gboolean found_group; - gboolean delete_group; - char *old_base_uri; - char *new_base_uri; - const char *soap_port; - const char *use_ssl; - GSList *sources; - ESource *source; - GConfClient *client; - const char *poa_address; - - - url = camel_url_new (existing_account_info->source_url, NULL); - if (url == NULL) { - return; - } - - poa_address = camel_url_get_param (url, "poa"); - if (!poa_address || strlen (poa_address) ==0) - return; - - old_base_uri = g_strdup_printf ("groupwise://%s@%s", url->user, poa_address); - camel_url_free (url); - - url = camel_url_new (account->source->url, NULL); - if (url == NULL) - return ; - poa_address = camel_url_get_param (url, "poa"); - if (!poa_address || strlen (poa_address) ==0) - return; - new_base_uri = g_strdup_printf ("groupwise://%s@%s", url->user, poa_address); - 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"); - - client = gconf_client_get_default (); - list = e_source_list_new_for_gconf (client, "/apps/evolution/addressbook/sources" ); - groups = e_source_list_peek_groups (list); - delete_group = FALSE; - if (strcmp (old_base_uri, new_base_uri) != 0) - delete_group = TRUE; - group = NULL; - found_group = FALSE; - for ( ; groups != NULL && !found_group; groups = g_slist_next (groups)) { - - group = E_SOURCE_GROUP (groups->data); - if ( strcmp ( e_source_group_peek_base_uri(group), old_base_uri) == 0 && strcmp (e_source_group_peek_name (group), existing_account_info->name) == 0) { - found_group = TRUE; - if (!delete_group) { - e_source_group_set_name (group, account->name); - sources = e_source_group_peek_sources (group); - for (; sources != NULL; sources = g_slist_next (sources)) { - source = E_SOURCE (sources->data); - e_source_set_property (source, "port", soap_port); - e_source_set_property (source, "use_ssl", use_ssl); - } - - e_source_list_sync (list, NULL); - } - - } - } - if (found_group && delete_group) { - e_source_list_remove_group (list, group); - e_source_list_sync (list, NULL); - g_object_unref (list); - list = NULL; - add_addressbook_sources (account); - } - g_free (old_base_uri); - if (list) - g_object_unref (list); - camel_url_free (url); - g_object_unref (client); - - -} - -static void -remove_addressbook_sources (GwAccountInfo *existing_account_info) -{ - ESourceList *list; - ESourceGroup *group; - GSList *groups; - gboolean found_group; - CamelURL *url; - char *base_uri; - const char *soap_port; - GConfClient *client; - const char *poa_address; - - url = camel_url_new (existing_account_info->source_url, NULL); - if (url == NULL) { - return; - } - - 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"; - base_uri = g_strdup_printf ("groupwise://%s@%s", url->user, poa_address); - client = gconf_client_get_default (); - list = e_source_list_new_for_gconf (client, "/apps/evolution/addressbook/sources" ); - groups = e_source_list_peek_groups (list); - - found_group = FALSE; - - for ( ; groups != NULL && !found_group; groups = g_slist_next (groups)) { - - group = E_SOURCE_GROUP (groups->data); - if ( strcmp ( e_source_group_peek_base_uri (group), base_uri) == 0 && strcmp (e_source_group_peek_name (group), existing_account_info->name) == 0) { - - e_source_list_remove_group (list, group); - e_source_list_sync (list, NULL); - found_group = TRUE; - - } - } - g_object_unref (list); - g_object_unref (client); - g_free (base_uri); - camel_url_free (url); - - -} - - - -static void -account_added (EAccountList *account_listener, EAccount *account) -{ - - GwAccountInfo *info; - gboolean status; - - if (!is_groupwise_account (account)) - return; - - info = g_new0 (GwAccountInfo, 1); - info->uid = g_strdup (account->uid); - info->name = g_strdup (account->name); - info->source_url = g_strdup (account->source->url); - status = add_addressbook_sources (account); - if (status) - add_calendar_tasks_sources (info); - groupwise_accounts = g_list_append (groupwise_accounts, info); - -} - -static void -account_removed (EAccountList *account_listener, EAccount *account) -{ - GwAccountInfo *info; - - if (!is_groupwise_account (account)) - return; - - info = lookup_account_info (account->uid); - if (info == NULL) { - return; - } - - remove_calendar_tasks_sources (info); - remove_addressbook_sources (info); - groupwise_accounts = g_list_remove (groupwise_accounts, info); - g_free (info->uid); - g_free (info->name); - g_free (info->source_url); - g_free (info); - - -} - - -static void -account_changed (EAccountList *account_listener, EAccount *account) -{ - gboolean is_gw_account; - CamelURL *old_url, *new_url; - const char *old_soap_port, *new_soap_port; - GwAccountInfo *existing_account_info; - const char *old_use_ssl, *new_use_ssl; - gboolean old_ssl, new_ssl; - const char *old_poa_address, *new_poa_address; - - is_gw_account = is_groupwise_account (account); - - existing_account_info = lookup_account_info (account->uid); - - if (existing_account_info == NULL && is_gw_account) { - - if (!account->enabled) - return; - - /* some account of other type is changed to Groupwise */ - account_added (account_listener, account); - - } else if ( existing_account_info != NULL && !is_gw_account) { - - /*Groupwise account is changed to some other type */ - remove_calendar_tasks_sources (existing_account_info); - remove_addressbook_sources (existing_account_info); - groupwise_accounts = g_list_remove (groupwise_accounts, existing_account_info); - g_free (existing_account_info->uid); - g_free (existing_account_info->name); - g_free (existing_account_info->source_url); - g_free (existing_account_info); - - } else if ( existing_account_info != NULL && is_gw_account ) { - - if (!account->enabled) { - account_removed (account_listener, account); - return; - } - old_ssl = new_ssl = FALSE; - /* some info of groupwise account is changed . update the sources with new info if required */ - old_url = camel_url_new (existing_account_info->source_url, NULL); - old_poa_address = camel_url_get_param (old_url, "poa"); - old_soap_port = camel_url_get_param (old_url, "soap_port"); - old_use_ssl = camel_url_get_param (old_url, "soap_ssl"); - if (old_use_ssl) - old_ssl = TRUE; - new_url = camel_url_new (account->source->url, NULL); - - new_poa_address = camel_url_get_param (new_url, "poa"); - if (!new_poa_address || strlen (new_poa_address) ==0) - return; - new_soap_port = camel_url_get_param (new_url, "soap_port"); - if (!new_soap_port || strlen (new_soap_port) == 0) - new_soap_port = "7181"; - - new_use_ssl = camel_url_get_param (new_url, "soap_ssl"); - if (new_use_ssl){ - new_use_ssl = "always"; - new_ssl = TRUE; - } - - if ((old_poa_address && strcmp (old_poa_address, new_poa_address)) - || (old_soap_port && strcmp (old_soap_port, new_soap_port)) - || strcmp (old_url->user, new_url->user) - || ( old_ssl ^ new_ssl)) { - - account_removed (account_listener, 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); - modify_addressbook_sources (account, existing_account_info); - - } - - g_free (existing_account_info->name); - g_free (existing_account_info->source_url); - existing_account_info->name = g_strdup (account->name); - existing_account_info->source_url = g_strdup (account->source->url); - camel_url_free (old_url); - camel_url_free (new_url); - } - - -} - - - -static void -camel_gw_listener_construct (CamelGwListener *config_listener) -{ - EIterator *iter; - EAccount *account; - GwAccountInfo *info ; - - config_listener->priv->account_list = e_account_list_new (config_listener->priv->gconf_client); - - for ( iter = e_list_get_iterator (E_LIST ( config_listener->priv->account_list) ) ; e_iterator_is_valid (iter); e_iterator_next (iter) ) { - - account = E_ACCOUNT (e_iterator_get (iter)); - if ( is_groupwise_account (account) && account->enabled) { - - info = g_new0 (GwAccountInfo, 1); - info->uid = g_strdup (account->uid); - info->name = g_strdup (account->name); - info->source_url = g_strdup (account->source->url); - groupwise_accounts = g_list_append (groupwise_accounts, info); - - } - - } - g_signal_connect (config_listener->priv->account_list, "account_added", G_CALLBACK (account_added), NULL); - g_signal_connect (config_listener->priv->account_list, "account_changed", G_CALLBACK (account_changed), NULL); - g_signal_connect (config_listener->priv->account_list, "account_removed", G_CALLBACK (account_removed), NULL); - - -} - -GType -camel_gw_listener_get_type (void) -{ - static GType camel_gw_listener_type = 0; - - if (!camel_gw_listener_type) { - static GTypeInfo info = { - sizeof (CamelGwListenerClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) camel_gw_listener_class_init, - NULL, NULL, - sizeof (CamelGwListener), - 0, - (GInstanceInitFunc) camel_gw_listener_init - }; - camel_gw_listener_type = g_type_register_static (PARENT_TYPE, "CamelGwListener", &info, 0); - } - - return camel_gw_listener_type; -} - -CamelGwListener* -camel_gw_listener_new () -{ - CamelGwListener *config_listener; - - config_listener = g_object_new (CAMEL_TYPE_GW_LISTENER, NULL); - config_listener->priv->gconf_client = gconf_client_get_default(); - - camel_gw_listener_construct (config_listener); - - return config_listener; - -} - - diff --git a/camel/providers/groupwise/camel-gw-listener.h b/camel/providers/groupwise/camel-gw-listener.h deleted file mode 100644 index c4079723f4..0000000000 --- a/camel/providers/groupwise/camel-gw-listener.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors : - * - * Sivaiah Nallagatla <snallagatla@novell.com> - * - * Copyright 2003, Novell, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_GW_LISTENER_H -#define CAMEL_GW_LISTENER_H - - -#include <libedataserver/e-account-list.h> -#include<libedataserver/e-source.h> -#include<libedataserver/e-source-list.h> -#include "camel-url.h" - -G_BEGIN_DECLS - -#define CAMEL_TYPE_GW_LISTENER (camel_gw_listener_get_type ()) -#define CAMEL_GW_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CAMEL_TYPE_GW_LISTENER, CamelGwListener)) -#define CAMEL_GW_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CAMEL_TYPE_GW_LISTENER, CamelGWListenerClass)) -#define CAMEL_IS_GWLISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CAMEL_TYPE_GW_LISTENER)) -#define CAMEL_IS_GW_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), CAMEL_TYPE_GW_LISTENER)) - -typedef struct _CamelGwListener CamelGwListener; -typedef struct _CamelGwListenerClass CamelGwListenerClass; -typedef struct _CamelGwListenerPrivate CamelGwListenerPrivate; -struct _CamelGwListener { - GObject parent; - - CamelGwListenerPrivate *priv; -}; - -struct _CamelGwListenerClass { - GObjectClass parent_class; - - -}; - -GType camel_gw_listener_get_type (void); -CamelGwListener *camel_gw_listener_new (void); - -G_END_DECLS - -#endif - diff --git a/camel/providers/groupwise/libcamelgroupwise.urls b/camel/providers/groupwise/libcamelgroupwise.urls deleted file mode 100644 index fb6242262a..0000000000 --- a/camel/providers/groupwise/libcamelgroupwise.urls +++ /dev/null @@ -1 +0,0 @@ -groupwise diff --git a/camel/providers/imap/.cvsignore b/camel/providers/imap/.cvsignore deleted file mode 100644 index 3fa8afaa38..0000000000 --- a/camel/providers/imap/.cvsignore +++ /dev/null @@ -1,11 +0,0 @@ -.deps -Makefile -Makefile.in -.libs -.deps -*.lo -*.la -*.bb -*.bbg -*.da -*.gcov diff --git a/camel/providers/imap/Makefile.am b/camel/providers/imap/Makefile.am deleted file mode 100644 index 7c18acfa7f..0000000000 --- a/camel/providers/imap/Makefile.am +++ /dev/null @@ -1,44 +0,0 @@ -## Process this file with automake to produce Makefile.in - -camel_provider_LTLIBRARIES = libcamelimap.la -camel_provider_DATA = libcamelimap.urls - -INCLUDES = -I.. \ - -I$(srcdir)/.. \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/e-util \ - -I$(top_srcdir) \ - $(CAMEL_CFLAGS) \ - $(GNOME_INCLUDEDIR) \ - $(GTK_INCLUDEDIR) \ - -DG_LOG_DOMAIN=\"camel-imap-provider\" - -libcamelimap_la_SOURCES = \ - camel-imap-command.c \ - camel-imap-folder.c \ - camel-imap-message-cache.c \ - camel-imap-provider.c \ - camel-imap-search.c \ - camel-imap-store.c \ - camel-imap-store-summary.c \ - camel-imap-summary.c \ - camel-imap-utils.c \ - camel-imap-wrapper.c - -noinst_HEADERS = \ - camel-imap-command.h \ - camel-imap-folder.h \ - camel-imap-message-cache.h \ - camel-imap-search.h \ - camel-imap-store.h \ - camel-imap-store-summary.h \ - camel-imap-summary.h \ - camel-imap-types.h \ - camel-imap-utils.h \ - camel-imap-wrapper.h \ - camel-imap-private.h - -libcamelimap_la_LDFLAGS = -avoid-version -module - -EXTRA_DIST = libcamelimap.urls diff --git a/camel/providers/imap/camel-imap-command.c b/camel/providers/imap/camel-imap-command.c deleted file mode 100644 index eeb3ecd302..0000000000 --- a/camel/providers/imap/camel-imap-command.c +++ /dev/null @@ -1,819 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-command.c: IMAP command sending/parsing routines */ - -/* - * Authors: - * Dan Winship <danw@ximian.com> - * Jeffrey Stedfast <fejj@ximian.com> - * - * Copyright 2000, 2001 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdarg.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include "camel-imap-command.h" -#include "camel-imap-utils.h" -#include "camel-imap-folder.h" -#include "camel-imap-store.h" -#include "camel-imap-store-summary.h" -#include "camel-imap-private.h" -#include <camel/camel-exception.h> -#include <camel/camel-private.h> -#include <camel/camel-utf8.h> -#include <camel/camel-session.h> -#include "camel-i18n.h" - -extern int camel_verbose_debug; - -static gboolean imap_command_start (CamelImapStore *store, CamelFolder *folder, - const char *cmd, CamelException *ex); -CamelImapResponse *imap_read_response (CamelImapStore *store, - CamelException *ex); -static char *imap_read_untagged (CamelImapStore *store, char *line, - CamelException *ex); -static char *imap_command_strdup_vprintf (CamelImapStore *store, - const char *fmt, va_list ap); -static char *imap_command_strdup_printf (CamelImapStore *store, - const char *fmt, ...); - -/** - * camel_imap_command: - * @store: the IMAP store - * @folder: The folder to perform the operation in (or %NULL if not - * relevant). - * @ex: a CamelException - * @fmt: a sort of printf-style format string, followed by arguments - * - * This function calls camel_imap_command_start() to send the - * command, then reads the complete response to it using - * camel_imap_command_response() and returns a CamelImapResponse - * structure. - * - * As a special case, if @fmt is %NULL, it will just select @folder - * and return the response from doing so. - * - * See camel_imap_command_start() for details on @fmt. - * - * On success, the store's connect_lock will be locked. It will be freed - * when you call camel_imap_response_free. (The lock is recursive, so - * callers can grab and release it themselves if they need to run - * multiple commands atomically.) - * - * Return value: %NULL if an error occurred (in which case @ex will - * be set). Otherwise, a CamelImapResponse describing the server's - * response, which the caller must free with camel_imap_response_free(). - **/ -CamelImapResponse * -camel_imap_command (CamelImapStore *store, CamelFolder *folder, - CamelException *ex, const char *fmt, ...) -{ - va_list ap; - char *cmd; - - CAMEL_SERVICE_LOCK (store, connect_lock); - - if (fmt) { - va_start (ap, fmt); - cmd = imap_command_strdup_vprintf (store, fmt, ap); - va_end (ap); - } else { - camel_object_ref(folder); - if (store->current_folder) - camel_object_unref(store->current_folder); - store->current_folder = folder; - cmd = imap_command_strdup_printf (store, "SELECT %F", folder->full_name); - } - - if (!imap_command_start (store, folder, cmd, ex)) { - g_free (cmd); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return NULL; - } - g_free (cmd); - - return imap_read_response (store, ex); -} - -/** - * camel_imap_command_start: - * @store: the IMAP store - * @folder: The folder to perform the operation in (or %NULL if not - * relevant). - * @ex: a CamelException - * @fmt: a sort of printf-style format string, followed by arguments - * - * This function makes sure that @folder (if non-%NULL) is the - * currently-selected folder on @store and then sends the IMAP command - * specified by @fmt and the following arguments. - * - * @fmt can include the following %-escapes ONLY: - * %s, %d, %%: as with printf - * %S: an IMAP "string" (quoted string or literal) - * %F: an IMAP folder name - * - * %S strings will be passed as literals if the server supports LITERAL+ - * and quoted strings otherwise. (%S does not support strings that - * contain newlines.) - * - * %F will have the imap store's namespace prepended and then be processed - * like %S. - * - * On success, the store's connect_lock will be locked. It will be - * freed when %CAMEL_IMAP_RESPONSE_TAGGED or %CAMEL_IMAP_RESPONSE_ERROR - * is returned from camel_imap_command_response(). (The lock is - * recursive, so callers can grab and release it themselves if they - * need to run multiple commands atomically.) - * - * Return value: %TRUE if the command was sent successfully, %FALSE if - * an error occurred (in which case @ex will be set). - **/ -gboolean -camel_imap_command_start (CamelImapStore *store, CamelFolder *folder, - CamelException *ex, const char *fmt, ...) -{ - va_list ap; - char *cmd; - gboolean ok; - - va_start (ap, fmt); - cmd = imap_command_strdup_vprintf (store, fmt, ap); - va_end (ap); - - CAMEL_SERVICE_LOCK (store, connect_lock); - ok = imap_command_start (store, folder, cmd, ex); - g_free (cmd); - - if (!ok) - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return ok; -} - -static gboolean -imap_command_start (CamelImapStore *store, CamelFolder *folder, - const char *cmd, CamelException *ex) -{ - ssize_t nwritten; - - /* Check for current folder */ - if (folder && folder != store->current_folder) { - CamelImapResponse *response; - CamelException internal_ex; - - response = camel_imap_command (store, folder, ex, NULL); - if (!response) - return FALSE; - camel_exception_init (&internal_ex); - camel_imap_folder_selected (folder, response, &internal_ex); - camel_imap_response_free (store, response); - if (camel_exception_is_set (&internal_ex)) { - camel_exception_xfer (ex, &internal_ex); - return FALSE; - } - } - - /* Send the command */ - if (camel_verbose_debug) { - const char *mask; - - if (!strncmp ("LOGIN \"", cmd, 7)) - mask = "LOGIN \"xxx\" xxx"; - else if (!strncmp ("LOGIN {", cmd, 7)) - mask = "LOGIN {N+}\r\nxxx {N+}\r\nxxx"; - else if (!strncmp ("LOGIN ", cmd, 6)) - mask = "LOGIN xxx xxx"; - else - mask = cmd; - - fprintf (stderr, "sending : %c%.5d %s\r\n", store->tag_prefix, store->command, mask); - } - - nwritten = camel_stream_printf (store->ostream, "%c%.5d %s\r\n", - store->tag_prefix, store->command++, cmd); - - if (nwritten == -1) { - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Operation cancelled")); - else - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - g_strerror (errno)); - - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); - return FALSE; - } - - return TRUE; -} - -/** - * camel_imap_command_continuation: - * @store: the IMAP store - * @cmd: buffer containing the response/request data - * @cmdlen: command length - * @ex: a CamelException - * - * This method is for sending continuing responses to the IMAP server - * after camel_imap_command() or camel_imap_command_response() returns - * a continuation response. - * - * This function assumes you have an exclusive lock on the imap stream. - * - * Return value: as for camel_imap_command(). On failure, the store's - * connect_lock will be released. - **/ -CamelImapResponse * -camel_imap_command_continuation (CamelImapStore *store, const char *cmd, - size_t cmdlen, CamelException *ex) -{ - if (!camel_imap_store_connected (store, ex)) - return NULL; - - if (camel_stream_write (store->ostream, cmd, cmdlen) == -1 || - camel_stream_write (store->ostream, "\r\n", 2) == -1) { - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Operation cancelled")); - else - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - g_strerror (errno)); - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return NULL; - } - - return imap_read_response (store, ex); -} - -/** - * camel_imap_command_response: - * @store: the IMAP store - * @response: a pointer to pass back the response data in - * @ex: a CamelException - * - * This reads a single tagged, untagged, or continuation response from - * @store into *@response. The caller must free the string when it is - * done with it. - * - * Return value: One of %CAMEL_IMAP_RESPONSE_CONTINUATION, - * %CAMEL_IMAP_RESPONSE_UNTAGGED, %CAMEL_IMAP_RESPONSE_TAGGED, or - * %CAMEL_IMAP_RESPONSE_ERROR. If either of the last two, @store's - * command lock will be unlocked. - **/ -CamelImapResponseType -camel_imap_command_response (CamelImapStore *store, char **response, - CamelException *ex) -{ - CamelImapResponseType type; - char *respbuf; - - if (camel_imap_store_readline (store, &respbuf, ex) < 0) { - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return CAMEL_IMAP_RESPONSE_ERROR; - } - - switch (*respbuf) { - case '*': - if (!strncasecmp (respbuf, "* BYE", 5)) { - /* Connection was lost, no more data to fetch */ - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Server unexpectedly disconnected: %s"), - _("Unknown error")); /* g_strerror (104)); FIXME after 1.0 is released */ - store->connected = FALSE; - g_free (respbuf); - respbuf = NULL; - type = CAMEL_IMAP_RESPONSE_ERROR; - break; - } - - /* Read the rest of the response. */ - type = CAMEL_IMAP_RESPONSE_UNTAGGED; - respbuf = imap_read_untagged (store, respbuf, ex); - if (!respbuf) - type = CAMEL_IMAP_RESPONSE_ERROR; - else if (!strncasecmp (respbuf, "* OK [ALERT]", 12)) { - char *msg; - - /* for imap ALERT codes, account user@host */ - msg = g_strdup_printf(_("Alert from IMAP server %s@%s:\n%s"), - ((CamelService *)store)->url->user, ((CamelService *)store)->url->host, respbuf+12); - camel_session_alert_user(((CamelService *)store)->session, CAMEL_SESSION_ALERT_WARNING, msg, FALSE); - g_free(msg); - } - - break; - case '+': - type = CAMEL_IMAP_RESPONSE_CONTINUATION; - break; - default: - type = CAMEL_IMAP_RESPONSE_TAGGED; - break; - } - *response = respbuf; - - if (type == CAMEL_IMAP_RESPONSE_ERROR || - type == CAMEL_IMAP_RESPONSE_TAGGED) - CAMEL_SERVICE_UNLOCK (store, connect_lock); - - return type; -} - -CamelImapResponse * -imap_read_response (CamelImapStore *store, CamelException *ex) -{ - CamelImapResponse *response; - CamelImapResponseType type; - char *respbuf, *p; - - /* Get another lock so that when we reach the tagged - * response and camel_imap_command_response unlocks, - * we're still locked. This lock is owned by response - * and gets unlocked when response is freed. - */ - CAMEL_SERVICE_LOCK (store, connect_lock); - - response = g_new0 (CamelImapResponse, 1); - if (store->current_folder && camel_disco_store_status (CAMEL_DISCO_STORE (store)) != CAMEL_DISCO_STORE_RESYNCING) { - response->folder = store->current_folder; - camel_object_ref (CAMEL_OBJECT (response->folder)); - } - - response->untagged = g_ptr_array_new (); - while ((type = camel_imap_command_response (store, &respbuf, ex)) - == CAMEL_IMAP_RESPONSE_UNTAGGED) - g_ptr_array_add (response->untagged, respbuf); - - if (type == CAMEL_IMAP_RESPONSE_ERROR) { - camel_imap_response_free_without_processing (store, response); - return NULL; - } - - response->status = respbuf; - - /* Check for OK or continuation response. */ - if (*respbuf == '+') - return response; - p = strchr (respbuf, ' '); - if (p && !strncasecmp (p, " OK", 3)) - return response; - - /* We should never get BAD, or anything else but +, OK, or NO - * for that matter. - */ - if (!p || strncasecmp (p, " NO", 3) != 0) { - g_warning ("Unexpected response from IMAP server: %s", - respbuf); - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Unexpected response from IMAP " - "server: %s"), respbuf); - camel_imap_response_free_without_processing (store, response); - return NULL; - } - - p += 3; - if (!*p++) - p = NULL; - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("IMAP command failed: %s"), - p ? p : _("Unknown error")); - camel_imap_response_free_without_processing (store, response); - return NULL; -} - -/* Given a line that is the start of an untagged response, read and - * return the complete response, which may include an arbitrary number - * of literals. - */ -static char * -imap_read_untagged (CamelImapStore *store, char *line, CamelException *ex) -{ - int fulllen, ldigits, nread, i; - unsigned int length; - GPtrArray *data; - GString *str; - char *end, *p, *s, *d; - - p = strrchr (line, '{'); - if (!p) - return line; - - data = g_ptr_array_new (); - fulllen = 0; - - while (1) { - str = g_string_new (line); - g_free (line); - fulllen += str->len; - g_ptr_array_add (data, str); - - p = strrchr (str->str, '{'); - if (!p) - break; - - length = strtoul (p + 1, &end, 10); - if (*end != '}' || *(end + 1) || end == p + 1 || length >= UINT_MAX - 2) - break; - ldigits = end - (p + 1); - - /* Read the literal */ - str = g_string_sized_new (length + 2); - str->str[0] = '\n'; - nread = camel_stream_read (store->istream, str->str + 1, length); - if (nread == -1) { - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Operation cancelled")); - else - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - g_strerror (errno)); - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); - g_string_free (str, TRUE); - goto lose; - } - if (nread < length) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Server response ended too soon.")); - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); - g_string_free (str, TRUE); - goto lose; - } - str->str[length + 1] = '\0'; - - /* Fix up the literal, turning CRLFs into LF. Also, if - * we find any embedded NULs, strip them. This is - * dubious, but: - * - The IMAP grammar says you can't have NULs here - * anyway, so this will not affect our behavior - * against any completely correct server. - * - WU-imapd 12.264 (at least) will cheerily pass - * NULs along if they are embedded in the message - */ - - s = d = str->str + 1; - end = str->str + 1 + length; - while (s < end) { - while (s < end && *s == '\0') { - s++; - length--; - } - if (*s == '\r' && *(s + 1) == '\n') { - s++; - length--; - } - *d++ = *s++; - } - *d = '\0'; - str->len = length + 1; - - /* p points to the "{" in the line that starts the - * literal. The length of the CR-less response must be - * less than or equal to the length of the response - * with CRs, therefore overwriting the old value with - * the new value cannot cause an overrun. However, we - * don't want it to be shorter either, because then the - * GString's length would be off... - */ - sprintf (p, "{%0*d}", ldigits, length); - - fulllen += str->len; - g_ptr_array_add (data, str); - - /* Read the next line. */ - if (camel_imap_store_readline (store, &line, ex) < 0) - goto lose; - } - - /* Now reassemble the data. */ - p = line = g_malloc (fulllen + 1); - for (i = 0; i < data->len; i++) { - str = data->pdata[i]; - memcpy (p, str->str, str->len); - p += str->len; - g_string_free (str, TRUE); - } - *p = '\0'; - g_ptr_array_free (data, TRUE); - return line; - - lose: - for (i = 0; i < data->len; i++) - g_string_free (data->pdata[i], TRUE); - g_ptr_array_free (data, TRUE); - return NULL; -} - - -/** - * camel_imap_response_free: - * @store: the CamelImapStore the response is from - * @response: a CamelImapResponse - * - * Frees all of the data in @response and processes any untagged - * EXPUNGE and EXISTS responses in it. Releases @store's connect_lock. - **/ -void -camel_imap_response_free (CamelImapStore *store, CamelImapResponse *response) -{ - int i, number, exists = 0; - GArray *expunged = NULL; - char *resp, *p; - - if (!response) - return; - - for (i = 0; i < response->untagged->len; i++) { - resp = response->untagged->pdata[i]; - - if (response->folder) { - /* Check if it's something we need to handle. */ - number = strtoul (resp + 2, &p, 10); - if (!g_ascii_strcasecmp (p, " EXISTS")) { - exists = number; - } else if (!strcasecmp (p, " EXPUNGE")) { - if (!expunged) { - expunged = g_array_new (FALSE, FALSE, - sizeof (int)); - } - g_array_append_val (expunged, number); - } - } - g_free (resp); - } - - g_ptr_array_free (response->untagged, TRUE); - g_free (response->status); - - if (response->folder) { - if (exists > 0 || expunged) { - /* Update the summary */ - camel_imap_folder_changed (response->folder, - exists, expunged, NULL); - if (expunged) - g_array_free (expunged, TRUE); - } - - camel_object_unref (CAMEL_OBJECT (response->folder)); - } - - g_free (response); - CAMEL_SERVICE_UNLOCK (store, connect_lock); -} - -/** - * camel_imap_response_free_without_processing: - * @store: the CamelImapStore the response is from. - * @response: a CamelImapResponse: - * - * Frees all of the data in @response without processing any untagged - * responses. Releases @store's command lock. - **/ -void -camel_imap_response_free_without_processing (CamelImapStore *store, - CamelImapResponse *response) -{ - if (!response) - return; - - if (response->folder) { - camel_object_unref (CAMEL_OBJECT (response->folder)); - response->folder = NULL; - } - camel_imap_response_free (store, response); -} - -/** - * camel_imap_response_extract: - * @store: the store the response came from - * @response: the response data returned from camel_imap_command - * @type: the response type to extract - * @ex: a CamelException - * - * This checks that @response contains a single untagged response of - * type @type and returns just that response data. If @response - * doesn't contain the right information, the function will set @ex - * and return %NULL. Either way, @response will be freed and the - * store's connect_lock released. - * - * Return value: the desired response string, which the caller must free. - **/ -char * -camel_imap_response_extract (CamelImapStore *store, - CamelImapResponse *response, - const char *type, - CamelException *ex) -{ - int len = strlen (type), i; - char *resp; - - len = strlen (type); - - for (i = 0; i < response->untagged->len; i++) { - resp = response->untagged->pdata[i]; - /* Skip "* ", and initial sequence number, if present */ - strtoul (resp + 2, &resp, 10); - if (*resp == ' ') - resp = (char *) imap_next_word (resp); - - if (!strncasecmp (resp, type, len)) - break; - } - - if (i < response->untagged->len) { - resp = response->untagged->pdata[i]; - g_ptr_array_remove_index (response->untagged, i); - } else { - resp = NULL; - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("IMAP server response did not contain " - "%s information"), type); - } - - camel_imap_response_free (store, response); - return resp; -} - -/** - * camel_imap_response_extract_continuation: - * @store: the store the response came from - * @response: the response data returned from camel_imap_command - * @ex: a CamelException - * - * This checks that @response contains a continuation response, and - * returns just that data. If @response doesn't contain a continuation - * response, the function will set @ex, release @store's connect_lock, - * and return %NULL. Either way, @response will be freed. - * - * Return value: the desired response string, which the caller must free. - **/ -char * -camel_imap_response_extract_continuation (CamelImapStore *store, - CamelImapResponse *response, - CamelException *ex) -{ - char *status; - - if (response->status && *response->status == '+') { - status = response->status; - response->status = NULL; - camel_imap_response_free (store, response); - return status; - } - - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Unexpected OK response from IMAP server: %s"), - response->status); - camel_imap_response_free (store, response); - return NULL; -} - -static char * -imap_command_strdup_vprintf (CamelImapStore *store, const char *fmt, - va_list ap) -{ - GPtrArray *args; - const char *p, *start; - char *out, *outptr, *string; - int num, len, i, arglen; - - args = g_ptr_array_new (); - - /* Determine the length of the data */ - len = strlen (fmt); - p = start = fmt; - while (*p) { - p = strchr (start, '%'); - if (!p) - break; - - switch (*++p) { - case 'd': - num = va_arg (ap, int); - g_ptr_array_add (args, GINT_TO_POINTER (num)); - start = p + 1; - len += 10; - break; - case 's': - string = va_arg (ap, char *); - g_ptr_array_add (args, string); - start = p + 1; - len += strlen (string); - break; - case 'S': - case 'F': - string = va_arg (ap, char *); - if (*p == 'F') { - /* NB: this is freed during output */ - char *s = camel_imap_store_summary_full_from_path(store->summary, string); - string = s?s:camel_utf8_utf7(string); - } - arglen = strlen (string); - g_ptr_array_add (args, string); - if (imap_is_atom (string)) { - len += arglen; - } else { - if (store->capabilities & IMAP_CAPABILITY_LITERALPLUS) - len += arglen + 15; - else - len += arglen * 2; - } - start = p + 1; - break; - case '%': - start = p; - break; - default: - g_warning ("camel-imap-command is not printf. I don't " - "know what '%%%c' means.", *p); - start = *p ? p + 1 : p; - break; - } - } - - /* Now write out the string */ - outptr = out = g_malloc (len + 1); - p = start = fmt; - i = 0; - while (*p) { - p = strchr (start, '%'); - if (!p) { - strcpy (outptr, start); - break; - } else { - strncpy (outptr, start, p - start); - outptr += p - start; - } - - switch (*++p) { - case 'd': - num = GPOINTER_TO_INT (args->pdata[i++]); - outptr += sprintf (outptr, "%d", num); - break; - - case 's': - string = args->pdata[i++]; - outptr += sprintf (outptr, "%s", string); - break; - case 'S': - case 'F': - string = args->pdata[i++]; - if (imap_is_atom (string)) { - outptr += sprintf (outptr, "%s", string); - } else { - if (store->capabilities & IMAP_CAPABILITY_LITERALPLUS) { - outptr += sprintf (outptr, "{%d+}\r\n%s", strlen (string), string); - } else { - char *quoted = imap_quote_string (string); - - outptr += sprintf (outptr, "%s", quoted); - g_free (quoted); - } - } - - if (*p == 'F') - g_free (string); - break; - default: - *outptr++ = '%'; - *outptr++ = *p; - } - - start = *p ? p + 1 : p; - } - - return out; -} - -static char * -imap_command_strdup_printf (CamelImapStore *store, const char *fmt, ...) -{ - va_list ap; - char *result; - - va_start (ap, fmt); - result = imap_command_strdup_vprintf (store, fmt, ap); - va_end (ap); - - return result; -} diff --git a/camel/providers/imap/camel-imap-command.h b/camel/providers/imap/camel-imap-command.h deleted file mode 100644 index 3539ac63d2..0000000000 --- a/camel/providers/imap/camel-imap-command.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-command.h: IMAP command sending/parsing routines */ - -/* - * Authors: - * Dan Winship <danw@ximian.com> - * Jeffrey Stedfast <fejj@ximian.com> - * - * Copyright (C) 2000, 2001 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_IMAP_COMMAND_H -#define CAMEL_IMAP_COMMAND_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include <glib.h> -#include "camel-imap-types.h" - -typedef enum { - CAMEL_IMAP_RESPONSE_ERROR, - CAMEL_IMAP_RESPONSE_CONTINUATION, - CAMEL_IMAP_RESPONSE_UNTAGGED, - CAMEL_IMAP_RESPONSE_TAGGED -} CamelImapResponseType; - -struct _CamelImapResponse { - CamelFolder *folder; - GPtrArray *untagged; - char *status; -}; - -CamelImapResponse *camel_imap_command (CamelImapStore *store, - CamelFolder *folder, - CamelException *ex, - const char *fmt, ...); -CamelImapResponse *camel_imap_command_continuation (CamelImapStore *store, - const char *cmd, - size_t cmdlen, - CamelException *ex); - -void camel_imap_response_free (CamelImapStore *store, - CamelImapResponse *response); -void camel_imap_response_free_without_processing (CamelImapStore *store, - CamelImapResponse *response); -char *camel_imap_response_extract (CamelImapStore *store, - CamelImapResponse *response, - const char *type, - CamelException *ex); -char *camel_imap_response_extract_continuation (CamelImapStore *store, - CamelImapResponse *response, - CamelException *ex); - -gboolean camel_imap_command_start (CamelImapStore *store, - CamelFolder *folder, - CamelException *ex, - const char *fmt, ...); -CamelImapResponseType camel_imap_command_response (CamelImapStore *store, - char **respbuf, - CamelException *ex); - -#endif /* CAMEL_IMAP_COMMAND_H */ diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c deleted file mode 100644 index 6cdd96bcf7..0000000000 --- a/camel/providers/imap/camel-imap-folder.c +++ /dev/null @@ -1,2812 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-folder.c: class for an imap folder */ - -/* - * Authors: - * Dan Winship <danw@ximian.com> - * Jeffrey Stedfast <fejj@ximian.com> - * - * Copyright (C) 2000, 2001 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <sys/types.h> -#include <dirent.h> -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <fcntl.h> -#include <ctype.h> - -/*#include "libedataserver/e-path.h"*/ -#include "libedataserver/e-time-utils.h" - -#include "camel-imap-folder.h" -#include "camel-imap-command.h" -#include "camel-imap-message-cache.h" -#include "camel-imap-private.h" -#include "camel-imap-search.h" -#include "camel-imap-store.h" -#include "camel-imap-summary.h" -#include "camel-imap-utils.h" -#include "camel-imap-wrapper.h" -#include "camel-data-wrapper.h" -#include "camel-disco-diary.h" -#include "camel-exception.h" -#include "camel-mime-filter-crlf.h" -#include "camel-mime-filter-from.h" -#include "camel-mime-message.h" -#include "camel-mime-utils.h" -#include "camel-multipart.h" -#include "camel-multipart-signed.h" -#include "camel-multipart-encrypted.h" -#include "camel-operation.h" -#include "camel-session.h" -#include "camel-stream-buffer.h" -#include "camel-stream-filter.h" -#include "camel-stream-mem.h" -#include "camel-stream.h" -#include "camel-private.h" -#include "camel-string-utils.h" -#include "camel-file-utils.h" -#include "camel-debug.h" -#include "camel-i18n.h" - -#define d(x) - -/* set to -1 for infinite size (suggested max command-line length is - * 1000 octets (see rfc2683), so we should keep the uid-set length to - * something under that so that our command-lines don't exceed 1000 - * octets) */ -#define UID_SET_LIMIT (768) - - -#define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(o))) -static CamelDiscoFolderClass *disco_folder_class = NULL; - -static void imap_finalize (CamelObject *object); -static int imap_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args); - -static void imap_rescan (CamelFolder *folder, int exists, CamelException *ex); -static void imap_refresh_info (CamelFolder *folder, CamelException *ex); -static void imap_sync_online (CamelFolder *folder, CamelException *ex); -static void imap_sync_offline (CamelFolder *folder, CamelException *ex); -static void imap_expunge_uids_online (CamelFolder *folder, GPtrArray *uids, CamelException *ex); -static void imap_expunge_uids_offline (CamelFolder *folder, GPtrArray *uids, CamelException *ex); -static void imap_expunge_uids_resyncing (CamelFolder *folder, GPtrArray *uids, CamelException *ex); -static void imap_cache_message (CamelDiscoFolder *disco_folder, const char *uid, CamelException *ex); -static void imap_rename (CamelFolder *folder, const char *new); - -/* message manipulation */ -static CamelMimeMessage *imap_get_message (CamelFolder *folder, const gchar *uid, - CamelException *ex); -static void imap_append_online (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **appended_uid, - CamelException *ex); -static void imap_append_offline (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **appended_uid, - CamelException *ex); -static void imap_append_resyncing (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **appended_uid, - CamelException *ex); - -static void imap_transfer_online (CamelFolder *source, GPtrArray *uids, - CamelFolder *dest, GPtrArray **transferred_uids, - gboolean delete_originals, - CamelException *ex); -static void imap_transfer_offline (CamelFolder *source, GPtrArray *uids, - CamelFolder *dest, GPtrArray **transferred_uids, - gboolean delete_originals, - CamelException *ex); -static void imap_transfer_resyncing (CamelFolder *source, GPtrArray *uids, - CamelFolder *dest, GPtrArray **transferred_uids, - gboolean delete_originals, - CamelException *ex); - -/* searching */ -static GPtrArray *imap_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex); -static GPtrArray *imap_search_by_uids (CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex); -static void imap_search_free (CamelFolder *folder, GPtrArray *uids); - -static void imap_thaw (CamelFolder *folder); - -static CamelObjectClass *parent_class; - -static GData *parse_fetch_response (CamelImapFolder *imap_folder, char *msg_att); - -static void -camel_imap_folder_class_init (CamelImapFolderClass *camel_imap_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_imap_folder_class); - CamelDiscoFolderClass *camel_disco_folder_class = CAMEL_DISCO_FOLDER_CLASS (camel_imap_folder_class); - - disco_folder_class = CAMEL_DISCO_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_disco_folder_get_type ())); - - /* virtual method overload */ - ((CamelObjectClass *)camel_imap_folder_class)->getv = imap_getv; - - camel_folder_class->get_message = imap_get_message; - camel_folder_class->rename = imap_rename; - camel_folder_class->search_by_expression = imap_search_by_expression; - camel_folder_class->search_by_uids = imap_search_by_uids; - camel_folder_class->search_free = imap_search_free; - camel_folder_class->thaw = imap_thaw; - - camel_disco_folder_class->refresh_info_online = imap_refresh_info; - camel_disco_folder_class->sync_online = imap_sync_online; - camel_disco_folder_class->sync_offline = imap_sync_offline; - /* We don't sync flags at resync time: the online code will - * deal with it eventually. - */ - camel_disco_folder_class->sync_resyncing = imap_sync_offline; - camel_disco_folder_class->expunge_uids_online = imap_expunge_uids_online; - camel_disco_folder_class->expunge_uids_offline = imap_expunge_uids_offline; - camel_disco_folder_class->expunge_uids_resyncing = imap_expunge_uids_resyncing; - camel_disco_folder_class->append_online = imap_append_online; - camel_disco_folder_class->append_offline = imap_append_offline; - camel_disco_folder_class->append_resyncing = imap_append_resyncing; - camel_disco_folder_class->transfer_online = imap_transfer_online; - camel_disco_folder_class->transfer_offline = imap_transfer_offline; - camel_disco_folder_class->transfer_resyncing = imap_transfer_resyncing; - camel_disco_folder_class->cache_message = imap_cache_message; -} - -static void -camel_imap_folder_init (gpointer object, gpointer klass) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object); - CamelFolder *folder = CAMEL_FOLDER (object); - - folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_DELETED | - CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN; - - folder->folder_flags |= (CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | - CAMEL_FOLDER_HAS_SEARCH_CAPABILITY); - - imap_folder->priv = g_malloc0(sizeof(*imap_folder->priv)); -#ifdef ENABLE_THREADS - imap_folder->priv->search_lock = e_mutex_new(E_MUTEX_SIMPLE); - imap_folder->priv->cache_lock = e_mutex_new(E_MUTEX_REC); -#endif - - imap_folder->need_rescan = TRUE; -} - -CamelType -camel_imap_folder_get_type (void) -{ - static CamelType camel_imap_folder_type = CAMEL_INVALID_TYPE; - - if (camel_imap_folder_type == CAMEL_INVALID_TYPE) { - parent_class = camel_disco_folder_get_type(); - camel_imap_folder_type = - camel_type_register (parent_class, "CamelImapFolder", - sizeof (CamelImapFolder), - sizeof (CamelImapFolderClass), - (CamelObjectClassInitFunc) camel_imap_folder_class_init, - NULL, - (CamelObjectInitFunc) camel_imap_folder_init, - (CamelObjectFinalizeFunc) imap_finalize); - } - - return camel_imap_folder_type; -} - -CamelFolder * -camel_imap_folder_new (CamelStore *parent, const char *folder_name, - const char *folder_dir, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (parent); - CamelFolder *folder; - CamelImapFolder *imap_folder; - const char *short_name; - char *summary_file, *state_file; - - if (camel_mkdir (folder_dir, S_IRWXU) != 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create directory %s: %s"), - folder_dir, g_strerror (errno)); - return NULL; - } - - folder = CAMEL_FOLDER (camel_object_new (camel_imap_folder_get_type ())); - short_name = strrchr (folder_name, '/'); - if (short_name) - short_name++; - else - short_name = 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); - g_free (summary_file); - if (!folder->summary) { - camel_object_unref (CAMEL_OBJECT (folder)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not load summary for %s"), - folder_name); - return NULL; - } - - /* set/load persistent state */ - state_file = g_strdup_printf ("%s/cmeta", folder_dir); - camel_object_set(folder, NULL, CAMEL_OBJECT_STATE_FILE, state_file, NULL); - g_free(state_file); - camel_object_state_read(folder); - - imap_folder = CAMEL_IMAP_FOLDER (folder); - imap_folder->cache = camel_imap_message_cache_new (folder_dir, folder->summary, ex); - if (!imap_folder->cache) { - camel_object_unref (CAMEL_OBJECT (folder)); - return NULL; - } - - if (!g_ascii_strcasecmp (folder_name, "INBOX")) { - if ((imap_store->parameters & IMAP_PARAM_FILTER_INBOX)) - folder->folder_flags |= CAMEL_FOLDER_FILTER_RECENT; - if ((imap_store->parameters & IMAP_PARAM_FILTER_JUNK)) - folder->folder_flags |= CAMEL_FOLDER_FILTER_JUNK; - } else { - if ((imap_store->parameters & (IMAP_PARAM_FILTER_JUNK|IMAP_PARAM_FILTER_JUNK_INBOX)) == (IMAP_PARAM_FILTER_JUNK)) - folder->folder_flags |= CAMEL_FOLDER_FILTER_JUNK; - } - - imap_folder->search = camel_imap_search_new(folder_dir); - - return folder; -} - -/* Called with the store's connect_lock locked */ -void -camel_imap_folder_selected (CamelFolder *folder, CamelImapResponse *response, - CamelException *ex) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - CamelImapSummary *imap_summary = CAMEL_IMAP_SUMMARY (folder->summary); - unsigned long exists = 0, validity = 0, val, uid; - CamelMessageInfo *info; - guint32 perm_flags = 0; - GData *fetch_data; - int i, count; - char *resp; - - CAMEL_SERVICE_ASSERT_LOCKED (folder->parent_store, connect_lock); - - count = camel_folder_summary_count (folder->summary); - - for (i = 0; i < response->untagged->len; i++) { - resp = response->untagged->pdata[i] + 2; - if (!strncasecmp (resp, "FLAGS ", 6) && !perm_flags) { - resp += 6; - folder->permanent_flags = imap_parse_flag_list (&resp); - } else if (!strncasecmp (resp, "OK [PERMANENTFLAGS ", 19)) { - resp += 19; - - /* workaround for broken IMAP servers that send "* OK [PERMANENTFLAGS ()] Permanent flags" - * even tho they do allow storing flags. *Sigh* So many fucking broken IMAP servers out there. */ - if ((perm_flags = imap_parse_flag_list (&resp)) != 0) - folder->permanent_flags = perm_flags; - } else if (!strncasecmp (resp, "OK [UIDVALIDITY ", 16)) { - validity = strtoul (resp + 16, NULL, 10); - } else if (isdigit ((unsigned char)*resp)) { - unsigned long num = strtoul (resp, &resp, 10); - - if (!strncasecmp (resp, " EXISTS", 7)) { - exists = num; - /* Remove from the response so nothing - * else tries to interpret it. - */ - g_free (response->untagged->pdata[i]); - g_ptr_array_remove_index (response->untagged, i--); - } - } - } - - if (camel_strstrcase (response->status, "OK [READ-ONLY]")) - imap_folder->read_only = TRUE; - - if (camel_disco_store_status (CAMEL_DISCO_STORE (folder->parent_store)) == CAMEL_DISCO_STORE_RESYNCING) { - if (validity != imap_summary->validity) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_SUMMARY_INVALID, - _("Folder was destroyed and recreated on server.")); - return; - } - - /* FIXME: find missing UIDs ? */ - return; - } - - if (!imap_summary->validity) - imap_summary->validity = validity; - else if (validity != imap_summary->validity) { - imap_summary->validity = validity; - camel_folder_summary_clear (folder->summary); - CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock); - camel_imap_message_cache_clear (imap_folder->cache); - CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock); - imap_folder->need_rescan = FALSE; - camel_imap_folder_changed (folder, exists, NULL, ex); - return; - } - - /* If we've lost messages, we have to rescan everything */ - if (exists < count) - imap_folder->need_rescan = TRUE; - else if (count != 0 && !imap_folder->need_rescan) { - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - - /* Similarly, if the UID of the highest message we - * know about has changed, then that indicates that - * messages have been both added and removed, so we - * have to rescan to find the removed ones. (We pass - * NULL for the folder since we know that this folder - * is selected, and we don't want camel_imap_command - * to worry about it.) - */ - response = camel_imap_command (store, NULL, ex, "FETCH %d UID", count); - if (!response) - return; - uid = 0; - for (i = 0; i < response->untagged->len; i++) { - resp = response->untagged->pdata[i]; - val = strtoul (resp + 2, &resp, 10); - if (val == 0) - continue; - if (!g_ascii_strcasecmp (resp, " EXISTS")) { - /* Another one?? */ - exists = val; - continue; - } - if (uid != 0 || val != count || strncasecmp (resp, " FETCH (", 8) != 0) - continue; - - fetch_data = parse_fetch_response (imap_folder, resp + 7); - uid = strtoul (g_datalist_get_data (&fetch_data, "UID"), NULL, 10); - g_datalist_clear (&fetch_data); - } - camel_imap_response_free_without_processing (store, response); - - info = camel_folder_summary_index (folder->summary, count - 1); - val = strtoul (camel_message_info_uid (info), NULL, 10); - camel_message_info_free(info); - if (uid == 0 || uid != val) - imap_folder->need_rescan = TRUE; - } - - /* Now rescan if we need to */ - if (imap_folder->need_rescan) { - imap_rescan (folder, exists, ex); - return; - } - - /* If we don't need to rescan completely, but new messages - * have been added, find out about them. - */ - if (exists > count) - camel_imap_folder_changed (folder, exists, NULL, ex); - - /* And we're done. */ -} - -static void -imap_finalize (CamelObject *object) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object); - - if (imap_folder->search) - camel_object_unref (CAMEL_OBJECT (imap_folder->search)); - if (imap_folder->cache) - camel_object_unref (CAMEL_OBJECT (imap_folder->cache)); - -#ifdef ENABLE_THREADS - e_mutex_destroy(imap_folder->priv->search_lock); - e_mutex_destroy(imap_folder->priv->cache_lock); -#endif - g_free(imap_folder->priv); -} - -static int -imap_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args) -{ - CamelFolder *folder = (CamelFolder *)object; - int i, count=0; - guint32 tag; - - for (i=0;i<args->argc;i++) { - CamelArgGet *arg = &args->argv[i]; - - tag = arg->tag; - - switch (tag & CAMEL_ARG_TAG) { - /* CamelObject args */ - case CAMEL_OBJECT_ARG_DESCRIPTION: - if (folder->description == NULL) { - CamelURL *uri = ((CamelService *)folder->parent_store)->url; - - /* what if the full name doesn't incclude /'s? does it matter? */ - folder->description = g_strdup_printf("%s@%s:%s", uri->user, uri->host, folder->full_name); - } - *arg->ca_str = folder->description; - break; - default: - count++; - continue; - } - - arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE; - } - - if (count) - return ((CamelObjectClass *)parent_class)->getv(object, ex, args); - - return 0; -} - -static void -imap_rename (CamelFolder *folder, const char *new) -{ - CamelImapFolder *imap_folder = (CamelImapFolder *)folder; - CamelImapStore *imap_store = (CamelImapStore *)folder->parent_store; - char *folder_dir, *summary_path, *state_file; - char *folders; - - folders = g_strconcat (imap_store->storage_path, "/folders", NULL); - folder_dir = imap_path_to_physical (folders, new); - g_free (folders); - summary_path = g_strdup_printf("%s/summary", folder_dir); - - CAMEL_IMAP_FOLDER_LOCK (folder, cache_lock); - camel_imap_message_cache_set_path(imap_folder->cache, folder_dir); - CAMEL_IMAP_FOLDER_UNLOCK (folder, cache_lock); - - camel_folder_summary_set_filename(folder->summary, summary_path); - - state_file = g_strdup_printf ("%s/cmeta", folder_dir); - camel_object_set(folder, NULL, CAMEL_OBJECT_STATE_FILE, state_file, NULL); - g_free(state_file); - - g_free(summary_path); - g_free(folder_dir); - - ((CamelFolderClass *)disco_folder_class)->rename(folder, new); -} - -static void -imap_refresh_info (CamelFolder *folder, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - CamelImapResponse *response; - - if (camel_disco_store_status (CAMEL_DISCO_STORE (imap_store)) == CAMEL_DISCO_STORE_OFFLINE) - return; - - if (camel_folder_is_frozen (folder)) { - imap_folder->need_refresh = TRUE; - return; - } - - /* If the folder isn't selected, select it (which will force - * a rescan if one is needed). - * Also, if this is the INBOX, some servers (cryus) wont tell - * us with a NOOP of new messages, so force a reselect which - * should do it. */ - CAMEL_SERVICE_LOCK (imap_store, connect_lock); - if (imap_store->current_folder != folder - || g_ascii_strcasecmp(folder->full_name, "INBOX") == 0) { - response = camel_imap_command (imap_store, folder, ex, NULL); - if (response) { - camel_imap_folder_selected (folder, response, ex); - camel_imap_response_free (imap_store, response); - } - } else if (imap_folder->need_rescan) { - /* Otherwise, if we need a rescan, do it, and if not, just do - * a NOOP to give the server a chance to tell us about new - * messages. - */ - imap_rescan (folder, camel_folder_summary_count (folder->summary), ex); - } else { -#if 0 - /* on some servers need to CHECKpoint INBOX to recieve new messages?? */ - /* rfc2060 suggests this, but havent seen a server that requires it */ - if (g_ascii_strcasecmp(folder->full_name, "INBOX") == 0) { - response = camel_imap_command (imap_store, folder, ex, "CHECK"); - camel_imap_response_free (imap_store, response); - } -#endif - response = camel_imap_command (imap_store, folder, ex, "NOOP"); - camel_imap_response_free (imap_store, response); - } - - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); -} - -/* Called with the store's connect_lock locked */ -static void -imap_rescan (CamelFolder *folder, int exists, CamelException *ex) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - struct { - char *uid; - guint32 flags; - } *new; - char *resp; - CamelImapResponseType type; - int i, seq, summary_len, summary_got; - CamelMessageInfo *info; - CamelImapMessageInfo *iinfo; - GArray *removed; - gboolean ok; - CamelFolderChangeInfo *changes = NULL; - - CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock); - imap_folder->need_rescan = FALSE; - - summary_len = camel_folder_summary_count (folder->summary); - if (summary_len == 0) { - if (exists) - camel_imap_folder_changed (folder, exists, NULL, ex); - return; - } - - /* Check UIDs and flags of all messages we already know of. */ - camel_operation_start (NULL, _("Scanning for changed messages")); - info = camel_folder_summary_index (folder->summary, summary_len - 1); - ok = camel_imap_command_start (store, folder, ex, - "UID FETCH 1:%s (FLAGS)", - camel_message_info_uid (info)); - camel_message_info_free(info); - if (!ok) { - camel_operation_end (NULL); - return; - } - - new = g_malloc0 (summary_len * sizeof (*new)); - summary_got = 0; - while ((type = camel_imap_command_response (store, &resp, ex)) == CAMEL_IMAP_RESPONSE_UNTAGGED) { - GData *data; - char *uid; - guint32 flags; - - data = parse_fetch_response (imap_folder, resp); - g_free (resp); - if (!data) - continue; - - seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE")); - uid = g_datalist_get_data (&data, "UID"); - flags = GPOINTER_TO_UINT (g_datalist_get_data (&data, "FLAGS")); - - if (!uid || !seq || seq > summary_len) { - g_datalist_clear (&data); - continue; - } - - camel_operation_progress (NULL, ++summary_got * 100 / summary_len); - new[seq - 1].uid = g_strdup (uid); - new[seq - 1].flags = flags; - g_datalist_clear (&data); - } - - camel_operation_end (NULL); - if (type == CAMEL_IMAP_RESPONSE_ERROR) { - for (i = 0; i < summary_len && new[i].uid; i++) - g_free (new[i].uid); - g_free (new); - return; - } - - /* Free the final tagged response */ - g_free (resp); - - /* If we find a UID in the summary that doesn't correspond to - * the UID in the folder, then either: (a) it's a real UID, - * but the message was deleted on the server, or (b) it's a - * fake UID, and needs to be removed from the summary in order - * to sync up with the server. So either way, we remove it - * from the summary. - */ - removed = g_array_new (FALSE, FALSE, sizeof (int)); - for (i = 0; i < summary_len && new[i].uid; i++) { - info = camel_folder_summary_index (folder->summary, i); - iinfo = (CamelImapMessageInfo *)info; - - if (strcmp (camel_message_info_uid (info), new[i].uid) != 0) { - camel_message_info_free(info); - seq = i + 1; - g_array_append_val (removed, seq); - i--; - summary_len--; - continue; - } - - /* Update summary flags */ - if (new[i].flags != iinfo->server_flags) { - guint32 server_set, server_cleared; - - 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; - iinfo->server_flags = new[i].flags; - - if (changes == NULL) - changes = camel_folder_change_info_new(); - camel_folder_change_info_change_uid(changes, new[i].uid); - } - - camel_message_info_free(info); - g_free (new[i].uid); - } - - if (changes) { - camel_object_trigger_event(CAMEL_OBJECT (folder), "folder_changed", changes); - camel_folder_change_info_free(changes); - } - - seq = i + 1; - - /* Free remaining memory. */ - while (i < summary_len && new[i].uid) - g_free (new[i++].uid); - g_free (new); - - /* Remove any leftover cached summary messages. (Yes, we - * repeatedly add the same number to the removed array. - * See RFC2060 7.4.1) - */ - - for (i = seq; i <= summary_len; i++) - g_array_append_val (removed, seq); - - /* And finally update the summary. */ - camel_imap_folder_changed (folder, exists, removed, ex); - g_array_free (removed, TRUE); -} - -/* the max number of chars that an unsigned 32-bit int can be is 10 chars plus 1 for a possible : */ -#define UID_SET_FULL(setlen, maxlen) (maxlen > 0 ? setlen + 11 >= maxlen : FALSE) - -/* Find all messages in @folder with flags matching @flags and @mask. - * If no messages match, returns %NULL. Otherwise, returns an array of - * CamelMessageInfo and sets *@set to a message set corresponding the - * UIDs of the matched messages (up to @UID_SET_LIMIT bytes). The - * caller must free the infos, the array, and the set string. - */ -static GPtrArray * -get_matching (CamelFolder *folder, guint32 flags, guint32 mask, char **set) -{ - GPtrArray *matches; - CamelImapMessageInfo *info; - int i, max, range; - GString *gset; - - matches = g_ptr_array_new (); - gset = g_string_new (""); - 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); - if (!info) - continue; - if ((info->info.flags & mask) != flags) { - camel_message_info_free((CamelMessageInfo *)info); - if (range != -1) { - if (range != i - 1) { - info = matches->pdata[matches->len - 1]; - g_string_append_printf (gset, ":%s", camel_message_info_uid (info)); - } - range = -1; - } - continue; - } - - g_ptr_array_add (matches, info); - if (range != -1) - continue; - range = i; - if (gset->len) - g_string_append_c (gset, ','); - g_string_append_printf (gset, "%s", camel_message_info_uid (info)); - } - - if (range != -1 && range != max - 1) { - info = matches->pdata[matches->len - 1]; - g_string_append_printf (gset, ":%s", camel_message_info_uid (info)); - } - - if (matches->len) { - *set = gset->str; - g_string_free (gset, FALSE); - return matches; - } else { - *set = NULL; - g_string_free (gset, TRUE); - g_ptr_array_free (matches, TRUE); - return NULL; - } -} - -static void -imap_sync_offline (CamelFolder *folder, CamelException *ex) -{ - camel_folder_summary_save (folder->summary); -} - -static void -imap_sync_online (CamelFolder *folder, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response = NULL; - CamelImapMessageInfo *info; - CamelException local_ex; - GPtrArray *matches; - char *set, *flaglist; - gboolean unset; - int i, j, max; - - if (((CamelImapFolder *)folder)->read_only) { - imap_sync_offline (folder, ex); - return; - } - - camel_exception_init (&local_ex); - CAMEL_SERVICE_LOCK (store, connect_lock); - - /* Find a message with changed flags, find all of the other - * messages like it, sync them as a group, mark them as - * updated, and continue. - */ - max = camel_folder_summary_count (folder->summary); - for (i = 0; i < max; i++) { - if (!(info = (CamelImapMessageInfo *)camel_folder_summary_index (folder->summary, i))) - continue; - - if (!(info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) { - camel_message_info_free((CamelMessageInfo *)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); - - /* 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), - folder->permanent_flags | CAMEL_MESSAGE_FOLDER_FLAGGED, &set); - camel_message_info_free(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); - - /* Note: to `unset' flags, use -FLAGS.SILENT (<flag list>) */ - response = camel_imap_command (store, folder, &local_ex, - "UID STORE %s %sFLAGS.SILENT %s", - set, unset ? "-" : "", flaglist); - g_free (set); - g_free (flaglist); - - if (response) - camel_imap_response_free (store, response); - - 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; - } - camel_folder_summary_touch (folder->summary); - } - - for (j = 0; j < matches->len; j++) { - info = matches->pdata[j]; - camel_message_info_free(&info->info); - } - g_ptr_array_free (matches, TRUE); - - /* We unlock here so that other threads can have a chance to grab the connect_lock */ - CAMEL_SERVICE_UNLOCK (store, connect_lock); - - /* check for an exception */ - if (camel_exception_is_set (&local_ex)) { - camel_exception_xfer (ex, &local_ex); - return; - } - - /* Re-lock the connect_lock */ - CAMEL_SERVICE_LOCK (store, connect_lock); - } - - /* Save the summary */ - imap_sync_offline (folder, ex); - - CAMEL_SERVICE_UNLOCK (store, connect_lock); -} - -static int -uid_compar (const void *va, const void *vb) -{ - const char **sa = (const char **)va, **sb = (const char **)vb; - unsigned long a, b; - - a = strtoul (*sa, NULL, 10); - b = strtoul (*sb, NULL, 10); - if (a < b) - return -1; - else if (a == b) - return 0; - else - return 1; -} - -static void -imap_expunge_uids_offline (CamelFolder *folder, GPtrArray *uids, CamelException *ex) -{ - CamelFolderChangeInfo *changes; - int i; - - qsort (uids->pdata, uids->len, sizeof (void *), uid_compar); - - changes = camel_folder_change_info_new (); - - for (i = 0; i < uids->len; i++) { - camel_folder_summary_remove_uid (folder->summary, uids->pdata[i]); - camel_folder_change_info_remove_uid (changes, uids->pdata[i]); - /* We intentionally don't remove it from the cache because - * the cached data may be useful in replaying a COPY later. - */ - } - camel_folder_summary_save (folder->summary); - - camel_disco_diary_log (CAMEL_DISCO_STORE (folder->parent_store)->diary, - CAMEL_DISCO_DIARY_FOLDER_EXPUNGE, folder, uids); - - camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", changes); - camel_folder_change_info_free (changes); -} - -static void -imap_expunge_uids_online (CamelFolder *folder, GPtrArray *uids, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response; - int uid = 0; - char *set; - - CAMEL_SERVICE_LOCK (store, connect_lock); - - if ((store->capabilities & IMAP_CAPABILITY_UIDPLUS) == 0) { - ((CamelFolderClass *)CAMEL_OBJECT_GET_CLASS(folder))->sync(folder, 0, ex); - if (camel_exception_is_set(ex)) { - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return; - } - } - - qsort (uids->pdata, uids->len, sizeof (void *), uid_compar); - - while (uid < uids->len) { - set = imap_uid_array_to_set (folder->summary, uids, uid, UID_SET_LIMIT, &uid); - response = camel_imap_command (store, folder, ex, - "UID STORE %s +FLAGS.SILENT (\\Deleted)", - set); - if (response) - camel_imap_response_free (store, response); - if (camel_exception_is_set (ex)) { - CAMEL_SERVICE_UNLOCK (store, connect_lock); - g_free (set); - return; - } - - if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) { - response = camel_imap_command (store, folder, ex, - "UID EXPUNGE %s", set); - } else - response = camel_imap_command (store, folder, ex, "EXPUNGE"); - - if (response) - camel_imap_response_free (store, response); - } - - CAMEL_SERVICE_UNLOCK (store, connect_lock); -} - -static void -imap_expunge_uids_resyncing (CamelFolder *folder, GPtrArray *uids, CamelException *ex) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - GPtrArray *keep_uids, *mark_uids; - CamelImapResponse *response; - char *result; - - if (imap_folder->read_only) - return; - - if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) { - imap_expunge_uids_online (folder, uids, ex); - return; - } - - /* If we don't have UID EXPUNGE we need to avoid expunging any - * of the wrong messages. So we search for deleted messages, - * and any that aren't in our to-expunge list get temporarily - * marked un-deleted. - */ - - CAMEL_SERVICE_LOCK (store, connect_lock); - - ((CamelFolderClass *)CAMEL_OBJECT_GET_CLASS(folder))->sync(folder, 0, ex); - if (camel_exception_is_set(ex)) { - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return; - } - - response = camel_imap_command (store, folder, ex, "UID SEARCH DELETED"); - if (!response) { - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return; - } - result = camel_imap_response_extract (store, response, "SEARCH", ex); - if (!result) { - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return; - } - - if (result[8] == ' ') { - char *uid, *lasts = NULL; - unsigned long euid, kuid; - int ei, ki; - - keep_uids = g_ptr_array_new (); - mark_uids = g_ptr_array_new (); - - /* Parse SEARCH response */ - for (uid = strtok_r (result + 9, " ", &lasts); uid; uid = strtok_r (NULL, " ", &lasts)) - g_ptr_array_add (keep_uids, uid); - qsort (keep_uids->pdata, keep_uids->len, - sizeof (void *), uid_compar); - - /* Fill in "mark_uids", empty out "keep_uids" as needed */ - for (ei = ki = 0; ei < uids->len; ei++) { - euid = strtoul (uids->pdata[ei], NULL, 10); - - for (kuid = 0; ki < keep_uids->len; ki++) { - kuid = strtoul (keep_uids->pdata[ki], NULL, 10); - - if (kuid >= euid) - break; - } - - if (euid == kuid) - g_ptr_array_remove_index (keep_uids, ki); - else - g_ptr_array_add (mark_uids, uids->pdata[ei]); - } - } else { - /* Empty SEARCH result, meaning nothing is marked deleted - * on server. - */ - - keep_uids = NULL; - mark_uids = uids; - } - - /* Unmark messages to be kept */ - - if (keep_uids) { - char *uidset; - int uid = 0; - - while (uid < keep_uids->len) { - uidset = imap_uid_array_to_set (folder->summary, keep_uids, uid, UID_SET_LIMIT, &uid); - - response = camel_imap_command (store, folder, ex, - "UID STORE %s -FLAGS.SILENT (\\Deleted)", - uidset); - - g_free (uidset); - - if (!response) { - g_ptr_array_free (keep_uids, TRUE); - g_ptr_array_free (mark_uids, TRUE); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return; - } - camel_imap_response_free (store, response); - } - } - - /* Mark any messages that still need to be marked */ - if (mark_uids) { - char *uidset; - int uid = 0; - - while (uid < mark_uids->len) { - uidset = imap_uid_array_to_set (folder->summary, mark_uids, uid, UID_SET_LIMIT, &uid); - - response = camel_imap_command (store, folder, ex, - "UID STORE %s +FLAGS.SILENT (\\Deleted)", - uidset); - - g_free (uidset); - - if (!response) { - g_ptr_array_free (keep_uids, TRUE); - g_ptr_array_free (mark_uids, TRUE); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return; - } - camel_imap_response_free (store, response); - } - - if (mark_uids != uids) - g_ptr_array_free (mark_uids, TRUE); - } - - /* Do the actual expunging */ - response = camel_imap_command (store, folder, ex, "EXPUNGE"); - if (response) - camel_imap_response_free (store, response); - - /* And fix the remaining messages if we mangled them */ - if (keep_uids) { - char *uidset; - int uid = 0; - - while (uid < keep_uids->len) { - uidset = imap_uid_array_to_set (folder->summary, keep_uids, uid, UID_SET_LIMIT, &uid); - - /* Don't pass ex if it's already been set */ - response = camel_imap_command (store, folder, - camel_exception_is_set (ex) ? NULL : ex, - "UID STORE %s +FLAGS.SILENT (\\Deleted)", - uidset); - - g_free (uidset); - if (response) - camel_imap_response_free (store, response); - } - - g_ptr_array_free (keep_uids, TRUE); - } - - /* now we can free this, now that we're done with keep_uids */ - g_free (result); - - CAMEL_SERVICE_UNLOCK (store, connect_lock); -} - -static gchar * -get_temp_uid (void) -{ - gchar *res; - - static int counter = 0; - G_LOCK_DEFINE_STATIC (lock); - - G_LOCK (lock); - res = g_strdup_printf ("tempuid-%lx-%d", - (unsigned long) time (NULL), - counter++); - G_UNLOCK (lock); - - return res; -} - -static void -imap_append_offline (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **appended_uid, - CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapMessageCache *cache = CAMEL_IMAP_FOLDER (folder)->cache; - CamelFolderChangeInfo *changes; - char *uid; - - uid = get_temp_uid (); - - camel_imap_summary_add_offline (folder->summary, uid, message, info); - CAMEL_IMAP_FOLDER_LOCK (folder, cache_lock); - camel_imap_message_cache_insert_wrapper (cache, uid, "", - CAMEL_DATA_WRAPPER (message), ex); - CAMEL_IMAP_FOLDER_UNLOCK (folder, cache_lock); - - changes = camel_folder_change_info_new (); - camel_folder_change_info_add_uid (changes, uid); - camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", - changes); - camel_folder_change_info_free (changes); - - camel_disco_diary_log (CAMEL_DISCO_STORE (imap_store)->diary, - CAMEL_DISCO_DIARY_FOLDER_APPEND, folder, uid); - if (appended_uid) - *appended_uid = uid; - else - g_free (uid); -} - -static CamelImapResponse * -do_append (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **uid, - CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response, *response2; - CamelStream *memstream; - CamelMimeFilter *crlf_filter; - CamelStreamFilter *streamfilter; - GByteArray *ba; - char *flagstr, *end; - guint32 flags; - - flags = camel_message_info_flags(info); - if (flags) - flagstr = imap_create_flag_list (flags); - else - flagstr = NULL; - - /* encode any 8bit parts so we avoid sending embedded nul-chars and such */ - camel_mime_message_encode_8bit_parts (message); - - /* FIXME: We could avoid this if we knew how big the message was. */ - memstream = camel_stream_mem_new (); - ba = g_byte_array_new (); - camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (memstream), ba); - - streamfilter = camel_stream_filter_new_with_stream (memstream); - crlf_filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, - CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); - camel_stream_filter_add (streamfilter, crlf_filter); - camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), - CAMEL_STREAM (streamfilter)); - camel_object_unref (CAMEL_OBJECT (streamfilter)); - camel_object_unref (CAMEL_OBJECT (crlf_filter)); - camel_object_unref (CAMEL_OBJECT (memstream)); - - response = camel_imap_command (store, NULL, ex, "APPEND %F%s%s {%d}", - folder->full_name, flagstr ? " " : "", - flagstr ? flagstr : "", ba->len); - g_free (flagstr); - - if (!response) { - g_byte_array_free (ba, TRUE); - return NULL; - } - - if (*response->status != '+') { - camel_imap_response_free (store, response); - g_byte_array_free (ba, TRUE); - return NULL; - } - - /* send the rest of our data - the mime message */ - response2 = camel_imap_command_continuation (store, ba->data, ba->len, ex); - g_byte_array_free (ba, TRUE); - - /* free it only after message is sent. This may cause more FETCHes. */ - camel_imap_response_free (store, response); - if (!response2) - return response2; - - if (store->capabilities & IMAP_CAPABILITY_UIDPLUS) { - *uid = camel_strstrcase (response2->status, "[APPENDUID "); - if (*uid) - *uid = strchr (*uid + 11, ' '); - if (*uid) { - *uid = g_strndup (*uid + 1, strcspn (*uid + 1, "]")); - /* Make sure it's a number */ - if (strtoul (*uid, &end, 10) == 0 || *end) { - g_free (*uid); - *uid = NULL; - } - } - } else - *uid = NULL; - - return response2; -} - -static void -imap_append_online (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **appended_uid, - CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response; - char *uid; - int count; - - count = camel_folder_summary_count (folder->summary); - response = do_append (folder, message, info, &uid, ex); - if (!response) - return; - - if (uid) { - /* Cache first, since freeing response may trigger a - * summary update that will want this information. - */ - CAMEL_IMAP_FOLDER_LOCK (folder, cache_lock); - camel_imap_message_cache_insert_wrapper ( - CAMEL_IMAP_FOLDER (folder)->cache, uid, - "", CAMEL_DATA_WRAPPER (message), ex); - CAMEL_IMAP_FOLDER_UNLOCK (folder, cache_lock); - if (appended_uid) - *appended_uid = uid; - else - g_free (uid); - } else if (appended_uid) - *appended_uid = NULL; - - camel_imap_response_free (store, response); - - /* Make sure a "folder_changed" is emitted. */ - CAMEL_SERVICE_LOCK (store, connect_lock); - if (store->current_folder != folder || - camel_folder_summary_count (folder->summary) == count) - imap_refresh_info (folder, ex); - CAMEL_SERVICE_UNLOCK (store, connect_lock); -} - -static void -imap_append_resyncing (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **appended_uid, - CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response; - char *uid; - - response = do_append (folder, message, info, &uid, ex); - if (!response) - return; - - if (uid) { - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - const char *olduid = camel_message_info_uid (info); - - CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock); - camel_imap_message_cache_copy (imap_folder->cache, olduid, - imap_folder->cache, uid, ex); - CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock); - - if (appended_uid) - *appended_uid = uid; - else - g_free (uid); - } else if (appended_uid) - *appended_uid = NULL; - - camel_imap_response_free (store, response); -} - - -static void -imap_transfer_offline (CamelFolder *source, GPtrArray *uids, - CamelFolder *dest, GPtrArray **transferred_uids, - gboolean delete_originals, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store); - CamelImapMessageCache *sc = CAMEL_IMAP_FOLDER (source)->cache; - CamelImapMessageCache *dc = CAMEL_IMAP_FOLDER (dest)->cache; - CamelFolderChangeInfo *changes; - CamelMimeMessage *message; - CamelMessageInfo *mi; - char *uid, *destuid; - int i; - - /* We grab the store's command lock first, and then grab the - * source and destination cache_locks. This way we can't - * deadlock in the case where we're simultaneously also trying - * to copy messages in the other direction from another thread. - */ - CAMEL_SERVICE_LOCK (store, connect_lock); - CAMEL_IMAP_FOLDER_LOCK (source, cache_lock); - CAMEL_IMAP_FOLDER_LOCK (dest, cache_lock); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - - if (transferred_uids) { - *transferred_uids = g_ptr_array_new (); - g_ptr_array_set_size (*transferred_uids, uids->len); - } - - changes = camel_folder_change_info_new (); - - for (i = 0; i < uids->len; i++) { - uid = uids->pdata[i]; - - destuid = get_temp_uid (); - - mi = camel_folder_summary_uid (source->summary, uid); - g_return_if_fail (mi != NULL); - - message = camel_folder_get_message (source, uid, NULL); - - if (message) { - camel_imap_summary_add_offline (dest->summary, destuid, message, mi); - camel_object_unref (CAMEL_OBJECT (message)); - } else - 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_change_info_add_uid (changes, destuid); - if (transferred_uids) - (*transferred_uids)->pdata[i] = destuid; - else - g_free (destuid); - - if (delete_originals) - camel_folder_delete_message (source, uid); - } - - CAMEL_IMAP_FOLDER_UNLOCK (dest, cache_lock); - CAMEL_IMAP_FOLDER_UNLOCK (source, cache_lock); - - camel_object_trigger_event (CAMEL_OBJECT (dest), "folder_changed", changes); - camel_folder_change_info_free (changes); - - camel_disco_diary_log (CAMEL_DISCO_STORE (store)->diary, - CAMEL_DISCO_DIARY_FOLDER_TRANSFER, - source, dest, uids, delete_originals); -} - -static void -handle_copyuid (CamelImapResponse *response, CamelFolder *source, - CamelFolder *destination) -{ - CamelImapMessageCache *scache = CAMEL_IMAP_FOLDER (source)->cache; - CamelImapMessageCache *dcache = CAMEL_IMAP_FOLDER (destination)->cache; - char *validity, *srcset, *destset; - GPtrArray *src, *dest; - int i; - - validity = camel_strstrcase (response->status, "[COPYUID "); - if (!validity) - return; - validity += 9; - if (strtoul (validity, NULL, 10) != - CAMEL_IMAP_SUMMARY (destination->summary)->validity) - return; - - srcset = strchr (validity, ' '); - if (!srcset++) - goto lose; - destset = strchr (srcset, ' '); - if (!destset++) - goto lose; - - src = imap_uid_set_to_array (source->summary, srcset); - dest = imap_uid_set_to_array (destination->summary, destset); - - if (src && dest && src->len == dest->len) { - /* We don't have to worry about deadlocking on the - * cache locks here, because we've got the store's - * command lock too, so no one else could be here. - */ - CAMEL_IMAP_FOLDER_LOCK (source, cache_lock); - CAMEL_IMAP_FOLDER_LOCK (destination, cache_lock); - for (i = 0; i < src->len; i++) { - camel_imap_message_cache_copy (scache, src->pdata[i], - dcache, dest->pdata[i], - NULL); - } - CAMEL_IMAP_FOLDER_UNLOCK (source, cache_lock); - CAMEL_IMAP_FOLDER_UNLOCK (destination, cache_lock); - - imap_uid_array_free (src); - imap_uid_array_free (dest); - return; - } - - imap_uid_array_free (src); - imap_uid_array_free (dest); - lose: - g_warning ("Bad COPYUID response from server"); -} - -static void -do_copy (CamelFolder *source, GPtrArray *uids, - CamelFolder *destination, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store); - CamelImapResponse *response; - char *uidset; - int uid = 0; - - while (uid < uids->len && !camel_exception_is_set (ex)) { - uidset = imap_uid_array_to_set (source->summary, uids, uid, UID_SET_LIMIT, &uid); - - response = camel_imap_command (store, source, ex, "UID COPY %s %F", - uidset, destination->full_name); - - g_free (uidset); - - if (response && (store->capabilities & IMAP_CAPABILITY_UIDPLUS)) - handle_copyuid (response, source, destination); - - camel_imap_response_free (store, response); - } -} - -static void -imap_transfer_online (CamelFolder *source, GPtrArray *uids, - CamelFolder *dest, GPtrArray **transferred_uids, - gboolean delete_originals, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store); - int count, i; - - /* Sync message flags if needed. */ - imap_sync_online (source, ex); - if (camel_exception_is_set (ex)) - return; - - count = camel_folder_summary_count (dest->summary); - - qsort (uids->pdata, uids->len, sizeof (void *), uid_compar); - - /* Now copy the messages */ - do_copy (source, uids, dest, ex); - if (camel_exception_is_set (ex)) - return; - - /* Make the destination notice its new messages */ - if (store->current_folder != dest || - camel_folder_summary_count (dest->summary) == count) - camel_folder_refresh_info (dest, ex); - - if (delete_originals) { - for (i = 0; i < uids->len; i++) - camel_folder_delete_message (source, uids->pdata[i]); - } - - /* FIXME */ - if (transferred_uids) - *transferred_uids = NULL; -} - -static void -imap_transfer_resyncing (CamelFolder *source, GPtrArray *uids, - CamelFolder *dest, GPtrArray **transferred_uids, - gboolean delete_originals, CamelException *ex) -{ - CamelDiscoDiary *diary = CAMEL_DISCO_STORE (source->parent_store)->diary; - GPtrArray *realuids; - int first, i; - const char *uid; - CamelMimeMessage *message; - CamelMessageInfo *info; - - qsort (uids->pdata, uids->len, sizeof (void *), uid_compar); - - /* This is trickier than append_resyncing, because some of - * the messages we are copying may have been copied or - * appended into @source while we were offline, in which case - * if we don't have UIDPLUS, we won't know their real UIDs, - * so we'll have to append them rather than copying. - */ - - realuids = g_ptr_array_new (); - - i = 0; - while (i < uids->len) { - /* Skip past real UIDs */ - for (first = i; i < uids->len; i++) { - uid = uids->pdata[i]; - - if (!isdigit ((unsigned char)*uid)) { - uid = camel_disco_diary_uidmap_lookup (diary, uid); - if (!uid) - break; - } - g_ptr_array_add (realuids, (char *)uid); - - if (delete_originals) - camel_folder_delete_message (source, uid); - } - - /* If we saw any real UIDs, do a COPY */ - if (i != first) { - do_copy (source, realuids, dest, ex); - g_ptr_array_set_size (realuids, 0); - if (i == uids->len || camel_exception_is_set (ex)) - break; - } - - /* Deal with fake UIDs */ - while (i < uids->len && - !isdigit (*(unsigned char *)(uids->pdata[i])) && - !camel_exception_is_set (ex)) { - uid = uids->pdata[i]; - message = camel_folder_get_message (source, uid, NULL); - if (!message) { - /* Message must have been expunged */ - continue; - } - info = camel_folder_get_message_info (source, uid); - g_return_if_fail (info != NULL); - - imap_append_online (dest, message, info, NULL, ex); - camel_folder_free_message_info (source, info); - camel_object_unref (CAMEL_OBJECT (message)); - if (delete_originals) - camel_folder_delete_message (source, uid); - i++; - } - } - - g_ptr_array_free (realuids, FALSE); - - /* FIXME */ - if (transferred_uids) - *transferred_uids = NULL; -} - -static GPtrArray * -imap_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - GPtrArray *matches; - - /* we could get around this by creating a new search object each time, - but i doubt its worth it since any long operation would lock the - command channel too */ - CAMEL_IMAP_FOLDER_LOCK(folder, search_lock); - - camel_folder_search_set_folder (imap_folder->search, folder); - matches = camel_folder_search_search(imap_folder->search, expression, NULL, ex); - - CAMEL_IMAP_FOLDER_UNLOCK(folder, search_lock); - - return matches; -} - -static GPtrArray * -imap_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER(folder); - GPtrArray *matches; - - if (uids->len == 0) - return g_ptr_array_new(); - - CAMEL_IMAP_FOLDER_LOCK(folder, search_lock); - - camel_folder_search_set_folder(imap_folder->search, folder); - matches = camel_folder_search_search(imap_folder->search, expression, uids, ex); - - CAMEL_IMAP_FOLDER_UNLOCK(folder, search_lock); - - return matches; -} - -static void -imap_search_free (CamelFolder *folder, GPtrArray *uids) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - - g_return_if_fail (imap_folder->search); - - CAMEL_IMAP_FOLDER_LOCK(folder, search_lock); - - camel_folder_search_free_result (imap_folder->search, uids); - - CAMEL_IMAP_FOLDER_UNLOCK(folder, search_lock); -} - -static CamelMimeMessage *get_message (CamelImapFolder *imap_folder, - const char *uid, - CamelMessageContentInfo *ci, - CamelException *ex); - -struct _part_spec_stack { - struct _part_spec_stack *parent; - int part; -}; - -static void -part_spec_push (struct _part_spec_stack **stack, int part) -{ - struct _part_spec_stack *node; - - node = g_new (struct _part_spec_stack, 1); - node->parent = *stack; - node->part = part; - - *stack = node; -} - -static int -part_spec_pop (struct _part_spec_stack **stack) -{ - struct _part_spec_stack *node; - int part; - - g_return_val_if_fail (*stack != NULL, 0); - - node = *stack; - *stack = node->parent; - - part = node->part; - g_free (node); - - return part; -} - -static char * -content_info_get_part_spec (CamelMessageContentInfo *ci) -{ - struct _part_spec_stack *stack = NULL; - CamelMessageContentInfo *node; - char *part_spec, *buf; - size_t len = 1; - int part; - - node = ci; - while (node->parent) { - CamelMessageContentInfo *child; - - /* FIXME: is this only supposed to apply if 'node' is a multipart? */ - if (node->parent->parent && camel_content_type_is (node->parent->type, "message", "*")) { - node = node->parent; - continue; - } - - child = node->parent->childs; - for (part = 1; child; part++) { - if (child == node) - break; - - child = child->next; - } - - part_spec_push (&stack, part); - - len += 2; - while ((part = part / 10)) - len++; - - node = node->parent; - } - - buf = part_spec = g_malloc (len); - part_spec[0] = '\0'; - - while (stack) { - part = part_spec_pop (&stack); - buf += sprintf (buf, "%d%s", part, stack ? "." : ""); - } - - return part_spec; -} - -/* Fetch the contents of the MIME part indicated by @ci, which is part - * of message @uid in @folder. - */ -static CamelDataWrapper * -get_content (CamelImapFolder *imap_folder, const char *uid, - CamelMimePart *part, CamelMessageContentInfo *ci, - int frommsg, - CamelException *ex) -{ - CamelDataWrapper *content = NULL; - CamelStream *stream; - char *part_spec; - - part_spec = content_info_get_part_spec (ci); - - d(printf("get content '%s' '%s' (frommsg = %d)\n", part_spec, camel_content_type_format(ci->type), frommsg)); - - /* There are three cases: multipart/signed, multipart, message/rfc822, and "other" */ - if (camel_content_type_is (ci->type, "multipart", "signed")) { - CamelMultipartSigned *body_mp; - char *spec; - int ret; - - /* Note: because we get the content parts uninterpreted anyway, we could potentially - just use the normalmultipart code, except that multipart/signed wont let you yet! */ - - body_mp = camel_multipart_signed_new (); - /* need to set this so it grabs the boundary and other info about the signed type */ - /* we assume that part->content_type is more accurate/full than ci->type */ - camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (body_mp), CAMEL_DATA_WRAPPER (part)->mime_type); - - spec = g_alloca(strlen(part_spec) + 6); - if (frommsg) - sprintf(spec, part_spec[0] ? "%s.TEXT" : "TEXT", part_spec); - else - strcpy(spec, part_spec); - g_free(part_spec); - - stream = camel_imap_folder_fetch_data (imap_folder, uid, spec, FALSE, ex); - if (stream) { - ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (body_mp), stream); - camel_object_unref (CAMEL_OBJECT (stream)); - if (ret == -1) { - camel_object_unref ((CamelObject *) body_mp); - return NULL; - } - } - - return (CamelDataWrapper *) body_mp; - } else if (camel_content_type_is (ci->type, "multipart", "*")) { - CamelMultipart *body_mp; - char *child_spec; - int speclen, num, isdigest; - - if (camel_content_type_is (ci->type, "multipart", "encrypted")) - body_mp = (CamelMultipart *) camel_multipart_encrypted_new (); - else - body_mp = camel_multipart_new (); - - /* need to set this so it grabs the boundary and other info about the multipart */ - /* we assume that part->content_type is more accurate/full than ci->type */ - camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (body_mp), CAMEL_DATA_WRAPPER (part)->mime_type); - isdigest = camel_content_type_is(((CamelDataWrapper *)part)->mime_type, "multipart", "digest"); - - speclen = strlen (part_spec); - child_spec = g_malloc (speclen + 17); /* dot + 10 + dot + MIME + nul */ - memcpy (child_spec, part_spec, speclen); - if (speclen > 0) - child_spec[speclen++] = '.'; - g_free (part_spec); - - ci = ci->childs; - num = 1; - while (ci) { - sprintf (child_spec + speclen, "%d.MIME", num++); - stream = camel_imap_folder_fetch_data (imap_folder, uid, child_spec, FALSE, ex); - if (stream) { - int ret; - - part = camel_mime_part_new (); - ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (part), stream); - camel_object_unref (CAMEL_OBJECT (stream)); - if (ret == -1) { - camel_object_unref (CAMEL_OBJECT (part)); - camel_object_unref (CAMEL_OBJECT (body_mp)); - g_free (child_spec); - return NULL; - } - - content = get_content (imap_folder, uid, part, ci, FALSE, ex); - } - - if (!stream || !content) { - camel_object_unref (CAMEL_OBJECT (body_mp)); - g_free (child_spec); - return NULL; - } - - if (camel_debug("imap:folder")) { - char *ct = camel_content_type_format(camel_mime_part_get_content_type((CamelMimePart *)part)); - char *ct2 = camel_content_type_format(ci->type); - - printf("Setting part content type to '%s' contentinfo type is '%s'\n", ct, ct2); - g_free(ct); - g_free(ct2); - } - - /* if we had no content-type header on a multipart/digest sub-part, then we need to - treat it as message/rfc822 instead */ - if (isdigest && camel_medium_get_header((CamelMedium *)part, "content-type") == NULL) { - CamelContentType *ct = camel_content_type_new("message", "rfc822"); - - camel_data_wrapper_set_mime_type_field(content, ct); - camel_content_type_unref(ct); - } else { - camel_data_wrapper_set_mime_type_field(content, camel_mime_part_get_content_type(part)); - } - - camel_medium_set_content_object (CAMEL_MEDIUM (part), content); - camel_object_unref(content); - - camel_multipart_add_part (body_mp, part); - camel_object_unref(part); - - ci = ci->next; - } - - g_free (child_spec); - - return (CamelDataWrapper *) body_mp; - } else if (camel_content_type_is (ci->type, "message", "rfc822")) { - content = (CamelDataWrapper *) get_message (imap_folder, uid, ci->childs, ex); - g_free (part_spec); - return content; - } else { - CamelTransferEncoding enc; - char *spec; - - spec = g_alloca(strlen(part_spec) + 6); - if (frommsg) - sprintf(spec, part_spec[0] ? "%s.TEXT" : "1.TEXT", part_spec); - else - strcpy(spec, part_spec[0]?part_spec:"1"); - - enc = ci->encoding?camel_transfer_encoding_from_string(ci->encoding):CAMEL_TRANSFER_ENCODING_DEFAULT; - content = camel_imap_wrapper_new (imap_folder, ci->type, enc, uid, spec, part); - g_free (part_spec); - return content; - } -} - -static CamelMimeMessage * -get_message (CamelImapFolder *imap_folder, const char *uid, - CamelMessageContentInfo *ci, - CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (CAMEL_FOLDER (imap_folder)->parent_store); - CamelDataWrapper *content; - CamelMimeMessage *msg; - CamelStream *stream; - char *section_text, *part_spec; - int ret; - - part_spec = content_info_get_part_spec(ci); - d(printf("get message '%s'\n", part_spec)); - section_text = g_strdup_printf ("%s%s%s", part_spec, *part_spec ? "." : "", - store->server_level >= IMAP_LEVEL_IMAP4REV1 ? "HEADER" : "0"); - - stream = camel_imap_folder_fetch_data (imap_folder, uid, section_text, FALSE, ex); - g_free (section_text); - g_free(part_spec); - if (!stream) - return NULL; - - msg = camel_mime_message_new (); - ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), stream); - camel_object_unref (CAMEL_OBJECT (stream)); - if (ret == -1) { - camel_object_unref (CAMEL_OBJECT (msg)); - return NULL; - } - - content = get_content (imap_folder, uid, CAMEL_MIME_PART (msg), ci, TRUE, ex); - if (!content) { - camel_object_unref (CAMEL_OBJECT (msg)); - return NULL; - } - - if (camel_debug("imap:folder")) { - char *ct = camel_content_type_format(camel_mime_part_get_content_type((CamelMimePart *)msg)); - char *ct2 = camel_content_type_format(ci->type); - - printf("Setting message content type to '%s' contentinfo type is '%s'\n", ct, ct2); - g_free(ct); - g_free(ct2); - } - - camel_data_wrapper_set_mime_type_field(content, camel_mime_part_get_content_type((CamelMimePart *)msg)); - camel_medium_set_content_object (CAMEL_MEDIUM (msg), content); - camel_object_unref (CAMEL_OBJECT (content)); - - return msg; -} - -#define IMAP_SMALL_BODY_SIZE 5120 - -static CamelMimeMessage * -get_message_simple (CamelImapFolder *imap_folder, const char *uid, - CamelStream *stream, CamelException *ex) -{ - CamelMimeMessage *msg; - int ret; - - if (!stream) { - stream = camel_imap_folder_fetch_data (imap_folder, uid, "", - FALSE, ex); - if (!stream) - return NULL; - } - - msg = camel_mime_message_new (); - ret = camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), - stream); - camel_object_unref (CAMEL_OBJECT (stream)); - if (ret == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Unable to retrieve message: %s"), - g_strerror (errno)); - camel_object_unref (CAMEL_OBJECT (msg)); - return NULL; - } - - return msg; -} - -static gboolean -content_info_incomplete (CamelMessageContentInfo *ci) -{ - if (!ci->type) - return TRUE; - - if (camel_content_type_is (ci->type, "multipart", "*") - || camel_content_type_is (ci->type, "message", "rfc822")) { - if (!ci->childs) - return TRUE; - for (ci = ci->childs;ci;ci=ci->next) - if (content_info_incomplete(ci)) - return TRUE; - } - - return FALSE; -} - -static CamelMimeMessage * -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; - CamelMimeMessage *msg = NULL; - CamelStream *stream = NULL; - int retry; - - mi = (CamelImapMessageInfo *)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")); - return NULL; - } - - /* If its cached in full, just get it as is, this is only a shortcut, - since we get stuff from the cache anyway. It affects a busted connection though. */ - if ( (stream = camel_imap_folder_fetch_data(imap_folder, uid, "", TRUE, NULL)) - && (msg = get_message_simple(imap_folder, uid, stream, ex))) - goto done; - - /* All this mess is so we silently retry a fetch if we fail with - service_unavailable, without an (equivalent) mess of gotos */ - retry = 0; - do { - retry++; - camel_exception_clear(ex); - - /* If we are online, make sure we're also connected */ - if (camel_disco_store_status((CamelDiscoStore *)store) == CAMEL_DISCO_STORE_ONLINE - && !camel_imap_store_connected(store, ex)) - goto fail; - - /* 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)) { - msg = get_message_simple (imap_folder, uid, NULL, ex); - } else { - if (content_info_incomplete (mi->info.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 - * an empty content struct.) - */ - CamelImapResponse *response; - GData *fetch_data = NULL; - char *body, *found_uid; - int i; - - if (camel_disco_store_status (CAMEL_DISCO_STORE (store)) == CAMEL_DISCO_STORE_OFFLINE) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("This message is not currently available")); - goto fail; - } - - response = camel_imap_command (store, folder, ex, "UID FETCH %s BODY", uid); - if (response) { - for (i = 0, body = NULL; i < response->untagged->len; i++) { - fetch_data = parse_fetch_response (imap_folder, response->untagged->pdata[i]); - if (fetch_data) { - found_uid = g_datalist_get_data (&fetch_data, "UID"); - body = g_datalist_get_data (&fetch_data, "BODY"); - if (found_uid && body && !strcmp (found_uid, uid)) - break; - g_datalist_clear (&fetch_data); - fetch_data = NULL; - body = NULL; - } - } - - if (body) - imap_parse_body ((const char **) &body, folder, mi->info.content); - - if (fetch_data) - g_datalist_clear (&fetch_data); - - camel_imap_response_free (store, response); - } - } - - if (camel_debug_start("imap:folder")) { - printf("Folder get message '%s' folder info ->\n", uid); - camel_message_info_dump((CamelMessageInfo *)mi); - camel_debug_end(); - } - - /* FETCH returned OK, but we didn't parse a BODY - * response. Courier will return invalid BODY - * responses for invalidly MIMEd messages, so - * fall back to fetching the entire thing and - * let the mailer's "bad MIME" code handle it. - */ - if (content_info_incomplete (mi->info.content)) - msg = get_message_simple (imap_folder, uid, NULL, ex); - else - msg = get_message (imap_folder, uid, mi->info.content, ex); - } - } while (msg == NULL - && retry < 2 - && camel_exception_get_id(ex) == CAMEL_EXCEPTION_SERVICE_UNAVAILABLE); - -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); - - return msg; -} - -static void -imap_cache_message (CamelDiscoFolder *disco_folder, const char *uid, - CamelException *ex) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (disco_folder); - CamelStream *stream; - - stream = camel_imap_folder_fetch_data (imap_folder, uid, "", FALSE, ex); - if (stream) - camel_object_unref (CAMEL_OBJECT (stream)); -} - -/* We pretend that a FLAGS or RFC822.SIZE response is always exactly - * 20 bytes long, and a BODY[HEADERS] response is always 2000 bytes - * long. Since we know how many of each kind of response we're - * expecting, we can find the total (pretend) amount of server traffic - * to expect and then count off the responses as we read them to update - * the progress bar. - */ -#define IMAP_PRETEND_SIZEOF_FLAGS 20 -#define IMAP_PRETEND_SIZEOF_SIZE 20 -#define IMAP_PRETEND_SIZEOF_HEADERS 2000 - -static char *tm_months[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -static gboolean -decode_time (const unsigned char **in, int *hour, int *min, int *sec) -{ - register const unsigned char *inptr; - int *val, colons = 0; - - *hour = *min = *sec = 0; - - val = hour; - for (inptr = *in; *inptr && !isspace ((int) *inptr); inptr++) { - if (*inptr == ':') { - colons++; - switch (colons) { - case 1: - val = min; - break; - case 2: - val = sec; - break; - default: - return FALSE; - } - } else if (!isdigit ((int) *inptr)) - return FALSE; - else - *val = (*val * 10) + (*inptr - '0'); - } - - *in = inptr; - - return TRUE; -} - -static time_t -decode_internaldate (const unsigned char *in) -{ - const unsigned char *inptr = in; - int hour, min, sec, n; - unsigned char *buf; - struct tm tm; - time_t date; - - memset ((void *) &tm, 0, sizeof (struct tm)); - - tm.tm_mday = strtoul (inptr, (char **) &buf, 10); - if (buf == inptr || *buf != '-') - return (time_t) -1; - - inptr = buf + 1; - if (inptr[3] != '-') - return (time_t) -1; - - for (n = 0; n < 12; n++) { - if (!strncasecmp (inptr, tm_months[n], 3)) - break; - } - - if (n >= 12) - return (time_t) -1; - - tm.tm_mon = n; - - inptr += 4; - - n = strtoul (inptr, (char **) &buf, 10); - if (buf == inptr || *buf != ' ') - return (time_t) -1; - - tm.tm_year = n - 1900; - - inptr = buf + 1; - if (!decode_time (&inptr, &hour, &min, &sec)) - return (time_t) -1; - - tm.tm_hour = hour; - tm.tm_min = min; - tm.tm_sec = sec; - - n = strtol (inptr, NULL, 10); - - date = e_mktime_utc (&tm); - - /* date is now GMT of the time we want, but not offset by the timezone ... */ - - /* this should convert the time to the GMT equiv time */ - date -= ((n / 100) * 60 * 60) + (n % 100) * 60; - - return date; -} - -static void -add_message_from_data (CamelFolder *folder, GPtrArray *messages, - int first, GData *data) -{ - CamelMimeMessage *msg; - CamelStream *stream; - CamelImapMessageInfo *mi; - const char *idate; - int seq; - - seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE")); - if (seq < first) - return; - stream = g_datalist_get_data (&data, "BODY_PART_STREAM"); - if (!stream) - return; - - if (seq - first >= messages->len) - g_ptr_array_set_size (messages, seq - first + 1); - - msg = camel_mime_message_new (); - if (camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), stream) == -1) { - camel_object_unref (CAMEL_OBJECT (msg)); - return; - } - - mi = (CamelImapMessageInfo *)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); - - if (mi->info.date_received == -1) - mi->info.date_received = mi->info.date_sent; - - messages->pdata[seq - first] = mi; -} - - -#define CAMEL_MESSAGE_INFO_HEADERS "DATE FROM TO CC SUBJECT REFERENCES IN-REPLY-TO MESSAGE-ID MIME-VERSION CONTENT-TYPE" - -/* FIXME: this needs to be kept in sync with camel-mime-utils.c's list - of mailing-list headers and so might be best if this were - auto-generated? */ -#define MAILING_LIST_HEADERS "X-MAILING-LIST X-LOOP LIST-ID LIST-POST MAILING-LIST ORIGINATOR X-LIST SENDER RETURN-PATH X-BEENTHERE" - -static void -imap_update_summary (CamelFolder *folder, int exists, - CamelFolderChangeInfo *changes, - CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - GPtrArray *fetch_data = NULL, *messages = NULL, *needheaders; - guint32 flags, uidval; - int i, seq, first, size, got; - CamelImapResponseType type; - const char *header_spec; - CamelImapMessageInfo *mi, *info; - CamelStream *stream; - char *uid, *resp; - GData *data; - - CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock); - if (store->server_level >= IMAP_LEVEL_IMAP4REV1) - header_spec = "HEADER.FIELDS.NOT (RECEIVED)"; - else - header_spec = "0"; - - /* Figure out if any of the new messages are already cached (which - * may be the case if we're re-syncing after disconnected operation). - * If so, get their UIDs, FLAGS, and SIZEs. If not, get all that - * and ask for the headers too at the same time. - */ - seq = camel_folder_summary_count (folder->summary); - first = seq + 1; - if (seq > 0) { - mi = (CamelImapMessageInfo *)camel_folder_summary_index (folder->summary, seq - 1); - uidval = strtoul(camel_message_info_uid (mi), NULL, 10); - camel_message_info_free(&mi->info); - } else - uidval = 0; - - size = (exists - seq) * (IMAP_PRETEND_SIZEOF_FLAGS + IMAP_PRETEND_SIZEOF_SIZE + IMAP_PRETEND_SIZEOF_HEADERS); - got = 0; - if (!camel_imap_command_start (store, folder, ex, - "UID FETCH %d:* (FLAGS RFC822.SIZE INTERNALDATE BODY.PEEK[%s])", - uidval + 1, header_spec)) - return; - camel_operation_start (NULL, _("Fetching summary information for new messages")); - - /* Parse the responses. We can't add a message to the summary - * until we've gotten its headers, and there's no guarantee - * the server will send the responses in a useful order... - */ - fetch_data = g_ptr_array_new (); - messages = g_ptr_array_new (); - while ((type = camel_imap_command_response (store, &resp, ex)) == - CAMEL_IMAP_RESPONSE_UNTAGGED) { - data = parse_fetch_response (imap_folder, resp); - g_free (resp); - if (!data) - continue; - - seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE")); - if (seq < first) { - g_datalist_clear (&data); - continue; - } - - if (g_datalist_get_data (&data, "FLAGS")) - got += IMAP_PRETEND_SIZEOF_FLAGS; - if (g_datalist_get_data (&data, "RFC822.SIZE")) - got += IMAP_PRETEND_SIZEOF_SIZE; - stream = g_datalist_get_data (&data, "BODY_PART_STREAM"); - if (stream) { - got += IMAP_PRETEND_SIZEOF_HEADERS; - - /* Use the stream now so we don't tie up many - * many fds if we're fetching many many messages. - */ - add_message_from_data (folder, messages, first, data); - g_datalist_set_data (&data, "BODY_PART_STREAM", NULL); - } - - camel_operation_progress (NULL, got * 100 / size); - g_ptr_array_add (fetch_data, data); - } - camel_operation_end (NULL); - - if (type == CAMEL_IMAP_RESPONSE_ERROR) - goto lose; - - /* Free the final tagged response */ - g_free (resp); - - /* Figure out which headers we still need to fetch. */ - needheaders = g_ptr_array_new (); - size = got = 0; - for (i = 0; i < fetch_data->len; i++) { - data = fetch_data->pdata[i]; - if (g_datalist_get_data (&data, "BODY_PART_LEN")) - continue; - - uid = g_datalist_get_data (&data, "UID"); - if (uid) { - g_ptr_array_add (needheaders, uid); - size += IMAP_PRETEND_SIZEOF_HEADERS; - } - } - - /* And fetch them */ - if (needheaders->len) { - char *uidset; - int uid = 0; - - qsort (needheaders->pdata, needheaders->len, - sizeof (void *), uid_compar); - - camel_operation_start (NULL, _("Fetching summary information for new messages")); - - while (uid < needheaders->len) { - uidset = imap_uid_array_to_set (folder->summary, needheaders, uid, UID_SET_LIMIT, &uid); - if (!camel_imap_command_start (store, folder, ex, - "UID FETCH %s BODY.PEEK[%s]", - uidset, header_spec)) { - g_ptr_array_free (needheaders, TRUE); - camel_operation_end (NULL); - g_free (uidset); - goto lose; - } - g_free (uidset); - - while ((type = camel_imap_command_response (store, &resp, ex)) - == CAMEL_IMAP_RESPONSE_UNTAGGED) { - data = parse_fetch_response (imap_folder, resp); - g_free (resp); - if (!data) - continue; - - stream = g_datalist_get_data (&data, "BODY_PART_STREAM"); - if (stream) { - add_message_from_data (folder, messages, first, data); - got += IMAP_PRETEND_SIZEOF_HEADERS; - camel_operation_progress (NULL, got * 100 / size); - } - g_datalist_clear (&data); - } - - if (type == CAMEL_IMAP_RESPONSE_ERROR) { - g_ptr_array_free (needheaders, TRUE); - camel_operation_end (NULL); - goto lose; - } - } - - g_ptr_array_free (needheaders, TRUE); - camel_operation_end (NULL); - } - - /* Now finish up summary entries (fix UIDs, set flags and size) */ - for (i = 0; i < fetch_data->len; i++) { - data = fetch_data->pdata[i]; - - seq = GPOINTER_TO_INT (g_datalist_get_data (&data, "SEQUENCE")); - if (seq >= first + messages->len) { - g_datalist_clear (&data); - continue; - } - - mi = messages->pdata[seq - first]; - if (mi == NULL) { - CamelMessageInfo *pmi = NULL; - int j; - - /* This is a kludge around a bug in Exchange - * 5.5 that sometimes claims multiple messages - * have the same UID. See bug #17694 for - * details. The "solution" is to create a fake - * message-info with the same details as the - * previously valid message. Yes, the user - * will have a clone in his/her message-list, - * but at least we don't crash. - */ - - /* find the previous valid message info */ - for (j = seq - first - 1; j >= 0; j--) { - pmi = messages->pdata[j]; - if (pmi != NULL) - break; - } - - if (pmi == NULL) { - /* Server response is *really* fucked up, - I guess we just pretend it never happened? */ - continue; - } - - mi = (CamelImapMessageInfo *)camel_message_info_clone(pmi); - } - - uid = g_datalist_get_data (&data, "UID"); - if (uid) - mi->info.uid = 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; - } - size = GPOINTER_TO_INT (g_datalist_get_data (&data, "RFC822.SIZE")); - if (size) - mi->info.size = size; - - g_datalist_clear (&data); - } - g_ptr_array_free (fetch_data, TRUE); - - /* And add the entries to the summary, etc. */ - for (i = 0; i < messages->len; i++) { - mi = messages->pdata[i]; - if (!mi) { - g_warning ("No information for message %d", i + first); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Incomplete server response: no information provided for message %d"), - i + first); - break; - } - uid = (char *)camel_message_info_uid(mi); - if (uid[0] == 0) { - g_warning("Server provided no uid: message %d", i + first); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Incomplete server response: no UID provided for message %d"), - i + first); - break; - } - info = (CamelImapMessageInfo *)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) - break; - } - - g_warning("Message already present? %s", camel_message_info_uid(mi)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Unexpected server response: Identical UIDs provided for messages %d and %d"), - seq + 1, i + first); - - camel_message_info_free(&info->info); - break; - } - - camel_folder_summary_add (folder->summary, (CamelMessageInfo *)mi); - camel_folder_change_info_add_uid (changes, camel_message_info_uid (mi)); - - if ((mi->info.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); - } - - g_ptr_array_free (messages, TRUE); - - return; - - lose: - if (fetch_data) { - for (i = 0; i < fetch_data->len; i++) { - data = fetch_data->pdata[i]; - g_datalist_clear (&data); - } - g_ptr_array_free (fetch_data, TRUE); - } - if (messages) { - for (i = 0; i < messages->len; i++) { - if (messages->pdata[i]) - camel_message_info_free(messages->pdata[i]); - } - g_ptr_array_free (messages, TRUE); - } -} - -/* Called with the store's connect_lock locked */ -void -camel_imap_folder_changed (CamelFolder *folder, int exists, - GArray *expunged, CamelException *ex) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - CamelFolderChangeInfo *changes; - CamelMessageInfo *info; - int len; - - CAMEL_SERVICE_ASSERT_LOCKED (folder->parent_store, connect_lock); - - changes = camel_folder_change_info_new (); - if (expunged) { - int i, id; - - for (i = 0; i < expunged->len; i++) { - id = g_array_index (expunged, int, i); - info = camel_folder_summary_index (folder->summary, id - 1); - if (info == NULL) { - /* FIXME: danw: does this mean that the summary is corrupt? */ - /* I guess a message that we never retrieved got expunged? */ - continue; - } - - camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info)); - CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock); - 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); - } - } - - len = camel_folder_summary_count (folder->summary); - if (exists > len) - imap_update_summary (folder, exists, changes, ex); - - if (camel_folder_change_info_changed (changes)) - camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", changes); - - camel_folder_change_info_free (changes); - camel_folder_summary_save (folder->summary); -} - -static void -imap_thaw (CamelFolder *folder) -{ - CamelImapFolder *imap_folder; - - CAMEL_FOLDER_CLASS (disco_folder_class)->thaw (folder); - if (camel_folder_is_frozen (folder)) - return; - - imap_folder = CAMEL_IMAP_FOLDER (folder); - if (imap_folder->need_refresh) { - imap_folder->need_refresh = FALSE; - imap_refresh_info (folder, NULL); - } -} - - -CamelStream * -camel_imap_folder_fetch_data (CamelImapFolder *imap_folder, const char *uid, - const char *section_text, gboolean cache_only, - CamelException *ex) -{ - CamelFolder *folder = CAMEL_FOLDER (imap_folder); - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelImapResponse *response; - CamelStream *stream; - GData *fetch_data; - char *found_uid; - int i; - - /* EXPUNGE responses have to modify the cache, which means - * they have to grab the cache_lock while holding the - * connect_lock. So we grab the connect_lock now, in case - * we're going to need it below, since we can't grab it - * after the cache_lock. - */ - CAMEL_SERVICE_LOCK (store, connect_lock); - - CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock); - stream = camel_imap_message_cache_get (imap_folder->cache, uid, section_text, ex); - if (!stream && (!strcmp (section_text, "HEADER") || !strcmp (section_text, "0"))) { - camel_exception_clear (ex); - stream = camel_imap_message_cache_get (imap_folder->cache, uid, "", ex); - } - - if (stream || cache_only) { - CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return stream; - } - - if (camel_disco_store_status (CAMEL_DISCO_STORE (store)) == CAMEL_DISCO_STORE_OFFLINE) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("This message is not currently available")); - CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return NULL; - } - - camel_exception_clear (ex); - if (store->server_level < IMAP_LEVEL_IMAP4REV1 && !*section_text) { - response = camel_imap_command (store, folder, ex, - "UID FETCH %s RFC822.PEEK", - uid); - } else { - response = camel_imap_command (store, folder, ex, - "UID FETCH %s BODY.PEEK[%s]", - uid, section_text); - } - /* We won't need the connect_lock again after this. */ - CAMEL_SERVICE_UNLOCK (store, connect_lock); - - if (!response) { - CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock); - return NULL; - } - - for (i = 0; i < response->untagged->len; i++) { - fetch_data = parse_fetch_response (imap_folder, response->untagged->pdata[i]); - found_uid = g_datalist_get_data (&fetch_data, "UID"); - stream = g_datalist_get_data (&fetch_data, "BODY_PART_STREAM"); - if (found_uid && stream && !strcmp (uid, found_uid)) - break; - - g_datalist_clear (&fetch_data); - stream = NULL; - } - camel_imap_response_free (store, response); - CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock); - if (!stream) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not find message body in FETCH response.")); - } else { - camel_object_ref (CAMEL_OBJECT (stream)); - g_datalist_clear (&fetch_data); - } - - return stream; -} - -static GData * -parse_fetch_response (CamelImapFolder *imap_folder, char *response) -{ - GData *data = NULL; - char *start, *part_spec = NULL, *body = NULL, *uid = NULL, *idate = NULL; - gboolean cache_header = TRUE, header = FALSE; - size_t body_len = 0; - - if (*response != '(') { - long seq; - - if (*response != '*' || *(response + 1) != ' ') - return NULL; - seq = strtol (response + 2, &response, 10); - if (seq == 0) - return NULL; - if (strncasecmp (response, " FETCH (", 8) != 0) - return NULL; - response += 7; - - g_datalist_set_data (&data, "SEQUENCE", GINT_TO_POINTER (seq)); - } - - do { - /* Skip the initial '(' or the ' ' between elements */ - response++; - - if (!strncasecmp (response, "FLAGS ", 6)) { - guint32 flags; - - response += 6; - /* FIXME user flags */ - flags = imap_parse_flag_list (&response); - - g_datalist_set_data (&data, "FLAGS", GUINT_TO_POINTER (flags)); - } else if (!strncasecmp (response, "RFC822.SIZE ", 12)) { - unsigned long size; - - response += 12; - size = strtoul (response, &response, 10); - g_datalist_set_data (&data, "RFC822.SIZE", GUINT_TO_POINTER (size)); - } else if (!strncasecmp (response, "BODY[", 5) || - !strncasecmp (response, "RFC822 ", 7)) { - char *p; - - if (*response == 'B') { - response += 5; - - /* HEADER], HEADER.FIELDS (...)], or 0] */ - if (!strncasecmp (response, "HEADER", 6)) { - header = TRUE; - if (!strncasecmp (response + 6, ".FIELDS", 7)) - cache_header = FALSE; - } else if (!strncasecmp (response, "0]", 2)) - header = TRUE; - - p = strchr (response, ']'); - if (!p || *(p + 1) != ' ') - break; - - if (cache_header) - part_spec = g_strndup (response, p - response); - else - part_spec = g_strdup ("HEADER.FIELDS"); - - response = p + 2; - } else { - part_spec = g_strdup (""); - response += 7; - - if (!strncasecmp (response, "HEADER", 6)) - header = TRUE; - } - - body = imap_parse_nstring ((const char **) &response, &body_len); - if (!response) { - g_free (part_spec); - break; - } - - if (!body) - body = g_strdup (""); - g_datalist_set_data_full (&data, "BODY_PART_SPEC", part_spec, g_free); - g_datalist_set_data_full (&data, "BODY_PART_DATA", body, g_free); - g_datalist_set_data (&data, "BODY_PART_LEN", GINT_TO_POINTER (body_len)); - } else if (!strncasecmp (response, "BODY ", 5) || - !strncasecmp (response, "BODYSTRUCTURE ", 14)) { - response = strchr (response, ' ') + 1; - start = response; - imap_skip_list ((const char **) &response); - g_datalist_set_data_full (&data, "BODY", g_strndup (start, response - start), g_free); - } else if (!strncasecmp (response, "UID ", 4)) { - int len; - - len = strcspn (response + 4, " )"); - uid = g_strndup (response + 4, len); - g_datalist_set_data_full (&data, "UID", uid, g_free); - response += 4 + len; - } else if (!strncasecmp (response, "INTERNALDATE ", 13)) { - int len; - - response += 13; - if (*response == '"') { - response++; - len = strcspn (response, "\""); - idate = g_strndup (response, len); - g_datalist_set_data_full (&data, "INTERNALDATE", idate, g_free); - response += len + 1; - } - } else { - g_warning ("Unexpected FETCH response from server: (%s", response); - break; - } - } while (response && *response != ')'); - - if (!response || *response != ')') { - g_datalist_clear (&data); - return NULL; - } - - if (uid && body) { - CamelStream *stream; - - if (header && !cache_header) { - stream = camel_stream_mem_new_with_buffer (body, body_len); - } else { - CAMEL_IMAP_FOLDER_LOCK (imap_folder, cache_lock); - stream = camel_imap_message_cache_insert (imap_folder->cache, - uid, part_spec, - body, body_len, NULL); - CAMEL_IMAP_FOLDER_UNLOCK (imap_folder, cache_lock); - if (stream == NULL) - stream = camel_stream_mem_new_with_buffer (body, body_len); - } - - if (stream) - g_datalist_set_data_full (&data, "BODY_PART_STREAM", stream, - (GDestroyNotify) camel_object_unref); - } - - return data; -} - diff --git a/camel/providers/imap/camel-imap-folder.h b/camel/providers/imap/camel-imap-folder.h deleted file mode 100644 index a2ab1dfd2c..0000000000 --- a/camel/providers/imap/camel-imap-folder.h +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-folder.h: class for an imap folder */ - -/* - * Authors: - * Dan Winship <danw@ximian.com> - * Jeffrey Stedfast <fejj@ximian.com> - * - * Copyright (C) 2000, 2001 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_IMAP_FOLDER_H -#define CAMEL_IMAP_FOLDER_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include "camel-imap-types.h" -#include <camel/camel-disco-folder.h> -#include <camel/camel-folder-search.h> - -#define CAMEL_IMAP_FOLDER_TYPE (camel_imap_folder_get_type ()) -#define CAMEL_IMAP_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAP_FOLDER_TYPE, CamelImapFolder)) -#define CAMEL_IMAP_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAP_FOLDER_TYPE, CamelImapFolderClass)) -#define CAMEL_IS_IMAP_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAP_FOLDER_TYPE)) - -struct _CamelImapFolder { - CamelDiscoFolder parent_object; - - struct _CamelImapFolderPrivate *priv; - - CamelFolderSearch *search; - CamelImapMessageCache *cache; - - unsigned int need_rescan:1; - unsigned int need_refresh:1; - unsigned int read_only:1; -}; - -typedef struct { - CamelDiscoFolderClass parent_class; - - /* Virtual methods */ - -} CamelImapFolderClass; - - -/* public methods */ -CamelFolder *camel_imap_folder_new (CamelStore *parent, - const char *folder_name, - const char *folder_dir, - CamelException *ex); - -void camel_imap_folder_selected (CamelFolder *folder, - CamelImapResponse *response, - CamelException *ex); - -void camel_imap_folder_changed (CamelFolder *folder, int exists, - GArray *expunged, CamelException *ex); - -CamelStream *camel_imap_folder_fetch_data (CamelImapFolder *imap_folder, - const char *uid, - const char *section_text, - gboolean cache_only, - CamelException *ex); - -/* Standard Camel function */ -CamelType camel_imap_folder_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_IMAP_FOLDER_H */ diff --git a/camel/providers/imap/camel-imap-message-cache.c b/camel/providers/imap/camel-imap-message-cache.c deleted file mode 100644 index 3099602613..0000000000 --- a/camel/providers/imap/camel-imap-message-cache.c +++ /dev/null @@ -1,528 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-message-cache.c: Class for an IMAP message cache */ - -/* - * Author: - * Dan Winship <danw@ximian.com> - * - * Copyright (C) 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/types.h> -#include <dirent.h> -#include <errno.h> -#include <string.h> -#include <ctype.h> - -#include "camel-imap-message-cache.h" -#include "camel-data-wrapper.h" -#include "camel-exception.h" -#include "camel-stream-fs.h" -#include "camel-i18n.h" - -static void finalize (CamelImapMessageCache *cache); -static void stream_finalize (CamelObject *stream, gpointer event_data, gpointer user_data); - - -CamelType -camel_imap_message_cache_get_type (void) -{ - static CamelType camel_imap_message_cache_type = CAMEL_INVALID_TYPE; - - if (camel_imap_message_cache_type == CAMEL_INVALID_TYPE) { - camel_imap_message_cache_type = camel_type_register ( - CAMEL_OBJECT_TYPE, "CamelImapMessageCache", - sizeof (CamelImapMessageCache), - sizeof (CamelImapMessageCacheClass), - NULL, - NULL, - NULL, - (CamelObjectFinalizeFunc) finalize); - } - - return camel_imap_message_cache_type; -} - -static void -free_part (gpointer key, gpointer value, gpointer data) -{ - if (value) { - if (strchr (key, '.')) { - camel_object_unhook_event (value, "finalize", - stream_finalize, data); - camel_object_unref (value); - } else - g_ptr_array_free (value, TRUE); - } - g_free (key); -} - -static void -finalize (CamelImapMessageCache *cache) -{ - if (cache->path) - g_free (cache->path); - if (cache->parts) { - g_hash_table_foreach (cache->parts, free_part, cache); - g_hash_table_destroy (cache->parts); - } - if (cache->cached) - g_hash_table_destroy (cache->cached); -} - -static void -cache_put (CamelImapMessageCache *cache, const char *uid, const char *key, - CamelStream *stream) -{ - char *hash_key; - GPtrArray *subparts; - gpointer okey, ostream; - guint32 uidval; - - uidval = strtoul (uid, NULL, 10); - if (uidval > cache->max_uid) - cache->max_uid = uidval; - - subparts = g_hash_table_lookup (cache->parts, uid); - if (!subparts) { - subparts = g_ptr_array_new (); - g_hash_table_insert (cache->parts, g_strdup (uid), subparts); - } - - if (g_hash_table_lookup_extended (cache->parts, key, &okey, &ostream)) { - if (ostream) { - camel_object_unhook_event (ostream, "finalize", - stream_finalize, cache); - g_hash_table_remove (cache->cached, ostream); - camel_object_unref (ostream); - } - hash_key = okey; - } else { - hash_key = g_strdup (key); - g_ptr_array_add (subparts, hash_key); - } - - g_hash_table_insert (cache->parts, hash_key, stream); - g_hash_table_insert (cache->cached, stream, hash_key); - - if (stream) { - camel_object_hook_event (CAMEL_OBJECT (stream), "finalize", - stream_finalize, cache); - } -} - -/** - * camel_imap_message_cache_new: - * @path: directory to use for storage - * @summary: CamelFolderSummary for the folder we are caching - * @ex: a CamelException - * - * Return value: a new CamelImapMessageCache object using @path for - * storage. If cache files already exist in @path, then any that do not - * correspond to messages in @summary will be deleted. - **/ -CamelImapMessageCache * -camel_imap_message_cache_new (const char *path, CamelFolderSummary *summary, - CamelException *ex) -{ - CamelImapMessageCache *cache; - DIR *dir; - struct dirent *d; - char *uid, *p; - GPtrArray *deletes; - CamelMessageInfo *info; - - dir = opendir (path); - if (!dir) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open cache directory: %s"), - g_strerror (errno)); - return NULL; - } - - cache = (CamelImapMessageCache *)camel_object_new (CAMEL_IMAP_MESSAGE_CACHE_TYPE); - cache->path = g_strdup (path); - - cache->parts = g_hash_table_new (g_str_hash, g_str_equal); - cache->cached = g_hash_table_new (NULL, NULL); - deletes = g_ptr_array_new (); - while ((d = readdir (dir))) { - if (!isdigit (d->d_name[0])) - continue; - - p = strchr (d->d_name, '.'); - if (p) - uid = g_strndup (d->d_name, p - d->d_name); - else - uid = g_strdup (d->d_name); - - info = camel_folder_summary_uid (summary, uid); - if (info) { - camel_message_info_free(info); - cache_put (cache, uid, d->d_name, NULL); - } else - g_ptr_array_add (deletes, g_strdup_printf ("%s/%s", cache->path, d->d_name)); - g_free (uid); - } - closedir (dir); - - while (deletes->len) { - unlink (deletes->pdata[0]); - g_free (deletes->pdata[0]); - g_ptr_array_remove_index_fast (deletes, 0); - } - g_ptr_array_free (deletes, TRUE); - - return cache; -} - -/** - * camel_imap_message_cache_max_uid: - * @cache: the cache - * - * Return value: the largest (real) UID in the cache. - **/ -guint32 -camel_imap_message_cache_max_uid (CamelImapMessageCache *cache) -{ - return cache->max_uid; -} - -/** - * camel_imap_message_cache_set_path: - * @cache: - * @path: - * - * Set the path used for the message cache. - **/ -void -camel_imap_message_cache_set_path (CamelImapMessageCache *cache, const char *path) -{ - g_free(cache->path); - cache->path = g_strdup(path); -} - -static void -stream_finalize (CamelObject *stream, gpointer event_data, gpointer user_data) -{ - CamelImapMessageCache *cache = user_data; - char *key; - - key = g_hash_table_lookup (cache->cached, stream); - if (!key) - return; - g_hash_table_remove (cache->cached, stream); - g_hash_table_insert (cache->parts, key, NULL); -} - - -static CamelStream * -insert_setup (CamelImapMessageCache *cache, const char *uid, const char *part_spec, - char **path, char **key, CamelException *ex) -{ - CamelStream *stream; - int fd; - - *path = g_strdup_printf ("%s/%s.%s", cache->path, uid, part_spec); - *key = strrchr (*path, '/') + 1; - stream = g_hash_table_lookup (cache->parts, *key); - if (stream) - camel_object_unref (CAMEL_OBJECT (stream)); - - fd = open (*path, O_RDWR | O_CREAT | O_TRUNC, 0600); - if (fd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to cache message %s: %s"), - uid, g_strerror (errno)); - g_free (*path); - return NULL; - } - - return camel_stream_fs_new_with_fd (fd); -} - -static CamelStream * -insert_abort (char *path, CamelStream *stream) -{ - unlink (path); - g_free (path); - camel_object_unref (CAMEL_OBJECT (stream)); - return NULL; -} - -static CamelStream * -insert_finish (CamelImapMessageCache *cache, const char *uid, char *path, - char *key, CamelStream *stream) -{ - camel_stream_flush (stream); - camel_stream_reset (stream); - cache_put (cache, uid, key, stream); - g_free (path); - - return stream; -} - -/** - * camel_imap_message_cache_insert: - * @cache: the cache - * @uid: UID of the message data to cache - * @part_spec: the IMAP part_spec of the data - * @data: the data - * @len: length of @data - * - * Caches the provided data into @cache. - * - * Return value: a CamelStream containing the cached data, which the - * caller must unref. - **/ -CamelStream * -camel_imap_message_cache_insert (CamelImapMessageCache *cache, const char *uid, - const char *part_spec, const char *data, - int len, CamelException *ex) -{ - char *path, *key; - CamelStream *stream; - - stream = insert_setup (cache, uid, part_spec, &path, &key, ex); - if (!stream) - return NULL; - - if (camel_stream_write (stream, data, len) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to cache message %s: %s"), - uid, g_strerror (errno)); - return insert_abort (path, stream); - } - - return insert_finish (cache, uid, path, key, stream); -} - -/** - * camel_imap_message_cache_insert_stream: - * @cache: the cache - * @uid: UID of the message data to cache - * @part_spec: the IMAP part_spec of the data - * @data_stream: the stream to cache - * - * Caches the provided data into @cache. - **/ -void -camel_imap_message_cache_insert_stream (CamelImapMessageCache *cache, - const char *uid, const char *part_spec, - CamelStream *data_stream, CamelException *ex) -{ - char *path, *key; - CamelStream *stream; - - stream = insert_setup (cache, uid, part_spec, &path, &key, ex); - if (!stream) - return; - - if (camel_stream_write_to_stream (data_stream, stream) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to cache message %s: %s"), - uid, g_strerror (errno)); - insert_abort (path, stream); - } else { - insert_finish (cache, uid, path, key, stream); - camel_object_unref (CAMEL_OBJECT (stream)); - } -} - -/** - * camel_imap_message_cache_insert_wrapper: - * @cache: the cache - * @uid: UID of the message data to cache - * @part_spec: the IMAP part_spec of the data - * @wrapper: the wrapper to cache - * - * Caches the provided data into @cache. - **/ -void -camel_imap_message_cache_insert_wrapper (CamelImapMessageCache *cache, - const char *uid, const char *part_spec, - CamelDataWrapper *wrapper, CamelException *ex) -{ - char *path, *key; - CamelStream *stream; - - stream = insert_setup (cache, uid, part_spec, &path, &key, ex); - if (!stream) - return; - - if (camel_data_wrapper_write_to_stream (wrapper, stream) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to cache message %s: %s"), - uid, g_strerror (errno)); - insert_abort (path, stream); - } else { - insert_finish (cache, uid, path, key, stream); - camel_object_unref (CAMEL_OBJECT (stream)); - } -} - - -/** - * camel_imap_message_cache_get: - * @cache: the cache - * @uid: the UID of the data to get - * @part_spec: the part_spec of the data to get - * @ex: exception - * - * Return value: a CamelStream containing the cached data (which the - * caller must unref), or %NULL if that data is not cached. - **/ -CamelStream * -camel_imap_message_cache_get (CamelImapMessageCache *cache, const char *uid, - const char *part_spec, CamelException *ex) -{ - CamelStream *stream; - char *path, *key; - - if (uid[0] == 0) - return NULL; - - path = g_strdup_printf ("%s/%s.%s", cache->path, uid, part_spec); - key = strrchr (path, '/') + 1; - stream = g_hash_table_lookup (cache->parts, key); - if (stream) { - camel_stream_reset (CAMEL_STREAM (stream)); - camel_object_ref (CAMEL_OBJECT (stream)); - g_free (path); - return stream; - } - - stream = camel_stream_fs_new_with_name (path, O_RDONLY, 0); - if (stream) { - cache_put (cache, uid, key, stream); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to cache %s: %s"), - part_spec, g_strerror (errno)); - } - - g_free (path); - - return stream; -} - -/** - * camel_imap_message_cache_remove: - * @cache: the cache - * @uid: UID of the data to remove - * - * Removes all data associated with @uid from @cache. - **/ -void -camel_imap_message_cache_remove (CamelImapMessageCache *cache, const char *uid) -{ - GPtrArray *subparts; - char *key, *path; - CamelObject *stream; - int i; - - subparts = g_hash_table_lookup (cache->parts, uid); - if (!subparts) - return; - for (i = 0; i < subparts->len; i++) { - key = subparts->pdata[i]; - path = g_strdup_printf ("%s/%s", cache->path, key); - unlink (path); - g_free (path); - stream = g_hash_table_lookup (cache->parts, key); - if (stream) { - camel_object_unhook_event (stream, "finalize", - stream_finalize, cache); - camel_object_unref (stream); - g_hash_table_remove (cache->cached, stream); - } - g_hash_table_remove (cache->parts, key); - g_free (key); - } - g_hash_table_remove (cache->parts, uid); - g_ptr_array_free (subparts, TRUE); -} - -static void -add_uids (gpointer key, gpointer value, gpointer data) -{ - if (!strchr (key, '.')) - g_ptr_array_add (data, key); -} - -/** - * camel_imap_message_cache_clear: - * @cache: the cache - * - * Removes all cached data from @cache. - **/ -void -camel_imap_message_cache_clear (CamelImapMessageCache *cache) -{ - GPtrArray *uids; - int i; - - uids = g_ptr_array_new (); - g_hash_table_foreach (cache->parts, add_uids, uids); - - for (i = 0; i < uids->len; i++) - camel_imap_message_cache_remove (cache, uids->pdata[i]); - g_ptr_array_free (uids, TRUE); -} - - -/** - * camel_imap_message_cache_copy: - * @source: the source message cache - * @source_uid: UID of a message in @source - * @dest: the destination message cache - * @dest_uid: UID of the message in @dest - * - * Copies all cached parts from @source_uid in @source to @dest_uid in - * @destination. - **/ -void -camel_imap_message_cache_copy (CamelImapMessageCache *source, - const char *source_uid, - CamelImapMessageCache *dest, - const char *dest_uid, - CamelException *ex) -{ - GPtrArray *subparts; - CamelStream *stream; - char *part; - int i; - - subparts = g_hash_table_lookup (source->parts, source_uid); - if (!subparts || !subparts->len) - return; - - for (i = 0; i < subparts->len; i++) { - part = strchr (subparts->pdata[i], '.'); - if (!part++) - continue; - - if ((stream = camel_imap_message_cache_get (source, source_uid, part, ex))) { - camel_imap_message_cache_insert_stream (dest, dest_uid, part, stream, ex); - camel_object_unref (CAMEL_OBJECT (stream)); - } - } -} diff --git a/camel/providers/imap/camel-imap-message-cache.h b/camel/providers/imap/camel-imap-message-cache.h deleted file mode 100644 index c79195cfa4..0000000000 --- a/camel/providers/imap/camel-imap-message-cache.h +++ /dev/null @@ -1,111 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-message-cache.h: Class for an IMAP message cache */ - -/* - * Author: - * Dan Winship <danw@ximian.com> - * - * Copyright (C) 2001 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_IMAP_MESSAGE_CACHE_H -#define CAMEL_IMAP_MESSAGE_CACHE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-imap-types.h" -#include "camel-folder.h" -#include <camel/camel-folder-search.h> - -#define CAMEL_IMAP_MESSAGE_CACHE_TYPE (camel_imap_message_cache_get_type ()) -#define CAMEL_IMAP_MESSAGE_CACHE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAP_MESSAGE_CACHE_TYPE, CamelImapFolder)) -#define CAMEL_IMAP_MESSAGE_CACHE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAP_MESSAGE_CACHE_TYPE, CamelImapFolderClass)) -#define CAMEL_IS_IMAP_MESSAGE_CACHE(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAP_MESSAGE_CACHE_TYPE)) - -struct _CamelImapMessageCache { - CamelObject parent_object; - - char *path; - GHashTable *parts, *cached; - guint32 max_uid; -}; - - -typedef struct { - CamelFolderClass parent_class; - - /* Virtual methods */ - -} CamelImapMessageCacheClass; - - -/* public methods */ -CamelImapMessageCache *camel_imap_message_cache_new (const char *path, - CamelFolderSummary *summ, - CamelException *ex); - -void camel_imap_message_cache_set_path (CamelImapMessageCache *cache, - const char *path); - -guint32 camel_imap_message_cache_max_uid (CamelImapMessageCache *cache); - -CamelStream *camel_imap_message_cache_insert (CamelImapMessageCache *cache, - const char *uid, - const char *part_spec, - const char *data, - int len, - CamelException *ex); -void camel_imap_message_cache_insert_stream (CamelImapMessageCache *cache, - const char *uid, - const char *part_spec, - CamelStream *data_stream, - CamelException *ex); -void camel_imap_message_cache_insert_wrapper (CamelImapMessageCache *cache, - const char *uid, - const char *part_spec, - CamelDataWrapper *wrapper, - CamelException *ex); - -CamelStream *camel_imap_message_cache_get (CamelImapMessageCache *cache, - const char *uid, - const char *part_spec, - CamelException *ex); - -void camel_imap_message_cache_remove (CamelImapMessageCache *cache, - const char *uid); - -void camel_imap_message_cache_clear (CamelImapMessageCache *cache); - -void camel_imap_message_cache_copy (CamelImapMessageCache *source, - const char *source_uid, - CamelImapMessageCache *dest, - const char *dest_uid, - CamelException *ex); - -/* Standard Camel function */ -CamelType camel_imap_message_cache_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_IMAP_MESSAGE_CACHE_H */ diff --git a/camel/providers/imap/camel-imap-private.h b/camel/providers/imap/camel-imap-private.h deleted file mode 100644 index d07358527a..0000000000 --- a/camel/providers/imap/camel-imap-private.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * camel-imap-private.h: Private info for imap. - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_IMAP_PRIVATE_H -#define CAMEL_IMAP_PRIVATE_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -/* need a way to configure and save this data, if this header is to - be installed. For now, dont install it */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef ENABLE_THREADS -#include "libedataserver/e-msgport.h" -#endif - -struct _CamelImapFolderPrivate { -#ifdef ENABLE_THREADS - EMutex *search_lock; /* for locking the search object */ - EMutex *cache_lock; /* for locking the cache object */ -#endif -}; - -#ifdef ENABLE_THREADS -#define CAMEL_IMAP_FOLDER_LOCK(f, l) (e_mutex_lock(((CamelImapFolder *)f)->priv->l)) -#define CAMEL_IMAP_FOLDER_UNLOCK(f, l) (e_mutex_unlock(((CamelImapFolder *)f)->priv->l)) -#else -#define CAMEL_IMAP_FOLDER_LOCK(f, l) -#define CAMEL_IMAP_FOLDER_UNLOCK(f, l) -#endif - -struct _CamelImapWrapperPrivate { -#ifdef ENABLE_THREADS - GMutex *lock; -#endif -}; - -#ifdef ENABLE_THREADS -#define CAMEL_IMAP_WRAPPER_LOCK(f, l) (g_mutex_lock(((CamelImapWrapper *)f)->priv->l)) -#define CAMEL_IMAP_WRAPPER_UNLOCK(f, l) (g_mutex_unlock(((CamelImapWrapper *)f)->priv->l)) -#else -#define CAMEL_IMAP_WRAPPER_LOCK(f, l) -#define CAMEL_IMAP_WRAPPER_UNLOCK(f, l) -#endif - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_IMAP_PRIVATE_H */ - diff --git a/camel/providers/imap/camel-imap-provider.c b/camel/providers/imap/camel-imap-provider.c deleted file mode 100644 index e574a5c1f7..0000000000 --- a/camel/providers/imap/camel-imap-provider.c +++ /dev/null @@ -1,164 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-provider.c: imap provider registration code */ - -/* - * Authors: Jeffrey Stedfast <fejj@ximian.com> - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include "camel-imap-store.h" -#include "camel-provider.h" -#include "camel-session.h" -#include "camel-url.h" -#include "camel-sasl.h" -#include "camel-i18n.h" - -static void add_hash (guint *hash, char *s); -static guint imap_url_hash (gconstpointer key); -static gint check_equal (char *s1, char *s2); -static gint imap_url_equal (gconstpointer a, gconstpointer b); - -CamelProviderConfEntry imap_conf_entries[] = { - { CAMEL_PROVIDER_CONF_SECTION_START, "mailcheck", NULL, - N_("Checking for New Mail") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "check_all", NULL, - N_("C_heck for new messages in all folders"), "1" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_SECTION_START, "cmdsection", NULL, - N_("Connection to Server") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "use_command", NULL, - N_("_Use custom command to connect to server"), "0" }, - { CAMEL_PROVIDER_CONF_ENTRY, "command", "use_command", - N_("Command:"), "ssh -C -l %u %h exec /usr/sbin/imapd" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_SECTION_START, "folders", NULL, - N_("Folders") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "use_lsub", NULL, - N_("_Show only subscribed folders"), "1" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "override_namespace", NULL, - N_("O_verride server-supplied folder namespace"), "0" }, - { CAMEL_PROVIDER_CONF_ENTRY, "namespace", "override_namespace", - N_("Namespace") }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_SECTION_START, "general", NULL, N_("Options") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter", NULL, - N_("_Apply filters to new messages in INBOX on this server"), "0" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter_junk", NULL, - N_("Check new messages for _Junk contents"), "0" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter_junk_inbox", "filter_junk", - N_("Only check for Junk messa_ges in the INBOX folder"), "0" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "offline_sync", NULL, - N_("Automatically synchroni_ze remote mail locally"), "0" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider imap_provider = { - "imap", - N_("IMAP"), - - N_("For reading and storing mail on IMAP servers."), - - "mail", - - CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE | - CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_SUPPORTS_SSL, - - CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH, - - imap_conf_entries, - - /* ... */ -}; - -CamelServiceAuthType camel_imap_password_authtype = { - N_("Password"), - - N_("This option will connect to the IMAP server using a " - "plaintext password."), - - "", - TRUE -}; - -void -camel_provider_module_init(void) -{ - imap_provider.object_types[CAMEL_PROVIDER_STORE] = camel_imap_store_get_type (); - imap_provider.url_hash = imap_url_hash; - imap_provider.url_equal = imap_url_equal; - imap_provider.authtypes = camel_sasl_authtype_list (FALSE); - imap_provider.authtypes = g_list_prepend (imap_provider.authtypes, &camel_imap_password_authtype); - - camel_provider_register(&imap_provider); -} - -static void -add_hash (guint *hash, char *s) -{ - if (s) - *hash ^= g_str_hash(s); -} - -static guint -imap_url_hash (gconstpointer key) -{ - const CamelURL *u = (CamelURL *)key; - guint hash = 0; - - add_hash (&hash, u->user); - add_hash (&hash, u->authmech); - add_hash (&hash, u->host); - hash ^= u->port; - - return hash; -} - -static int -check_equal (char *s1, char *s2) -{ - if (s1 == NULL) { - if (s2 == NULL) - return TRUE; - else - return FALSE; - } - - if (s2 == NULL) - return FALSE; - - return strcmp (s1, s2) == 0; -} - -static int -imap_url_equal (gconstpointer a, gconstpointer b) -{ - const CamelURL *u1 = a, *u2 = b; - - return check_equal (u1->protocol, u2->protocol) - && check_equal (u1->user, u2->user) - && check_equal (u1->authmech, u2->authmech) - && check_equal (u1->host, u2->host) - && u1->port == u2->port; -} diff --git a/camel/providers/imap/camel-imap-search.c b/camel/providers/imap/camel-imap-search.c deleted file mode 100644 index 2c0dcb02f6..0000000000 --- a/camel/providers/imap/camel-imap-search.c +++ /dev/null @@ -1,499 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-search.c: IMAP folder search */ - -/* - * Authors: - * Dan Winship <danw@ximian.com> - * Michael Zucchi <notzed@ximian.com> - * - * Copyright 2000, 2001, 2002 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> - -#include "camel-imap-command.h" -#include "camel-imap-folder.h" -#include "camel-imap-store.h" -#include "camel-imap-search.h" -#include "camel-imap-private.h" -#include "camel-imap-utils.h" -#include "camel-imap-summary.h" - -#include "libedataserver/md5-utils.h" /* md5 hash building */ -#include "camel-mime-utils.h" /* base64 encoding */ - -#include "camel-seekable-stream.h" -#include "camel-search-private.h" - -#define d(x) - -/* - File is: - BODY (as in body search) - Last uid when search performed - termcount: number of search terms - matchcount: number of matches - term0, term1 ... - match0, match1, match2, ... -*/ - -/* size of in-memory cache */ -#define MATCH_CACHE_SIZE (32) - -/* Also takes care of 'endianness' file magic */ -#define MATCH_MARK (('B' << 24) | ('O' << 16) | ('D' << 8) | 'Y') - -/* on-disk header, in native endianness format, matches follow */ -struct _match_header { - guint32 mark; - guint32 validity; /* uidvalidity for this folder */ - guint32 lastuid; - guint32 termcount; - guint32 matchcount; -}; - -/* in-memory record */ -struct _match_record { - struct _match_record *next; - struct _match_record *prev; - - char hash[17]; - - guint32 lastuid; - guint32 validity; - - unsigned int termcount; - char **terms; - GArray *matches; -}; - - -static void free_match(CamelImapSearch *is, struct _match_record *mr); -static ESExpResult *imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s); - -static CamelFolderSearchClass *imap_search_parent_class; - -static void -camel_imap_search_class_init (CamelImapSearchClass *camel_imap_search_class) -{ - /* virtual method overload */ - CamelFolderSearchClass *camel_folder_search_class = - CAMEL_FOLDER_SEARCH_CLASS (camel_imap_search_class); - - imap_search_parent_class = (CamelFolderSearchClass *)camel_type_get_global_classfuncs (camel_folder_search_get_type ()); - - /* virtual method overload */ - camel_folder_search_class->body_contains = imap_body_contains; -} - -static void -camel_imap_search_init(CamelImapSearch *is) -{ - e_dlist_init(&is->matches); - is->matches_hash = g_hash_table_new(g_str_hash, g_str_equal); - is->matches_count = 0; - is->lastuid = 0; -} - -static void -camel_imap_search_finalise(CamelImapSearch *is) -{ - struct _match_record *mr; - - while ( (mr = (struct _match_record *)e_dlist_remtail(&is->matches)) ) - free_match(is, mr); - g_hash_table_destroy(is->matches_hash); - if (is->cache) - camel_object_unref((CamelObject *)is->cache); -} - -CamelType -camel_imap_search_get_type (void) -{ - static CamelType camel_imap_search_type = CAMEL_INVALID_TYPE; - - if (camel_imap_search_type == CAMEL_INVALID_TYPE) { - camel_imap_search_type = camel_type_register ( - CAMEL_FOLDER_SEARCH_TYPE, "CamelImapSearch", - sizeof (CamelImapSearch), - sizeof (CamelImapSearchClass), - (CamelObjectClassInitFunc) camel_imap_search_class_init, NULL, - (CamelObjectInitFunc) camel_imap_search_init, - (CamelObjectFinalizeFunc) camel_imap_search_finalise); - } - - return camel_imap_search_type; -} - -/** - * camel_imap_search_new: - * - * Return value: A new CamelImapSearch widget. - **/ -CamelFolderSearch * -camel_imap_search_new (const char *cachedir) -{ - CamelFolderSearch *new = CAMEL_FOLDER_SEARCH (camel_object_new (camel_imap_search_get_type ())); - CamelImapSearch *is = (CamelImapSearch *)new; - - camel_folder_search_construct (new); - - is->cache = camel_data_cache_new(cachedir, 0, NULL); - if (is->cache) { - /* Expire entries after 14 days of inactivity */ - camel_data_cache_set_expire_access(is->cache, 60*60*24*14); - } - - return new; -} - - -static void -hash_match(char hash[17], int argc, struct _ESExpResult **argv) -{ - MD5Context ctx; - unsigned char digest[16]; - unsigned int state = 0, save = 0; - int i; - - md5_init(&ctx); - for (i=0;i<argc;i++) { - if (argv[i]->type == ESEXP_RES_STRING) - md5_update(&ctx, argv[i]->value.string, strlen(argv[i]->value.string)); - } - md5_final(&ctx, digest); - - camel_base64_encode_close(digest, 12, FALSE, hash, &state, &save); - - for (i=0;i<16;i++) { - if (hash[i] == '+') - hash[i] = ','; - if (hash[i] == '/') - hash[i] = '_'; - } - - hash[16] = 0; -} - -static int -save_match(CamelImapSearch *is, struct _match_record *mr) -{ - guint32 mark = MATCH_MARK; - int ret = 0; - struct _match_header header; - CamelStream *stream; - - /* since its a cache, doesn't matter if it doesn't save, at least we have the in-memory cache - for this session */ - if (is->cache == NULL) - return -1; - - stream = camel_data_cache_add(is->cache, "search/body-contains", mr->hash, NULL); - if (stream == NULL) - return -1; - - d(printf("Saving search cache entry to '%s': %s\n", mr->hash, mr->terms[0])); - - /* we write the whole thing, then re-write the header magic, saves fancy sync code */ - memcpy(&header.mark, " ", 4); - header.termcount = 0; - header.matchcount = mr->matches->len; - header.lastuid = mr->lastuid; - header.validity = mr->validity; - - if (camel_stream_write(stream, (char *)&header, sizeof(header)) != sizeof(header) - || camel_stream_write(stream, mr->matches->data, mr->matches->len*sizeof(guint32)) != mr->matches->len*sizeof(guint32) - || camel_seekable_stream_seek((CamelSeekableStream *)stream, 0, CAMEL_STREAM_SET) == -1 - || camel_stream_write(stream, (char *)&mark, sizeof(mark)) != sizeof(mark)) { - d(printf(" saving failed, removing cache entry\n")); - camel_data_cache_remove(is->cache, "search/body-contains", mr->hash, NULL); - ret = -1; - } - - camel_object_unref((CamelObject *)stream); - return ret; -} - -static void -free_match(CamelImapSearch *is, struct _match_record *mr) -{ - int i; - - for (i=0;i<mr->termcount;i++) - g_free(mr->terms[i]); - g_free(mr->terms); - g_array_free(mr->matches, TRUE); - g_free(mr); -} - -static struct _match_record * -load_match(CamelImapSearch *is, char hash[17], int argc, struct _ESExpResult **argv) -{ - struct _match_record *mr; - CamelStream *stream = NULL; - struct _match_header header; - int i; - - mr = g_malloc0(sizeof(*mr)); - mr->matches = g_array_new(0, 0, sizeof(guint32)); - g_assert(strlen(hash) == 16); - strcpy(mr->hash, hash); - mr->terms = g_malloc0(sizeof(mr->terms[0]) * argc); - for (i=0;i<argc;i++) { - if (argv[i]->type == ESEXP_RES_STRING) { - mr->termcount++; - mr->terms[i] = g_strdup(argv[i]->value.string); - } - } - - d(printf("Loading search cache entry to '%s': %s\n", mr->hash, mr->terms[0])); - - memset(&header, 0, sizeof(header)); - if (is->cache) - stream = camel_data_cache_get(is->cache, "search/body-contains", mr->hash, NULL); - if (stream != NULL) { - /* 'cause i'm gonna be lazy, i'm going to have the termcount == 0 for now, - and not load or save them since i can't think of a nice way to do it, the hash - should be sufficient to key it */ - /* This check should also handle endianness changes, we just throw away - the data (its only a cache) */ - if (camel_stream_read(stream, (char *)&header, sizeof(header)) == sizeof(header) - && header.validity == is->validity - && header.mark == MATCH_MARK - && header.termcount == 0) { - d(printf(" found %d matches\n", header.matchcount)); - g_array_set_size(mr->matches, header.matchcount); - camel_stream_read(stream, mr->matches->data, sizeof(guint32)*header.matchcount); - } else { - d(printf(" file format invalid/validity changed\n")); - memset(&header, 0, sizeof(header)); - } - camel_object_unref((CamelObject *)stream); - } else { - d(printf(" no cache entry found\n")); - } - - mr->validity = header.validity; - if (mr->validity != is->validity) - mr->lastuid = 0; - else - mr->lastuid = header.lastuid; - - return mr; -} - -static int -sync_match(CamelImapSearch *is, struct _match_record *mr) -{ - char *p, *result, *lasts = NULL; - CamelImapResponse *response = NULL; - guint32 uid; - CamelFolder *folder = ((CamelFolderSearch *)is)->folder; - CamelImapStore *store = (CamelImapStore *)folder->parent_store; - struct _camel_search_words *words; - GString *search; - int i; - - if (mr->lastuid >= is->lastuid && mr->validity == is->validity) - return 0; - - d(printf ("updating match record for uid's %d:%d\n", mr->lastuid+1, is->lastuid)); - - /* TODO: Handle multiple search terms */ - - /* This handles multiple search words within a single term */ - words = camel_search_words_split (mr->terms[0]); - search = g_string_new (""); - g_string_append_printf (search, "UID %d:%d", mr->lastuid + 1, is->lastuid); - for (i = 0; i < words->len; i++) { - char *w = words->words[i]->word, c; - - g_string_append_printf (search, " BODY \""); - while ((c = *w++)) { - if (c == '\\' || c == '"') - g_string_append_c (search, '\\'); - g_string_append_c (search, c); - } - g_string_append_c (search, '"'); - } - camel_search_words_free (words); - - /* We only try search using utf8 if its non us-ascii text? */ - if ((words->type & CAMEL_SEARCH_WORD_8BIT) && (store->capabilities & IMAP_CAPABILITY_utf8_search)) { - response = camel_imap_command (store, folder, NULL, - "UID SEARCH CHARSET UTF-8 %s", search->str); - /* We can't actually tell if we got a NO response, so assume always */ - if (response == NULL) - store->capabilities &= ~IMAP_CAPABILITY_utf8_search; - } - if (response == NULL) - response = camel_imap_command (store, folder, NULL, - "UID SEARCH %s", search->str); - g_string_free(search, TRUE); - - if (!response) - return -1; - result = camel_imap_response_extract (store, response, "SEARCH", NULL); - if (!result) - return -1; - - p = result + sizeof ("* SEARCH"); - for (p = strtok_r (p, " ", &lasts); p; p = strtok_r (NULL, " ", &lasts)) { - uid = strtoul(p, NULL, 10); - g_array_append_vals(mr->matches, &uid, 1); - } - g_free(result); - - mr->validity = is->validity; - mr->lastuid = is->lastuid; - save_match(is, mr); - - return 0; -} - -static struct _match_record * -get_match(CamelImapSearch *is, int argc, struct _ESExpResult **argv) -{ - char hash[17]; - struct _match_record *mr; - - hash_match(hash, argc, argv); - - mr = g_hash_table_lookup(is->matches_hash, hash); - if (mr == NULL) { - while (is->matches_count >= MATCH_CACHE_SIZE) { - mr = (struct _match_record *)e_dlist_remtail(&is->matches); - if (mr) { - printf("expiring match '%s' (%s)\n", mr->hash, mr->terms[0]); - g_hash_table_remove(is->matches_hash, mr->hash); - free_match(is, mr); - is->matches_count--; - } else { - is->matches_count = 0; - } - } - mr = load_match(is, hash, argc, argv); - g_hash_table_insert(is->matches_hash, mr->hash, mr); - is->matches_count++; - } else { - e_dlist_remove((EDListNode *)mr); - } - - e_dlist_addhead(&is->matches, (EDListNode *)mr); - - /* what about offline mode? */ - /* We could cache those results too, or should we cache them elsewhere? */ - sync_match(is, mr); - - return mr; -} - -static ESExpResult * -imap_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (s->folder->parent_store); - CamelImapSearch *is = (CamelImapSearch *)s; - char *uid; - ESExpResult *r; - CamelMessageInfo *info; - GHashTable *uid_hash = NULL; - GPtrArray *array; - int i, j; - struct _match_record *mr; - guint32 uidn, *uidp; - - d(printf("Performing body search '%s'\n", argv[0]->value.string)); - - /* TODO: Cache offline searches too? */ - - /* If offline, search using the parent class, which can handle this manually */ - if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), NULL)) - return imap_search_parent_class->body_contains(f, argc, argv, s); - - /* optimise the match "" case - match everything */ - if (argc == 1 && argv[0]->value.string[0] == '\0') { - if (s->current) { - r = e_sexp_result_new(f, ESEXP_RES_BOOL); - r->value.bool = TRUE; - } else { - r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR); - r->value.ptrarray = g_ptr_array_new (); - for (i = 0; i < s->summary->len; i++) { - info = g_ptr_array_index(s->summary, i); - g_ptr_array_add(r->value.ptrarray, (char *)camel_message_info_uid(info)); - } - } - } else if (argc == 0 || s->summary->len == 0) { - /* nothing to match case, do nothing (should be handled higher up?) */ - if (s->current) { - r = e_sexp_result_new(f, ESEXP_RES_BOOL); - r->value.bool = FALSE; - } else { - r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR); - r->value.ptrarray = g_ptr_array_new (); - } - } else { - int truth = FALSE; - - /* setup lastuid/validity for synchronising */ - info = g_ptr_array_index(s->summary, s->summary->len-1); - is->lastuid = strtoul(camel_message_info_uid(info), NULL, 10); - is->validity = ((CamelImapSummary *)(s->folder->summary))->validity; - - mr = get_match(is, argc, argv); - - if (s->current) { - uidn = strtoul(camel_message_info_uid(s->current), NULL, 10); - uidp = (guint32 *)mr->matches->data; - j = mr->matches->len; - for (i=0;i<j && !truth;i++) - truth = *uidp++ == uidn; - r = e_sexp_result_new(f, ESEXP_RES_BOOL); - r->value.bool = truth; - } else { - r = e_sexp_result_new(f, ESEXP_RES_ARRAY_PTR); - array = r->value.ptrarray = g_ptr_array_new(); - - /* We use a hash to map the uid numbers to uid strings as required by the search api */ - /* We use the summary's strings so we dont need to alloc more */ - uid_hash = g_hash_table_new(NULL, NULL); - for (i = 0; i < s->summary->len; i++) { - info = s->summary->pdata[i]; - uid = (char *)camel_message_info_uid(info); - uidn = strtoul(uid, NULL, 10); - g_hash_table_insert(uid_hash, GUINT_TO_POINTER(uidn), uid); - } - - uidp = (guint32 *)mr->matches->data; - j = mr->matches->len; - for (i=0;i<j && !truth;i++) { - uid = g_hash_table_lookup(uid_hash, GUINT_TO_POINTER(*uidp++)); - if (uid) - g_ptr_array_add(array, uid); - } - - g_hash_table_destroy(uid_hash); - } - } - - return r; -} diff --git a/camel/providers/imap/camel-imap-search.h b/camel/providers/imap/camel-imap-search.h deleted file mode 100644 index 3ad7f8decc..0000000000 --- a/camel/providers/imap/camel-imap-search.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-search.h: IMAP folder search */ - -/* - * Authors: - * Dan Winship <danw@ximian.com> - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef _CAMEL_IMAP_SEARCH_H -#define _CAMEL_IMAP_SEARCH_H - -#include <camel/camel-folder-search.h> -#include <libedataserver/e-msgport.h> -#include <camel/camel-data-cache.h> - -#define CAMEL_IMAP_SEARCH_TYPE (camel_imap_search_get_type ()) -#define CAMEL_IMAP_SEARCH(obj) CAMEL_CHECK_CAST (obj, camel_imap_search_get_type (), CamelImapSearch) -#define CAMEL_IMAP_SEARCH_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imap_search_get_type (), CamelImapSearchClass) -#define CAMEL_IS_IMAP_SEARCH(obj) CAMEL_CHECK_TYPE (obj, camel_imap_search_get_type ()) - -typedef struct _CamelImapSearchClass CamelImapSearchClass; - -struct _CamelImapSearch { - CamelFolderSearch parent; - - guint32 lastuid; /* current 'last uid' for the folder */ - guint32 validity; /* validity of the current folder */ - - CamelDataCache *cache; /* disk-cache for searches */ - - /* cache of body search matches */ - unsigned int matches_count; - EDList matches; - GHashTable *matches_hash; -}; - -struct _CamelImapSearchClass { - CamelFolderSearchClass parent_class; - -}; - -CamelType camel_imap_search_get_type (void); -CamelFolderSearch *camel_imap_search_new (const char *cachedir); - -#endif /* ! _CAMEL_IMAP_SEARCH_H */ diff --git a/camel/providers/imap/camel-imap-store-summary.c b/camel/providers/imap/camel-imap-store-summary.c deleted file mode 100644 index 434f5b5da0..0000000000 --- a/camel/providers/imap/camel-imap-store-summary.c +++ /dev/null @@ -1,619 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2002 Ximian Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <unistd.h> -#include <ctype.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> - -#include "camel-imap-store-summary.h" - -#include "camel-file-utils.h" - -#include "libedataserver/md5-utils.h" -#include "libedataserver/e-memory.h" - -#include "camel-private.h" -#include "camel-utf8.h" - -#define d(x) -#define io(x) /* io debug */ - -#define CAMEL_IMAP_STORE_SUMMARY_VERSION_0 (0) - -#define CAMEL_IMAP_STORE_SUMMARY_VERSION (0) - -#define _PRIVATE(o) (((CamelImapStoreSummary *)(o))->priv) - -static int summary_header_load(CamelStoreSummary *, FILE *); -static int summary_header_save(CamelStoreSummary *, FILE *); - -/*static CamelStoreInfo * store_info_new(CamelStoreSummary *, const char *);*/ -static CamelStoreInfo * store_info_load(CamelStoreSummary *, FILE *); -static int store_info_save(CamelStoreSummary *, FILE *, CamelStoreInfo *); -static void store_info_free(CamelStoreSummary *, CamelStoreInfo *); - -static const char *store_info_string(CamelStoreSummary *, const CamelStoreInfo *, int); -static void store_info_set_string(CamelStoreSummary *, CamelStoreInfo *, int, const char *); - -static void camel_imap_store_summary_class_init (CamelImapStoreSummaryClass *klass); -static void camel_imap_store_summary_init (CamelImapStoreSummary *obj); -static void camel_imap_store_summary_finalise (CamelObject *obj); - -static CamelStoreSummaryClass *camel_imap_store_summary_parent; - -static void -camel_imap_store_summary_class_init (CamelImapStoreSummaryClass *klass) -{ - CamelStoreSummaryClass *ssklass = (CamelStoreSummaryClass *)klass; - - ssklass->summary_header_load = summary_header_load; - ssklass->summary_header_save = summary_header_save; - - /*ssklass->store_info_new = store_info_new;*/ - ssklass->store_info_load = store_info_load; - ssklass->store_info_save = store_info_save; - ssklass->store_info_free = store_info_free; - - ssklass->store_info_string = store_info_string; - ssklass->store_info_set_string = store_info_set_string; -} - -static void -camel_imap_store_summary_init (CamelImapStoreSummary *s) -{ - /*struct _CamelImapStoreSummaryPrivate *p; - - p = _PRIVATE(s) = g_malloc0(sizeof(*p));*/ - - ((CamelStoreSummary *)s)->store_info_size = sizeof(CamelImapStoreInfo); - s->version = CAMEL_IMAP_STORE_SUMMARY_VERSION; -} - -static void -camel_imap_store_summary_finalise (CamelObject *obj) -{ - /*struct _CamelImapStoreSummaryPrivate *p;*/ - /*CamelImapStoreSummary *s = (CamelImapStoreSummary *)obj;*/ - - /*p = _PRIVATE(obj); - g_free(p);*/ -} - -CamelType -camel_imap_store_summary_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - camel_imap_store_summary_parent = (CamelStoreSummaryClass *)camel_store_summary_get_type(); - type = camel_type_register((CamelType)camel_imap_store_summary_parent, "CamelImapStoreSummary", - sizeof (CamelImapStoreSummary), - sizeof (CamelImapStoreSummaryClass), - (CamelObjectClassInitFunc) camel_imap_store_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_imap_store_summary_init, - (CamelObjectFinalizeFunc) camel_imap_store_summary_finalise); - } - - return type; -} - -/** - * camel_imap_store_summary_new: - * - * Create a new CamelImapStoreSummary object. - * - * Return value: A new CamelImapStoreSummary widget. - **/ -CamelImapStoreSummary * -camel_imap_store_summary_new (void) -{ - CamelImapStoreSummary *new = CAMEL_IMAP_STORE_SUMMARY ( camel_object_new (camel_imap_store_summary_get_type ())); - - return new; -} - -/** - * camel_imap_store_summary_full_name: - * @s: - * @path: - * - * Retrieve a summary item by full name. - * - * A referenced to the summary item is returned, which may be - * ref'd or free'd as appropriate. - * - * Return value: The summary item, or NULL if the @full_name name - * is not available. - * It must be freed using camel_store_summary_info_free(). - **/ -CamelImapStoreInfo * -camel_imap_store_summary_full_name(CamelImapStoreSummary *s, const char *full_name) -{ - int count, i; - CamelImapStoreInfo *info; - - count = camel_store_summary_count((CamelStoreSummary *)s); - for (i=0;i<count;i++) { - info = (CamelImapStoreInfo *)camel_store_summary_index((CamelStoreSummary *)s, i); - if (info) { - if (strcmp(info->full_name, full_name) == 0) - return info; - camel_store_summary_info_free((CamelStoreSummary *)s, (CamelStoreInfo *)info); - } - } - - return NULL; -} - -char * -camel_imap_store_summary_full_to_path(CamelImapStoreSummary *s, const char *full_name, char dir_sep) -{ - char *path, *p; - int c; - const char *f; - - if (dir_sep != '/') { - p = path = alloca(strlen(full_name)*3+1); - f = full_name; - while ( (c = *f++ & 0xff) ) { - if (c == dir_sep) - *p++ = '/'; - else if (c == '/' || c == '%') - p += sprintf(p, "%%%02X", c); - else - *p++ = c; - } - *p = 0; - } else - path = (char *)full_name; - - return camel_utf7_utf8(path); -} - -static guint32 hexnib(guint32 c) -{ - if (c >= '0' && c <= '9') - return c-'0'; - else if (c>='A' && c <= 'Z') - return c-'A'+10; - else - return 0; -} - -char * -camel_imap_store_summary_path_to_full(CamelImapStoreSummary *s, const char *path, char dir_sep) -{ - unsigned char *full, *f; - guint32 c, v = 0; - const char *p; - int state=0; - char *subpath, *last = NULL; - CamelStoreInfo *si; - CamelImapStoreNamespace *ns; - - /* check to see if we have a subpath of path already defined */ - subpath = alloca(strlen(path)+1); - strcpy(subpath, path); - do { - si = camel_store_summary_path((CamelStoreSummary *)s, subpath); - if (si == NULL) { - last = strrchr(subpath, '/'); - if (last) - *last = 0; - } - } while (si == NULL && last); - - /* path is already present, use the raw version we have */ - if (si && strlen(subpath) == strlen(path)) { - f = g_strdup(camel_imap_store_info_full_name(s, si)); - camel_store_summary_info_free((CamelStoreSummary *)s, si); - return f; - } - - ns = camel_imap_store_summary_namespace_find_path(s, path); - - f = full = alloca(strlen(path)*2+1); - if (si) - p = path + strlen(subpath); - else if (ns) - p = path + strlen(ns->path); - else - p = path; - - while ( (c = camel_utf8_getc((const unsigned char **)&p)) ) { - switch(state) { - case 0: - if (c == '%') - state = 1; - else { - if (c == '/') - c = dir_sep; - camel_utf8_putc(&f, c); - } - break; - case 1: - state = 2; - v = hexnib(c)<<4; - break; - case 2: - state = 0; - v |= hexnib(c); - camel_utf8_putc(&f, v); - break; - } - } - camel_utf8_putc(&f, c); - - /* merge old path part if required */ - f = camel_utf8_utf7(full); - if (si) { - full = g_strdup_printf("%s%s", camel_imap_store_info_full_name(s, si), f); - g_free(f); - camel_store_summary_info_free((CamelStoreSummary *)s, si); - f = full; - } else if (ns) { - full = g_strdup_printf("%s%s", ns->full_name, f); - g_free(f); - f = full; - } - - return f; -} - -CamelImapStoreInfo * -camel_imap_store_summary_add_from_full(CamelImapStoreSummary *s, const char *full, char dir_sep) -{ - CamelImapStoreInfo *info; - char *pathu8, *prefix; - int len; - char *full_name; - CamelImapStoreNamespace *ns; - - d(printf("adding full name '%s' '%c'\n", full, dir_sep)); - - len = strlen(full); - full_name = alloca(len+1); - strcpy(full_name, full); - if (full_name[len-1] == dir_sep) - full_name[len-1] = 0; - - info = camel_imap_store_summary_full_name(s, full_name); - if (info) { - camel_store_summary_info_free((CamelStoreSummary *)s, (CamelStoreInfo *)info); - d(printf(" already there\n")); - return info; - } - - ns = camel_imap_store_summary_namespace_find_full(s, full_name); - if (ns) { - d(printf("(found namespace for '%s' ns '%s') ", full_name, ns->path)); - len = strlen(ns->full_name); - if (len >= strlen(full_name)) { - pathu8 = g_strdup(ns->path); - } else { - if (full_name[len] == ns->sep) - len++; - - prefix = camel_imap_store_summary_full_to_path(s, full_name+len, ns->sep); - if (*ns->path) { - pathu8 = g_strdup_printf ("%s/%s", ns->path, prefix); - g_free (prefix); - } else { - pathu8 = prefix; - } - } - d(printf(" (pathu8 = '%s')", pathu8)); - } else { - d(printf("(Cannot find namespace for '%s')\n", full_name)); - pathu8 = camel_imap_store_summary_full_to_path(s, full_name, dir_sep); - } - - info = (CamelImapStoreInfo *)camel_store_summary_add_from_path((CamelStoreSummary *)s, pathu8); - if (info) { - d(printf(" '%s' -> '%s'\n", pathu8, full_name)); - camel_store_info_set_string((CamelStoreSummary *)s, (CamelStoreInfo *)info, CAMEL_IMAP_STORE_INFO_FULL_NAME, full_name); - } else - d(printf(" failed\n")); - - return info; -} - -/* should this be const? */ -/* TODO: deprecate/merge this function with path_to_full */ -char * -camel_imap_store_summary_full_from_path(CamelImapStoreSummary *s, const char *path) -{ - CamelImapStoreNamespace *ns; - char *name = NULL; - - ns = camel_imap_store_summary_namespace_find_path(s, path); - if (ns) - name = camel_imap_store_summary_path_to_full(s, path, ns->sep); - - d(printf("looking up path %s -> %s\n", path, name?name:"not found")); - - return name; -} - -/* TODO: this api needs some more work */ -CamelImapStoreNamespace *camel_imap_store_summary_namespace_new(CamelImapStoreSummary *s, const char *full_name, char dir_sep) -{ - CamelImapStoreNamespace *ns; - char *p, *o, c; - int len; - - ns = g_malloc0(sizeof(*ns)); - ns->full_name = g_strdup(full_name); - len = strlen(ns->full_name)-1; - if (len >= 0 && ns->full_name[len] == dir_sep) - ns->full_name[len] = 0; - ns->sep = dir_sep; - - o = p = ns->path = camel_imap_store_summary_full_to_path(s, ns->full_name, dir_sep); - while ((c = *p++)) { - if (c != '#') { - if (c == '/') - c = '.'; - *o++ = c; - } - } - *o = 0; - - return ns; -} - -void camel_imap_store_summary_namespace_set(CamelImapStoreSummary *s, CamelImapStoreNamespace *ns) -{ - static void namespace_clear(CamelStoreSummary *s); - - d(printf("Setting namesapce to '%s' '%c' -> '%s'\n", ns->full_name, ns->sep, ns->path)); - namespace_clear((CamelStoreSummary *)s); - s->namespace = ns; - camel_store_summary_touch((CamelStoreSummary *)s); -} - -CamelImapStoreNamespace * -camel_imap_store_summary_namespace_find_path(CamelImapStoreSummary *s, const char *path) -{ - int len; - CamelImapStoreNamespace *ns; - - /* NB: this currently only compares against 1 namespace, in future compare against others */ - ns = s->namespace; - while (ns) { - len = strlen(ns->path); - if (len == 0 - || (strncmp(ns->path, path, len) == 0 - && (path[len] == '/' || path[len] == 0))) - break; - ns = NULL; - } - - /* have a default? */ - return ns; -} - -CamelImapStoreNamespace * -camel_imap_store_summary_namespace_find_full(CamelImapStoreSummary *s, const char *full) -{ - int len; - CamelImapStoreNamespace *ns; - - /* NB: this currently only compares against 1 namespace, in future compare against others */ - ns = s->namespace; - while (ns) { - len = strlen(ns->full_name); - d(printf("find_full: comparing namespace '%s' to name '%s'\n", ns->full_name, full)); - if (len == 0 - || (strncmp(ns->full_name, full, len) == 0 - && (full[len] == ns->sep || full[len] == 0))) - break; - ns = NULL; - } - - /* have a default? */ - return ns; -} - -static void -namespace_free(CamelStoreSummary *s, CamelImapStoreNamespace *ns) -{ - g_free(ns->path); - g_free(ns->full_name); - g_free(ns); -} - -static void -namespace_clear(CamelStoreSummary *s) -{ - CamelImapStoreSummary *is = (CamelImapStoreSummary *)s; - - if (is->namespace) - namespace_free(s, is->namespace); - is->namespace = NULL; -} - -static CamelImapStoreNamespace * -namespace_load(CamelStoreSummary *s, FILE *in) -{ - CamelImapStoreNamespace *ns; - guint32 sep = '/'; - - ns = g_malloc0(sizeof(*ns)); - if (camel_file_util_decode_string(in, &ns->path) == -1 - || camel_file_util_decode_string(in, &ns->full_name) == -1 - || camel_file_util_decode_uint32(in, &sep) == -1) { - namespace_free(s, ns); - ns = NULL; - } else { - ns->sep = sep; - } - - return ns; -} - -static int -namespace_save(CamelStoreSummary *s, FILE *in, CamelImapStoreNamespace *ns) -{ - if (camel_file_util_encode_string(in, ns->path) == -1 - || camel_file_util_encode_string(in, ns->full_name) == -1 - || camel_file_util_encode_uint32(in, (guint32)ns->sep) == -1) - return -1; - - return 0; -} - -static int -summary_header_load(CamelStoreSummary *s, FILE *in) -{ - CamelImapStoreSummary *is = (CamelImapStoreSummary *)s; - gint32 version, capabilities, count; - - namespace_clear(s); - - if (camel_imap_store_summary_parent->summary_header_load((CamelStoreSummary *)s, in) == -1 - || camel_file_util_decode_fixed_int32(in, &version) == -1) - return -1; - - is->version = version; - - if (version < CAMEL_IMAP_STORE_SUMMARY_VERSION_0) { - g_warning("Store summary header version too low"); - return -1; - } - - /* note file format can be expanded to contain more namespaces, but only 1 at the moment */ - if (camel_file_util_decode_fixed_int32(in, &capabilities) == -1 - || camel_file_util_decode_fixed_int32(in, &count) == -1 - || count > 1) - return -1; - - is->capabilities = capabilities; - if (count == 1) { - if ((is->namespace = namespace_load(s, in)) == NULL) - return -1; - } - - return 0; -} - -static int -summary_header_save(CamelStoreSummary *s, FILE *out) -{ - CamelImapStoreSummary *is = (CamelImapStoreSummary *)s; - guint32 count; - - count = is->namespace?1:0; - - /* always write as latest version */ - if (camel_imap_store_summary_parent->summary_header_save((CamelStoreSummary *)s, out) == -1 - || camel_file_util_encode_fixed_int32(out, CAMEL_IMAP_STORE_SUMMARY_VERSION) == -1 - || camel_file_util_encode_fixed_int32(out, is->capabilities) == -1 - || camel_file_util_encode_fixed_int32(out, count) == -1) - return -1; - - if (is->namespace && namespace_save(s, out, is->namespace) == -1) - return -1; - - return 0; -} - -static CamelStoreInfo * -store_info_load(CamelStoreSummary *s, FILE *in) -{ - CamelImapStoreInfo *mi; - - mi = (CamelImapStoreInfo *)camel_imap_store_summary_parent->store_info_load(s, in); - if (mi) { - if (camel_file_util_decode_string(in, &mi->full_name) == -1) { - camel_store_summary_info_free(s, (CamelStoreInfo *)mi); - mi = NULL; - } - } - - return (CamelStoreInfo *)mi; -} - -static int -store_info_save(CamelStoreSummary *s, FILE *out, CamelStoreInfo *mi) -{ - CamelImapStoreInfo *isi = (CamelImapStoreInfo *)mi; - - if (camel_imap_store_summary_parent->store_info_save(s, out, mi) == -1 - || camel_file_util_encode_string(out, isi->full_name) == -1) - return -1; - - return 0; -} - -static void -store_info_free(CamelStoreSummary *s, CamelStoreInfo *mi) -{ - CamelImapStoreInfo *isi = (CamelImapStoreInfo *)mi; - - g_free(isi->full_name); - camel_imap_store_summary_parent->store_info_free(s, mi); -} - -static const char * -store_info_string(CamelStoreSummary *s, const CamelStoreInfo *mi, int type) -{ - CamelImapStoreInfo *isi = (CamelImapStoreInfo *)mi; - - /* FIXME: Locks? */ - - g_assert (mi != NULL); - - switch (type) { - case CAMEL_IMAP_STORE_INFO_FULL_NAME: - return isi->full_name; - default: - return camel_imap_store_summary_parent->store_info_string(s, mi, type); - } -} - -static void -store_info_set_string(CamelStoreSummary *s, CamelStoreInfo *mi, int type, const char *str) -{ - CamelImapStoreInfo *isi = (CamelImapStoreInfo *)mi; - - g_assert(mi != NULL); - - switch(type) { - case CAMEL_IMAP_STORE_INFO_FULL_NAME: - d(printf("Set full name %s -> %s\n", isi->full_name, str)); - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - g_free(isi->full_name); - isi->full_name = g_strdup(str); - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); - break; - default: - camel_imap_store_summary_parent->store_info_set_string(s, mi, type, str); - break; - } -} diff --git a/camel/providers/imap/camel-imap-store-summary.h b/camel/providers/imap/camel-imap-store-summary.h deleted file mode 100644 index 0fa6be0df3..0000000000 --- a/camel/providers/imap/camel-imap-store-summary.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2002 Ximian Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef _CAMEL_IMAP_STORE_SUMMARY_H -#define _CAMEL_IMAP_STORE_SUMMARY_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include <camel/camel-object.h> -#include <camel/camel-store-summary.h> - -#define CAMEL_IMAP_STORE_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_imap_store_summary_get_type (), CamelImapStoreSummary) -#define CAMEL_IMAP_STORE_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imap_store_summary_get_type (), CamelImapStoreSummaryClass) -#define CAMEL_IS_IMAP_STORE_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_imap_store_summary_get_type ()) - -typedef struct _CamelImapStoreSummary CamelImapStoreSummary; -typedef struct _CamelImapStoreSummaryClass CamelImapStoreSummaryClass; - -typedef struct _CamelImapStoreInfo CamelImapStoreInfo; - -enum { - CAMEL_IMAP_STORE_INFO_FULL_NAME = CAMEL_STORE_INFO_LAST, - CAMEL_IMAP_STORE_INFO_LAST, -}; - -struct _CamelImapStoreInfo { - CamelStoreInfo info; - char *full_name; -}; - -typedef struct _CamelImapStoreNamespace CamelImapStoreNamespace; - -struct _CamelImapStoreNamespace { - char *path; /* display path */ - char *full_name; /* real name */ - char sep; /* directory separator */ -}; - -struct _CamelImapStoreSummary { - CamelStoreSummary summary; - - struct _CamelImapStoreSummaryPrivate *priv; - - /* header info */ - guint32 version; /* version of base part of file */ - guint32 capabilities; - CamelImapStoreNamespace *namespace; /* eventually to be a list */ -}; - -struct _CamelImapStoreSummaryClass { - CamelStoreSummaryClass summary_class; -}; - -CamelType camel_imap_store_summary_get_type (void); -CamelImapStoreSummary *camel_imap_store_summary_new (void); - -/* TODO: this api needs some more work, needs to support lists */ -CamelImapStoreNamespace *camel_imap_store_summary_namespace_new(CamelImapStoreSummary *s, const char *full_name, char dir_sep); -void camel_imap_store_summary_namespace_set(CamelImapStoreSummary *s, CamelImapStoreNamespace *ns); -CamelImapStoreNamespace *camel_imap_store_summary_namespace_find_path(CamelImapStoreSummary *s, const char *path); -CamelImapStoreNamespace *camel_imap_store_summary_namespace_find_full(CamelImapStoreSummary *s, const char *full_name); - -/* converts to/from utf8 canonical nasmes */ -char *camel_imap_store_summary_full_to_path(CamelImapStoreSummary *s, const char *full_name, char dir_sep); -char *camel_imap_store_summary_path_to_full(CamelImapStoreSummary *s, const char *path, char dir_sep); - -CamelImapStoreInfo *camel_imap_store_summary_full_name(CamelImapStoreSummary *s, const char *full_name); -CamelImapStoreInfo *camel_imap_store_summary_add_from_full(CamelImapStoreSummary *s, const char *full_name, char dir_sep); - -/* a convenience lookup function. always use this if path known */ -char *camel_imap_store_summary_full_from_path(CamelImapStoreSummary *s, const char *path); - -/* helper macro's */ -#define camel_imap_store_info_full_name(s, i) (camel_store_info_string((CamelStoreSummary *)s, (const CamelStoreInfo *)i, CAMEL_IMAP_STORE_INFO_FULL_NAME)) - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_IMAP_STORE_SUMMARY_H */ diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c deleted file mode 100644 index 5811b0f691..0000000000 --- a/camel/providers/imap/camel-imap-store.c +++ /dev/null @@ -1,3229 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-store.c : class for an imap store */ - -/* - * Authors: - * Dan Winship <danw@ximian.com> - * Jeffrey Stedfast <fejj@ximian.com> - * - * Copyright 2000, 2003 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -#include "camel-imap-store.h" -#include "camel-imap-store-summary.h" -#include "camel-imap-folder.h" -#include "camel-imap-utils.h" -#include "camel-imap-command.h" -#include "camel-imap-summary.h" -#include "camel-imap-message-cache.h" -#include "camel-disco-diary.h" -#include "camel-file-utils.h" -#include "camel-folder.h" -#include "camel-exception.h" -#include "camel-session.h" -#include "camel-stream.h" -#include "camel-stream-buffer.h" -#include "camel-stream-fs.h" -#include "camel-stream-process.h" -#include "camel-tcp-stream-raw.h" -#include "camel-tcp-stream-ssl.h" -#include "camel-url.h" -#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) - -/* Specified in RFC 2060 */ -#define IMAP_PORT "143" -#define IMAPS_PORT "993" - -static CamelDiscoStoreClass *parent_class = NULL; - -static char imap_tag_prefix = 'A'; - -static void construct (CamelService *service, CamelSession *session, - CamelProvider *provider, CamelURL *url, - CamelException *ex); - -static int imap_setv (CamelObject *object, CamelException *ex, CamelArgV *args); -static int imap_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args); - -static char *imap_get_name (CamelService *service, gboolean brief); - -static gboolean can_work_offline (CamelDiscoStore *disco_store); -static gboolean imap_connect_online (CamelService *service, CamelException *ex); -static gboolean imap_connect_offline (CamelService *service, CamelException *ex); -static gboolean imap_disconnect_online (CamelService *service, gboolean clean, CamelException *ex); -static gboolean imap_disconnect_offline (CamelService *service, gboolean clean, CamelException *ex); -static void imap_noop (CamelStore *store, CamelException *ex); -static CamelFolder *imap_get_junk(CamelStore *store, CamelException *ex); -static CamelFolder *imap_get_trash(CamelStore *store, CamelException *ex); -static GList *query_auth_types (CamelService *service, CamelException *ex); -static guint hash_folder_name (gconstpointer key); -static gint compare_folder_name (gconstpointer a, gconstpointer b); -static CamelFolder *get_folder_online (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex); -static CamelFolder *get_folder_offline (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex); - -static CamelFolderInfo *create_folder (CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex); -static void delete_folder (CamelStore *store, const char *folder_name, CamelException *ex); -static void rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex); -static CamelFolderInfo *get_folder_info_online (CamelStore *store, - const char *top, - guint32 flags, - CamelException *ex); -static CamelFolderInfo *get_folder_info_offline (CamelStore *store, - const char *top, - guint32 flags, - CamelException *ex); -static gboolean folder_subscribed (CamelStore *store, const char *folder_name); -static void subscribe_folder (CamelStore *store, const char *folder_name, - CamelException *ex); -static void unsubscribe_folder (CamelStore *store, const char *folder_name, - CamelException *ex); - -static void get_folders_online (CamelImapStore *imap_store, const char *pattern, - GPtrArray *folders, gboolean lsub, CamelException *ex); - - -static void imap_folder_effectively_unsubscribed(CamelImapStore *imap_store, const char *folder_name, CamelException *ex); -static gboolean imap_check_folder_still_extant (CamelImapStore *imap_store, const char *full_name, CamelException *ex); -static void imap_forget_folder(CamelImapStore *imap_store, const char *folder_name, CamelException *ex); -static void imap_set_server_level (CamelImapStore *store); - -static void -camel_imap_store_class_init (CamelImapStoreClass *camel_imap_store_class) -{ - CamelObjectClass *camel_object_class = - CAMEL_OBJECT_CLASS (camel_imap_store_class); - CamelServiceClass *camel_service_class = - CAMEL_SERVICE_CLASS (camel_imap_store_class); - CamelStoreClass *camel_store_class = - CAMEL_STORE_CLASS (camel_imap_store_class); - CamelDiscoStoreClass *camel_disco_store_class = - CAMEL_DISCO_STORE_CLASS (camel_imap_store_class); - - parent_class = CAMEL_DISCO_STORE_CLASS (camel_type_get_global_classfuncs (camel_disco_store_get_type ())); - - /* virtual method overload */ - camel_object_class->setv = imap_setv; - camel_object_class->getv = imap_getv; - - camel_service_class->construct = construct; - camel_service_class->query_auth_types = query_auth_types; - camel_service_class->get_name = imap_get_name; - - camel_store_class->hash_folder_name = hash_folder_name; - camel_store_class->compare_folder_name = compare_folder_name; - camel_store_class->create_folder = create_folder; - camel_store_class->delete_folder = delete_folder; - camel_store_class->rename_folder = rename_folder; - camel_store_class->free_folder_info = camel_store_free_folder_info_full; - camel_store_class->folder_subscribed = folder_subscribed; - camel_store_class->subscribe_folder = subscribe_folder; - camel_store_class->unsubscribe_folder = unsubscribe_folder; - camel_store_class->noop = imap_noop; - camel_store_class->get_trash = imap_get_trash; - camel_store_class->get_junk = imap_get_junk; - - camel_disco_store_class->can_work_offline = can_work_offline; - camel_disco_store_class->connect_online = imap_connect_online; - camel_disco_store_class->connect_offline = imap_connect_offline; - camel_disco_store_class->disconnect_online = imap_disconnect_online; - camel_disco_store_class->disconnect_offline = imap_disconnect_offline; - camel_disco_store_class->get_folder_online = get_folder_online; - camel_disco_store_class->get_folder_offline = get_folder_offline; - camel_disco_store_class->get_folder_resyncing = get_folder_online; - camel_disco_store_class->get_folder_info_online = get_folder_info_online; - camel_disco_store_class->get_folder_info_offline = get_folder_info_offline; - camel_disco_store_class->get_folder_info_resyncing = get_folder_info_online; -} - -static gboolean -free_key (gpointer key, gpointer value, gpointer user_data) -{ - g_free (key); - return TRUE; -} - -static void -camel_imap_store_finalize (CamelObject *object) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (object); - - /* This frees current_folder, folders, authtypes, streams, and namespace. */ - camel_service_disconnect((CamelService *)imap_store, TRUE, NULL); - - if (imap_store->summary) { - camel_store_summary_save((CamelStoreSummary *)imap_store->summary); - camel_object_unref(imap_store->summary); - } - - if (imap_store->base_url) - g_free (imap_store->base_url); - if (imap_store->storage_path) - g_free (imap_store->storage_path); -} - -static void -camel_imap_store_init (gpointer object, gpointer klass) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (object); - - imap_store->istream = NULL; - imap_store->ostream = NULL; - - imap_store->dir_sep = '\0'; - imap_store->current_folder = NULL; - imap_store->connected = FALSE; - imap_store->preauthed = FALSE; - - imap_store->tag_prefix = imap_tag_prefix++; - if (imap_tag_prefix > 'Z') - imap_tag_prefix = 'A'; -} - -CamelType -camel_imap_store_get_type (void) -{ - static CamelType camel_imap_store_type = CAMEL_INVALID_TYPE; - - if (camel_imap_store_type == CAMEL_INVALID_TYPE) { - camel_imap_store_type = - camel_type_register (CAMEL_DISCO_STORE_TYPE, - "CamelImapStore", - sizeof (CamelImapStore), - sizeof (CamelImapStoreClass), - (CamelObjectClassInitFunc) camel_imap_store_class_init, - NULL, - (CamelObjectInitFunc) camel_imap_store_init, - (CamelObjectFinalizeFunc) camel_imap_store_finalize); - } - - return camel_imap_store_type; -} - -static void -construct (CamelService *service, CamelSession *session, - CamelProvider *provider, CamelURL *url, - CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (service); - CamelStore *store = CAMEL_STORE (service); - char *tmp; - CamelURL *summary_url; - - CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); - if (camel_exception_is_set (ex)) - return; - - imap_store->storage_path = camel_session_get_storage_path (session, service, ex); - if (!imap_store->storage_path) - return; - - /* FIXME */ - imap_store->base_url = camel_url_to_string (service->url, (CAMEL_URL_HIDE_PASSWORD | - CAMEL_URL_HIDE_PARAMS | - CAMEL_URL_HIDE_AUTH)); - - imap_store->parameters = 0; - if (camel_url_get_param (url, "use_lsub")) - store->flags |= CAMEL_STORE_SUBSCRIPTIONS; - if (camel_url_get_param (url, "namespace")) { - imap_store->parameters |= IMAP_PARAM_OVERRIDE_NAMESPACE; - g_free(imap_store->namespace); - imap_store->namespace = g_strdup (camel_url_get_param (url, "namespace")); - } - if (camel_url_get_param (url, "check_all")) - imap_store->parameters |= IMAP_PARAM_CHECK_ALL; - if (camel_url_get_param (url, "filter")) { - imap_store->parameters |= IMAP_PARAM_FILTER_INBOX; - store->flags |= CAMEL_STORE_FILTER_INBOX; - } - if (camel_url_get_param (url, "filter_junk")) - imap_store->parameters |= IMAP_PARAM_FILTER_JUNK; - if (camel_url_get_param (url, "filter_junk_inbox")) - imap_store->parameters |= IMAP_PARAM_FILTER_JUNK_INBOX; - - /* setup/load the store summary */ - tmp = alloca(strlen(imap_store->storage_path)+32); - sprintf(tmp, "%s/.ev-store-summary", imap_store->storage_path); - imap_store->summary = camel_imap_store_summary_new(); - camel_store_summary_set_filename((CamelStoreSummary *)imap_store->summary, tmp); - summary_url = camel_url_new(imap_store->base_url, NULL); - camel_store_summary_set_uri_base((CamelStoreSummary *)imap_store->summary, summary_url); - camel_url_free(summary_url); - if (camel_store_summary_load((CamelStoreSummary *)imap_store->summary) == 0) { - CamelImapStoreSummary *is = imap_store->summary; - - if (is->namespace) { - /* if namespace has changed, clear folder list */ - if (imap_store->namespace && strcmp(imap_store->namespace, is->namespace->full_name) != 0) { - camel_store_summary_clear((CamelStoreSummary *)is); - } else { - imap_store->namespace = g_strdup(is->namespace->full_name); - imap_store->dir_sep = is->namespace->sep; - } - } - - imap_store->capabilities = is->capabilities; - imap_set_server_level(imap_store); - } -} - -static int -imap_setv (CamelObject *object, CamelException *ex, CamelArgV *args) -{ - CamelImapStore *store = (CamelImapStore *) object; - guint32 tag, flags; - int i; - - for (i = 0; i < args->argc; i++) { - tag = args->argv[i].tag; - - /* make sure this is an arg we're supposed to handle */ - if ((tag & CAMEL_ARG_TAG) <= CAMEL_IMAP_STORE_ARG_FIRST || - (tag & CAMEL_ARG_TAG) >= CAMEL_IMAP_STORE_ARG_FIRST + 100) - continue; - - switch (tag) { - case CAMEL_IMAP_STORE_NAMESPACE: - if (strcmp (store->namespace, args->argv[i].ca_str) != 0) { - g_free (store->namespace); - store->namespace = g_strdup (args->argv[i].ca_str); - /* the current imap code will need to do a reconnect for this to take effect */ - /*reconnect = TRUE;*/ - } - break; - case CAMEL_IMAP_STORE_OVERRIDE_NAMESPACE: - flags = args->argv[i].ca_int ? IMAP_PARAM_OVERRIDE_NAMESPACE : 0; - flags |= (store->parameters & ~IMAP_PARAM_OVERRIDE_NAMESPACE); - - if (store->parameters != flags) { - store->parameters = flags; - /* the current imap code will need to do a reconnect for this to take effect */ - /*reconnect = TRUE;*/ - } - break; - case CAMEL_IMAP_STORE_CHECK_ALL: - flags = args->argv[i].ca_int ? IMAP_PARAM_CHECK_ALL : 0; - flags |= (store->parameters & ~IMAP_PARAM_CHECK_ALL); - store->parameters = flags; - /* no need to reconnect for this option to take effect... */ - break; - case CAMEL_IMAP_STORE_FILTER_INBOX: - flags = args->argv[i].ca_int ? IMAP_PARAM_FILTER_INBOX : 0; - flags |= (store->parameters & ~IMAP_PARAM_FILTER_INBOX); - store->parameters = flags; - /* no need to reconnect for this option to take effect... */ - break; - case CAMEL_IMAP_STORE_FILTER_JUNK: - flags = args->argv[i].ca_int ? IMAP_PARAM_FILTER_JUNK : 0; - store->parameters = flags | (store->parameters & ~IMAP_PARAM_FILTER_JUNK); - break; - case CAMEL_IMAP_STORE_FILTER_JUNK_INBOX: - flags = args->argv[i].ca_int ? IMAP_PARAM_FILTER_JUNK_INBOX : 0; - store->parameters = flags | (store->parameters & ~IMAP_PARAM_FILTER_JUNK_INBOX); - break; - default: - /* error?? */ - continue; - } - - /* let our parent know that we've handled this arg */ - camel_argv_ignore (args, i); - } - - /* FIXME: if we need to reconnect for a change to take affect, - we need to do it here... or, better yet, somehow chain it - up to CamelService's setv implementation. */ - - return CAMEL_OBJECT_CLASS (parent_class)->setv (object, ex, args); -} - -static int -imap_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args) -{ - CamelImapStore *store = (CamelImapStore *) object; - guint32 tag; - int i; - - for (i = 0; i < args->argc; i++) { - tag = args->argv[i].tag; - - /* make sure this is an arg we're supposed to handle */ - if ((tag & CAMEL_ARG_TAG) <= CAMEL_IMAP_STORE_ARG_FIRST || - (tag & CAMEL_ARG_TAG) >= CAMEL_IMAP_STORE_ARG_FIRST + 100) - continue; - - switch (tag) { - case CAMEL_IMAP_STORE_NAMESPACE: - *args->argv[i].ca_str = store->namespace; - break; - case CAMEL_IMAP_STORE_OVERRIDE_NAMESPACE: - *args->argv[i].ca_int = store->parameters & IMAP_PARAM_OVERRIDE_NAMESPACE ? TRUE : FALSE; - break; - case CAMEL_IMAP_STORE_CHECK_ALL: - *args->argv[i].ca_int = store->parameters & IMAP_PARAM_CHECK_ALL ? TRUE : FALSE; - break; - case CAMEL_IMAP_STORE_FILTER_INBOX: - *args->argv[i].ca_int = store->parameters & IMAP_PARAM_FILTER_INBOX ? TRUE : FALSE; - break; - case CAMEL_IMAP_STORE_FILTER_JUNK: - *args->argv[i].ca_int = store->parameters & IMAP_PARAM_FILTER_JUNK ? TRUE : FALSE; - break; - case CAMEL_IMAP_STORE_FILTER_JUNK_INBOX: - *args->argv[i].ca_int = store->parameters & IMAP_PARAM_FILTER_JUNK_INBOX ? TRUE : FALSE; - break; - default: - /* error? */ - break; - } - } - - return CAMEL_OBJECT_CLASS (parent_class)->getv (object, ex, args); -} - -static char * -imap_get_name (CamelService *service, gboolean brief) -{ - if (brief) - return g_strdup_printf (_("IMAP server %s"), service->url->host); - else - return g_strdup_printf (_("IMAP service for %s on %s"), - service->url->user, service->url->host); -} - -static void -imap_set_server_level (CamelImapStore *store) -{ - if (store->capabilities & IMAP_CAPABILITY_IMAP4REV1) { - store->server_level = IMAP_LEVEL_IMAP4REV1; - store->capabilities |= IMAP_CAPABILITY_STATUS; - } else if (store->capabilities & IMAP_CAPABILITY_IMAP4) - store->server_level = IMAP_LEVEL_IMAP4; - else - store->server_level = IMAP_LEVEL_UNKNOWN; -} - -static struct { - const char *name; - guint32 flag; -} capabilities[] = { - { "IMAP4", IMAP_CAPABILITY_IMAP4 }, - { "IMAP4REV1", IMAP_CAPABILITY_IMAP4REV1 }, - { "STATUS", IMAP_CAPABILITY_STATUS }, - { "NAMESPACE", IMAP_CAPABILITY_NAMESPACE }, - { "UIDPLUS", IMAP_CAPABILITY_UIDPLUS }, - { "LITERAL+", IMAP_CAPABILITY_LITERALPLUS }, - { "STARTTLS", IMAP_CAPABILITY_STARTTLS }, - { NULL, 0 } -}; - -static gboolean -imap_get_capability (CamelService *service, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelImapResponse *response; - char *result, *capa, *lasts; - int i; - - CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock); - - /* Find out the IMAP capabilities */ - /* We assume we have utf8 capable search until a failed search tells us otherwise */ - store->capabilities = IMAP_CAPABILITY_utf8_search; - store->authtypes = g_hash_table_new (g_str_hash, g_str_equal); - response = camel_imap_command (store, NULL, ex, "CAPABILITY"); - if (!response) - return FALSE; - result = camel_imap_response_extract (store, response, "CAPABILITY ", ex); - if (!result) - return FALSE; - - /* Skip over "* CAPABILITY ". */ - capa = result + 13; - for (capa = strtok_r (capa, " ", &lasts); capa; - capa = strtok_r (NULL, " ", &lasts)) { - if (!strncmp (capa, "AUTH=", 5)) { - g_hash_table_insert (store->authtypes, - g_strdup (capa + 5), - GINT_TO_POINTER (1)); - continue; - } - for (i = 0; capabilities[i].name; i++) { - if (g_ascii_strcasecmp (capa, capabilities[i].name) == 0) { - store->capabilities |= capabilities[i].flag; - break; - } - } - } - g_free (result); - - imap_set_server_level (store); - - if (store->summary->capabilities != store->capabilities) { - store->summary->capabilities = store->capabilities; - camel_store_summary_touch((CamelStoreSummary *)store->summary); - camel_store_summary_save((CamelStoreSummary *)store->summary); - } - - return TRUE; -} - -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) -{ - CamelImapStore *store = (CamelImapStore *) service; - CamelImapResponse *response; - CamelStream *tcp_stream; - CamelSockOptData sockopt; - gboolean force_imap4 = FALSE; - int clean_quit, ret; - char *buf; - - 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); - } else { - 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")); - - return FALSE; -#endif /* HAVE_SSL */ - } else { - tcp_stream = camel_tcp_stream_raw_new (); - } - - 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)); - - camel_object_unref (tcp_stream); - - return FALSE; - } - - store->ostream = tcp_stream; - store->istream = camel_stream_buffer_new (tcp_stream, CAMEL_STREAM_BUFFER_READ); - - store->connected = TRUE; - store->preauthed = FALSE; - store->command = 0; - - /* Disable Nagle - we send a lot of small requests which nagle slows down */ - sockopt.option = CAMEL_SOCKOPT_NODELAY; - sockopt.value.no_delay = TRUE; - camel_tcp_stream_setsockopt((CamelTcpStream *)tcp_stream, &sockopt); - - /* Set keepalive - needed for some hosts/router configurations, we're idle a lot */ - sockopt.option = CAMEL_SOCKOPT_KEEPALIVE; - sockopt.value.keep_alive = TRUE; - camel_tcp_stream_setsockopt((CamelTcpStream *)tcp_stream, &sockopt); - - /* Read the greeting, if any, and deal with PREAUTH */ - if (camel_imap_store_readline (store, &buf, ex) < 0) { - if (store->istream) { - camel_object_unref (store->istream); - store->istream = NULL; - } - - if (store->ostream) { - camel_object_unref (store->ostream); - store->ostream = NULL; - } - - store->connected = FALSE; - - return FALSE; - } - - if (!strncmp(buf, "* PREAUTH", 9)) - store->preauthed = TRUE; - - if (strstr (buf, "Courier-IMAP")) { - /* 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 - * MIME parser sucks. In any event, we can't rely on - * them so we always have to request the full messages - * rather than getting individual parts. */ - store->braindamaged = TRUE; - } else if (strstr (buf, "WEB.DE") || strstr (buf, "Mail2World")) { - /* This is a workaround for servers which advertise - * IMAP4rev1 but which can sometimes subtly break in - * various ways if we try to use IMAP4rev1 queries. - * - * WEB.DE: when querying for HEADER.FIELDS.NOT, it - * returns an empty literal for the headers. Many - * complaints about empty message-list fields on the - * mailing lists and probably a few bugzilla bugs as - * well. - * - * Mail2World (aka NamePlanet): When requesting - * message info's, it ignores the fact that we - * requested BODY.PEEK[HEADER.FIELDS.NOT (RECEIVED)] - * and so the responses are incomplete. See bug #58766 - * for details. - **/ - force_imap4 = TRUE; - } - - g_free (buf); - - /* get the imap server capabilities */ - if (!imap_get_capability (service, ex)) { - if (store->istream) { - camel_object_unref (store->istream); - store->istream = NULL; - } - - if (store->ostream) { - camel_object_unref (store->ostream); - store->ostream = NULL; - } - - store->connected = FALSE; - return FALSE; - } - - if (force_imap4) { - store->capabilities &= ~IMAP_CAPABILITY_IMAP4REV1; - store->server_level = IMAP_LEVEL_IMAP4; - } - - if (ssl_mode != MODE_TLS) { - /* we're done */ - return TRUE; - } - - 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; - } - - /* as soon as we send a STARTTLS command, all hope is lost of a clean QUIT if problems arise */ - clean_quit = FALSE; - - response = camel_imap_command (store, NULL, ex, "STARTTLS"); - if (!response) { - camel_object_unref (store->istream); - camel_object_unref (store->ostream); - store->istream = store->ostream = NULL; - return FALSE; - } - - camel_imap_response_free_without_processing (store, response); - - /* Okay, now toggle SSL/TLS mode */ - if (camel_tcp_stream_ssl_enable_ssl (CAMEL_TCP_STREAM_SSL (tcp_stream)) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to IMAP server %s in secure mode: %s"), - service->url->host, _("SSL negotiations failed")); - goto exception; - } - - /* rfc2595, section 4 states that after a successful STLS - command, the client MUST discard prior CAPA responses */ - if (!imap_get_capability (service, ex)) { - if (store->istream) { - camel_object_unref (store->istream); - store->istream = NULL; - } - - if (store->ostream) { - camel_object_unref (store->ostream); - store->ostream = NULL; - } - - store->connected = FALSE; - - return FALSE; - } - - return TRUE; - - exception: - - if (clean_quit && store->connected) { - /* try to disconnect cleanly */ - response = camel_imap_command (store, NULL, ex, "LOGOUT"); - if (response) - camel_imap_response_free_without_processing (store, response); - } - - if (store->istream) { - camel_object_unref (store->istream); - store->istream = NULL; - } - - if (store->ostream) { - camel_object_unref (store->ostream); - store->ostream = NULL; - } - - store->connected = FALSE; - - return FALSE; -} - -static gboolean -connect_to_server_process (CamelService *service, const char *cmd, CamelException *ex) -{ - CamelImapStore *store = (CamelImapStore *) service; - CamelStream *cmd_stream; - int ret, i = 0; - char *buf; - char *cmd_copy; - char *full_cmd; - char *child_env[7]; - - /* Put full details in the environment, in case the connection - program needs them */ - buf = camel_url_to_string(service->url, 0); - child_env[i++] = g_strdup_printf("URL=%s", buf); - g_free(buf); - - child_env[i++] = g_strdup_printf("URLHOST=%s", service->url->host); - if (service->url->port) - child_env[i++] = g_strdup_printf("URLPORT=%d", service->url->port); - if (service->url->user) - child_env[i++] = g_strdup_printf("URLUSER=%s", service->url->user); - if (service->url->passwd) - child_env[i++] = g_strdup_printf("URLPASSWD=%s", service->url->passwd); - if (service->url->path) - child_env[i++] = g_strdup_printf("URLPATH=%s", service->url->path); - child_env[i] = NULL; - - /* Now do %h, %u, etc. substitution in cmd */ - buf = cmd_copy = g_strdup(cmd); - - full_cmd = g_strdup(""); - - for(;;) { - char *pc; - char *tmp; - char *var; - int len; - - pc = strchr(buf, '%'); - ignore: - if (!pc) { - tmp = g_strdup_printf("%s%s", full_cmd, buf); - g_free(full_cmd); - full_cmd = tmp; - break; - } - - len = pc - buf; - - var = NULL; - - switch(pc[1]) { - case 'h': - var = service->url->host; - break; - case 'u': - var = service->url->user; - break; - } - if (!var) { - /* If there wasn't a valid %-code, with an actual - variable to insert, pretend we didn't see the % */ - pc = strchr(pc + 1, '%'); - goto ignore; - } - tmp = g_strdup_printf("%s%.*s%s", full_cmd, len, buf, var); - g_free(full_cmd); - full_cmd = tmp; - buf = pc + 2; - } - - g_free(cmd_copy); - - cmd_stream = camel_stream_process_new (); - - ret = camel_stream_process_connect (CAMEL_STREAM_PROCESS(cmd_stream), - full_cmd, (const char **)child_env); - - while (i) - g_free(child_env[--i]); - - 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 with command \"%s\": %s"), - full_cmd, g_strerror (errno)); - - camel_object_unref (cmd_stream); - g_free (full_cmd); - return FALSE; - } - g_free (full_cmd); - - store->ostream = cmd_stream; - store->istream = camel_stream_buffer_new (cmd_stream, CAMEL_STREAM_BUFFER_READ); - - store->connected = TRUE; - store->preauthed = FALSE; - store->command = 0; - - /* Read the greeting, if any, and deal with PREAUTH */ - if (camel_imap_store_readline (store, &buf, ex) < 0) { - if (store->istream) { - camel_object_unref (store->istream); - store->istream = NULL; - } - - if (store->ostream) { - camel_object_unref (store->ostream); - store->ostream = NULL; - } - - store->connected = FALSE; - return FALSE; - } - if (!strncmp(buf, "* PREAUTH", 9)) - store->preauthed = TRUE; - g_free (buf); - - /* get the imap server capabilities */ - if (!imap_get_capability (service, ex)) { - if (store->istream) { - camel_object_unref (store->istream); - store->istream = NULL; - } - - if (store->ostream) { - camel_object_unref (store->ostream); - store->ostream = NULL; - } - - store->connected = FALSE; - return FALSE; - } - - return TRUE; - -} - -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 }, -}; - -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"))) - return connect_to_server_process (service, command, ex); - - 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 = "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); - } - - camel_freeaddrinfo (ai); - - return ret; -} - -extern CamelServiceAuthType camel_imap_password_authtype; - -static GList * -query_auth_types (CamelService *service, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelServiceAuthType *authtype; - GList *sasl_types, *t, *next; - gboolean connected; - - if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex)) - return NULL; - - CAMEL_SERVICE_LOCK (store, connect_lock); - connected = connect_to_server_wrapper (service, ex); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - if (!connected) - return NULL; - - sasl_types = camel_sasl_authtype_list (FALSE); - for (t = sasl_types; t; t = next) { - authtype = t->data; - next = t->next; - - if (!g_hash_table_lookup (store->authtypes, authtype->authproto)) { - sasl_types = g_list_remove_link (sasl_types, t); - g_list_free_1 (t); - } - } - - return g_list_prepend (sasl_types, &camel_imap_password_authtype); -} - -/* folder_name is path name */ -static CamelFolderInfo * -imap_build_folder_info(CamelImapStore *imap_store, const char *folder_name) -{ - CamelURL *url; - const char *name; - CamelFolderInfo *fi; - - fi = g_malloc0(sizeof(*fi)); - - fi->full_name = g_strdup(folder_name); - fi->unread = 0; - fi->total = 0; - - url = camel_url_new (imap_store->base_url, NULL); - g_free (url->path); - url->path = g_strdup_printf ("/%s", folder_name); - fi->uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - camel_url_free(url); - name = strrchr (fi->full_name, '/'); - if (name == NULL) - name = fi->full_name; - else - name++; - fi->name = g_strdup (name); - - return fi; -} - -static void -imap_folder_effectively_unsubscribed(CamelImapStore *imap_store, - const char *folder_name, CamelException *ex) -{ - CamelFolderInfo *fi; - CamelStoreInfo *si; - - si = camel_store_summary_path((CamelStoreSummary *)imap_store->summary, folder_name); - if (si) { - if (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) { - si->flags &= ~CAMEL_STORE_INFO_FOLDER_SUBSCRIBED; - camel_store_summary_touch((CamelStoreSummary *)imap_store->summary); - camel_store_summary_save((CamelStoreSummary *)imap_store->summary); - } - camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si); - } - - if (imap_store->renaming) { - /* we don't need to emit a "folder_unsubscribed" signal - if we are in the process of renaming folders, so we - are done here... */ - return; - - } - - fi = imap_build_folder_info(imap_store, folder_name); - camel_object_trigger_event (CAMEL_OBJECT (imap_store), "folder_unsubscribed", fi); - camel_folder_info_free (fi); -} - -static void -imap_forget_folder (CamelImapStore *imap_store, const char *folder_name, CamelException *ex) -{ - CamelFolderSummary *summary; - CamelImapMessageCache *cache; - char *summary_file, *state_file; - char *journal_file; - char *folder_dir, *storage_path; - CamelFolderInfo *fi; - const char *name; - - name = strrchr (folder_name, imap_store->dir_sep); - if (name) - name++; - else - name = folder_name; - - storage_path = g_strdup_printf ("%s/folders", imap_store->storage_path); - folder_dir = imap_path_to_physical (storage_path, folder_name); - g_free (storage_path); - if (access (folder_dir, F_OK) != 0) { - g_free (folder_dir); - goto event; - } - - summary_file = g_strdup_printf ("%s/summary", folder_dir); - summary = camel_imap_summary_new (NULL, summary_file); - if (!summary) { - g_free (summary_file); - g_free (folder_dir); - goto event; - } - - cache = camel_imap_message_cache_new (folder_dir, summary, ex); - if (cache) - camel_imap_message_cache_clear (cache); - - camel_object_unref (cache); - camel_object_unref (summary); - - unlink (summary_file); - g_free (summary_file); - - journal_file = g_strdup_printf ("%s/journal", folder_dir); - unlink (journal_file); - g_free (journal_file); - - state_file = g_strdup_printf ("%s/cmeta", folder_dir); - unlink (state_file); - g_free (state_file); - - rmdir (folder_dir); - g_free (folder_dir); - - event: - - camel_store_summary_remove_path((CamelStoreSummary *)imap_store->summary, folder_name); - camel_store_summary_save((CamelStoreSummary *)imap_store->summary); - - fi = imap_build_folder_info(imap_store, folder_name); - camel_object_trigger_event (CAMEL_OBJECT (imap_store), "folder_deleted", fi); - camel_folder_info_free (fi); -} - -static gboolean -imap_check_folder_still_extant (CamelImapStore *imap_store, const char *full_name, - CamelException *ex) -{ - CamelImapResponse *response; - - response = camel_imap_command (imap_store, NULL, ex, "LIST \"\" %F", - full_name); - - if (response) { - gboolean stillthere = response->untagged->len != 0; - - camel_imap_response_free_without_processing (imap_store, response); - - return stillthere; - } - - /* if the command was rejected, there must be some other error, - assume it worked so we dont blow away the folder unecessarily */ - return TRUE; -} - -/* This is a little 'hack' to avoid the deadlock conditions that would otherwise - ensue when calling camel_folder_refresh_info from inside a lock */ -/* NB: on second thougts this is probably not entirely safe, but it'll do for now */ -/* No, its definetly not safe. So its been changed to copy the folders first */ -/* the alternative is to: - make the camel folder->lock recursive (which should probably be done) - or remove it from camel_folder_refresh_info, and use another locking mechanism */ -/* also see get_folder_info_online() for the same hack repeated */ -static void -imap_store_refresh_folders (CamelImapStore *store, CamelException *ex) -{ - GPtrArray *folders; - int i; - - folders = camel_object_bag_list(CAMEL_STORE (store)->folders); - - for (i = 0; i <folders->len; i++) { - CamelFolder *folder = folders->pdata[i]; - - /* NB: we can have vtrash folders also in our store ... bit hacky */ - if (!CAMEL_IS_IMAP_FOLDER(folder)) { - camel_object_unref(folder); - continue; - } - - CAMEL_IMAP_FOLDER (folder)->need_rescan = TRUE; - if (!camel_exception_is_set(ex)) - CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(folder))->refresh_info(folder, ex); - - if (camel_exception_is_set (ex) && - imap_check_folder_still_extant (store, folder->full_name, ex) == FALSE) { - gchar *namedup; - - /* the folder was deleted (may happen when we come back online - * after being offline */ - - namedup = g_strdup (folder->full_name); - camel_object_unref(folder); - imap_folder_effectively_unsubscribed (store, namedup, ex); - imap_forget_folder (store, namedup, ex); - g_free (namedup); - } else - camel_object_unref(folder); - } - - g_ptr_array_free (folders, TRUE); -} - -static gboolean -try_auth (CamelImapStore *store, const char *mech, CamelException *ex) -{ - CamelSasl *sasl; - CamelImapResponse *response; - char *resp; - char *sasl_resp; - - CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock); - - response = camel_imap_command (store, NULL, ex, "AUTHENTICATE %s", mech); - if (!response) - return FALSE; - - sasl = camel_sasl_new ("imap", mech, CAMEL_SERVICE (store)); - while (!camel_sasl_authenticated (sasl)) { - resp = camel_imap_response_extract_continuation (store, response, ex); - if (!resp) - goto lose; - - sasl_resp = camel_sasl_challenge_base64 (sasl, imap_next_word (resp), ex); - g_free (resp); - if (camel_exception_is_set (ex)) - goto break_and_lose; - - response = camel_imap_command_continuation (store, sasl_resp, strlen (sasl_resp), ex); - g_free (sasl_resp); - if (!response) - goto lose; - } - - resp = camel_imap_response_extract_continuation (store, response, NULL); - if (resp) { - /* Oops. SASL claims we're done, but the IMAP server - * doesn't think so... - */ - g_free (resp); - goto lose; - } - - camel_object_unref (sasl); - - return TRUE; - - break_and_lose: - /* Get the server out of "waiting for continuation data" mode. */ - response = camel_imap_command_continuation (store, "*", 1, NULL); - if (response) - camel_imap_response_free (store, response); - - lose: - if (!camel_exception_is_set (ex)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Bad authentication response from server.")); - } - - camel_object_unref (sasl); - - return FALSE; -} - -static gboolean -imap_auth_loop (CamelService *service, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelSession *session = camel_service_get_session (service); - CamelServiceAuthType *authtype = NULL; - CamelImapResponse *response; - char *errbuf = NULL; - gboolean authenticated = FALSE; - const char *auth_domain; - - CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock); - auth_domain = camel_url_get_param (service->url, "auth-domain"); - - if (store->preauthed) { - if (camel_verbose_debug) - fprintf(stderr, "Server %s has preauthenticated us.\n", - service->url->host); - return TRUE; - } - - if (service->url->authmech) { - if (!g_hash_table_lookup (store->authtypes, service->url->authmech)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("IMAP server %s does not support requested " - "authentication type %s"), - service->url->host, - service->url->authmech); - return FALSE; - } - - authtype = camel_sasl_authtype (service->url->authmech); - if (!authtype) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("No support for authentication type %s"), - service->url->authmech); - return FALSE; - } - - if (!authtype->need_password) { - authenticated = try_auth (store, authtype->authproto, ex); - if (!authenticated) - return FALSE; - } - } - - while (!authenticated) { - if (errbuf) { - /* We need to un-cache the password before prompting again */ - camel_session_forget_password (session, service, auth_domain, "password", ex); - g_free (service->url->passwd); - service->url->passwd = NULL; - } - - if (!service->url->passwd) { - char *prompt; - - prompt = g_strdup_printf (_("%sPlease enter the IMAP " - "password for %s@%s"), - errbuf ? errbuf : "", - service->url->user, - service->url->host); - service->url->passwd = - camel_session_get_password (session, service, auth_domain, - prompt, "password", CAMEL_SESSION_PASSWORD_SECRET, ex); - g_free (prompt); - g_free (errbuf); - errbuf = NULL; - - if (!service->url->passwd) { - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("You didn't enter a password.")); - return FALSE; - } - } - - if (!store->connected) { - /* Some servers (eg, courier) will disconnect on - * a bad password. So reconnect here. - */ - if (!connect_to_server_wrapper (service, ex)) - return FALSE; - } - - if (authtype) - authenticated = try_auth (store, authtype->authproto, ex); - else { - response = camel_imap_command (store, NULL, ex, - "LOGIN %S %S", - service->url->user, - service->url->passwd); - if (response) { - camel_imap_response_free (store, response); - authenticated = TRUE; - } - } - if (!authenticated) { - if (camel_exception_get_id(ex) == CAMEL_EXCEPTION_USER_CANCEL) - return FALSE; - - errbuf = g_strdup_printf (_("Unable to authenticate " - "to IMAP server.\n%s\n\n"), - camel_exception_get_description (ex)); - camel_exception_clear (ex); - } - } - - return TRUE; -} - -static gboolean -can_work_offline (CamelDiscoStore *disco_store) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (disco_store); - - return camel_store_summary_count((CamelStoreSummary *)store->summary) != 0; -} - -static gboolean -imap_connect_online (CamelService *service, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelDiscoStore *disco_store = CAMEL_DISCO_STORE (service); - CamelImapResponse *response; - /*struct _namespaces *namespaces;*/ - char *result, *name, *path; - int i; - size_t len; - CamelImapStoreNamespace *ns; - - CAMEL_SERVICE_LOCK (store, connect_lock); - if (!connect_to_server_wrapper (service, ex) || - !imap_auth_loop (service, ex)) { - CAMEL_SERVICE_UNLOCK (store, connect_lock); - camel_service_disconnect (service, TRUE, NULL); - return FALSE; - } - - /* Get namespace and hierarchy separator */ - if ((store->capabilities & IMAP_CAPABILITY_NAMESPACE) && - !(store->parameters & IMAP_PARAM_OVERRIDE_NAMESPACE)) { - response = camel_imap_command (store, NULL, ex, "NAMESPACE"); - if (!response) - goto done; - - result = camel_imap_response_extract (store, response, "NAMESPACE", ex); - if (!result) - goto done; - -#if 0 - /* new code... */ - namespaces = imap_parse_namespace_response (result); - imap_namespaces_destroy (namespaces); - /* end new code */ -#endif - - name = camel_strstrcase (result, "NAMESPACE (("); - if (name) { - char *sep; - - name += 12; - store->namespace = imap_parse_string ((const char **) &name, &len); - if (name && *name++ == ' ') { - sep = imap_parse_string ((const char **) &name, &len); - if (sep) { - store->dir_sep = *sep; - g_free (sep); - } - } - } - g_free (result); - } - - if (!store->namespace) - store->namespace = g_strdup (""); - - if (!store->dir_sep) { - if (store->server_level >= IMAP_LEVEL_IMAP4REV1) { - /* This idiom means "tell me the hierarchy separator - * for the given path, even if that path doesn't exist. - */ - response = camel_imap_command (store, NULL, ex, - "LIST %S \"\"", - store->namespace); - } else { - /* Plain IMAP4 doesn't have that idiom, so we fall back - * to "tell me about this folder", which will fail if - * the folder doesn't exist (eg, if namespace is ""). - */ - response = camel_imap_command (store, NULL, ex, - "LIST \"\" %S", - store->namespace); - } - if (!response) - goto done; - - result = camel_imap_response_extract (store, response, "LIST", NULL); - if (result) { - imap_parse_list_response (store, result, NULL, &store->dir_sep, NULL); - g_free (result); - } - if (!store->dir_sep) { - store->dir_sep = '/'; /* Guess */ - } - } - - /* canonicalize the namespace to end with dir_sep */ - len = strlen (store->namespace); - if (len && store->namespace[len - 1] != store->dir_sep) { - gchar *tmp; - - tmp = g_strdup_printf ("%s%c", store->namespace, store->dir_sep); - g_free (store->namespace); - store->namespace = tmp; - } - - ns = camel_imap_store_summary_namespace_new(store->summary, store->namespace, store->dir_sep); - camel_imap_store_summary_namespace_set(store->summary, ns); - - if (CAMEL_STORE (store)->flags & CAMEL_STORE_SUBSCRIPTIONS) { - gboolean haveinbox = FALSE; - GPtrArray *folders; - char *pattern; - - /* this pre-fills the summary, and checks that lsub is useful */ - folders = g_ptr_array_new (); - pattern = g_strdup_printf ("%s*", store->namespace); - get_folders_online (store, pattern, folders, TRUE, ex); - g_free (pattern); - - for (i = 0; i < folders->len; i++) { - CamelFolderInfo *fi = folders->pdata[i]; - - haveinbox = haveinbox || !g_ascii_strcasecmp (fi->full_name, "INBOX"); - - if (fi->flags & (CAMEL_IMAP_FOLDER_MARKED | CAMEL_IMAP_FOLDER_UNMARKED)) - store->capabilities |= IMAP_CAPABILITY_useful_lsub; - camel_folder_info_free (fi); - } - - /* if the namespace is under INBOX, check INBOX explicitly */ - if (!g_ascii_strncasecmp (store->namespace, "INBOX", 5) && !camel_exception_is_set (ex)) { - gboolean just_subscribed = FALSE; - gboolean need_subscribe = FALSE; - - recheck: - g_ptr_array_set_size (folders, 0); - get_folders_online (store, "INBOX", folders, TRUE, ex); - - for (i = 0; i < folders->len; i++) { - CamelFolderInfo *fi = folders->pdata[i]; - - /* this should always be TRUE if folders->len > 0 */ - if (!g_ascii_strcasecmp (fi->full_name, "INBOX")) { - haveinbox = TRUE; - - /* if INBOX is marked as \NoSelect then it is probably - because it has not been subscribed to */ - if (!need_subscribe) - need_subscribe = fi->flags & CAMEL_FOLDER_NOSELECT; - } - - camel_folder_info_free (fi); - } - - need_subscribe = !haveinbox || need_subscribe; - if (need_subscribe && !just_subscribed && !camel_exception_is_set (ex)) { - /* in order to avoid user complaints, force a subscription to INBOX */ - response = camel_imap_command (store, NULL, ex, "SUBSCRIBE INBOX"); - if (response != NULL) { - /* force a re-check which will pre-fill the summary and - also get any folder flags present on the INBOX */ - camel_imap_response_free (store, response); - just_subscribed = TRUE; - goto recheck; - } - } - } - - g_ptr_array_free (folders, TRUE); - } - - path = g_strdup_printf ("%s/journal", store->storage_path); - disco_store->diary = camel_disco_diary_new (disco_store, path, ex); - g_free (path); - - done: - /* save any changes we had */ - camel_store_summary_save((CamelStoreSummary *)store->summary); - - CAMEL_SERVICE_UNLOCK (store, connect_lock); - - if (camel_exception_is_set (ex)) - camel_service_disconnect (service, TRUE, NULL); - else if (camel_disco_diary_empty (disco_store->diary)) - imap_store_refresh_folders (store, ex); - - return !camel_exception_is_set (ex); -} - -static gboolean -imap_connect_offline (CamelService *service, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelDiscoStore *disco_store = CAMEL_DISCO_STORE (service); - char *path; - - path = g_strdup_printf ("%s/journal", store->storage_path); - disco_store->diary = camel_disco_diary_new (disco_store, path, ex); - g_free (path); - if (!disco_store->diary) - return FALSE; - - imap_store_refresh_folders (store, ex); - - store->connected = !camel_exception_is_set (ex); - return store->connected; -} - -static gboolean -imap_disconnect_offline (CamelService *service, gboolean clean, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelDiscoStore *disco = CAMEL_DISCO_STORE (service); - - store->connected = FALSE; - if (store->current_folder) { - camel_object_unref (store->current_folder); - store->current_folder = NULL; - } - - if (store->authtypes) { - g_hash_table_foreach_remove (store->authtypes, - free_key, NULL); - g_hash_table_destroy (store->authtypes); - store->authtypes = NULL; - } - - if (store->namespace && !(store->parameters & IMAP_PARAM_OVERRIDE_NAMESPACE)) { - g_free (store->namespace); - store->namespace = NULL; - } - - if (disco->diary) { - camel_object_unref (disco->diary); - disco->diary = NULL; - } - - return TRUE; -} - -static gboolean -imap_disconnect_online (CamelService *service, gboolean clean, CamelException *ex) -{ - CamelImapStore *store = CAMEL_IMAP_STORE (service); - CamelImapResponse *response; - - if (store->connected && clean) { - response = camel_imap_command (store, NULL, NULL, "LOGOUT"); - camel_imap_response_free (store, response); - } - - if (store->istream) { - camel_object_unref (store->istream); - store->istream = NULL; - } - - if (store->ostream) { - camel_object_unref (store->ostream); - store->ostream = NULL; - } - - imap_disconnect_offline (service, clean, ex); - - return TRUE; -} - - -static gboolean -imap_summary_is_dirty (CamelFolderSummary *summary) -{ - CamelImapMessageInfo *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); - } - } - - return FALSE; -} - -static void -imap_noop (CamelStore *store, CamelException *ex) -{ - CamelImapStore *imap_store = (CamelImapStore *) store; - CamelDiscoStore *disco = (CamelDiscoStore *) store; - CamelImapResponse *response; - CamelFolder *current_folder; - - if (camel_disco_store_status (disco) != CAMEL_DISCO_STORE_ONLINE) - return; - - CAMEL_SERVICE_LOCK (imap_store, connect_lock); - - current_folder = imap_store->current_folder; - if (current_folder && imap_summary_is_dirty (current_folder->summary)) { - /* let's sync the flags instead. NB: must avoid folder lock */ - ((CamelFolderClass *)((CamelObject *)current_folder)->klass)->sync(current_folder, FALSE, ex); - } else { - response = camel_imap_command (imap_store, NULL, ex, "NOOP"); - if (response) - camel_imap_response_free (imap_store, response); - } - - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); -} - -static CamelFolder * -imap_get_trash(CamelStore *store, CamelException *ex) -{ - CamelFolder *folder = CAMEL_STORE_CLASS(parent_class)->get_trash(store, ex); - - if (folder) { - char *state = g_build_filename(((CamelImapStore *)store)->storage_path, "system", "Trash.cmeta", NULL); - - camel_object_set(folder, NULL, CAMEL_OBJECT_STATE_FILE, state, NULL); - g_free(state); - /* no defaults? */ - camel_object_state_read(folder); - } - - return folder; -} - -static CamelFolder * -imap_get_junk(CamelStore *store, CamelException *ex) -{ - CamelFolder *folder = CAMEL_STORE_CLASS(parent_class)->get_junk(store, ex); - - if (folder) { - char *state = g_build_filename(((CamelImapStore *)store)->storage_path, "system", "Junk.cmeta", NULL); - - camel_object_set(folder, NULL, CAMEL_OBJECT_STATE_FILE, state, NULL); - g_free(state); - /* no defaults? */ - camel_object_state_read(folder); - } - - return folder; -} - -static guint -hash_folder_name (gconstpointer key) -{ - if (g_ascii_strcasecmp (key, "INBOX") == 0) - return g_str_hash ("INBOX"); - else - return g_str_hash (key); -} - -static gint -compare_folder_name (gconstpointer a, gconstpointer b) -{ - gconstpointer aname = a, bname = b; - - if (g_ascii_strcasecmp (a, "INBOX") == 0) - aname = "INBOX"; - if (g_ascii_strcasecmp (b, "INBOX") == 0) - bname = "INBOX"; - return g_str_equal (aname, bname); -} - -struct imap_status_item { - struct imap_status_item *next; - char *name; - guint32 value; -}; - -static void -imap_status_item_free (struct imap_status_item *items) -{ - struct imap_status_item *next; - - while (items != NULL) { - next = items->next; - g_free (items->name); - g_free (items); - items = next; - } -} - -static struct imap_status_item * -get_folder_status (CamelImapStore *imap_store, const char *folder_name, const char *type) -{ - struct imap_status_item *items, *item, *tail; - CamelImapResponse *response; - char *status, *name, *p; - - /* FIXME: we assume the server is STATUS-capable */ - - response = camel_imap_command (imap_store, NULL, NULL, - "STATUS %F (%s)", - folder_name, - type); - - if (!response) { - CamelException ex; - - camel_exception_init (&ex); - if (imap_check_folder_still_extant (imap_store, folder_name, &ex) == FALSE) { - imap_folder_effectively_unsubscribed (imap_store, folder_name, &ex); - imap_forget_folder (imap_store, folder_name, &ex); - } - camel_exception_clear (&ex); - return NULL; - } - - if (!(status = camel_imap_response_extract (imap_store, response, "STATUS", NULL))) - return NULL; - - p = status + strlen ("* STATUS "); - while (*p == ' ') - p++; - - /* skip past the mailbox string */ - if (*p == '"') { - p++; - while (*p != '\0') { - if (*p == '"' && p[-1] != '\\') { - p++; - break; - } - - p++; - } - } else { - while (*p != ' ') - p++; - } - - while (*p == ' ') - p++; - - if (*p++ != '(') { - g_free (status); - return NULL; - } - - while (*p == ' ') - p++; - - if (*p == ')') { - g_free (status); - return NULL; - } - - items = NULL; - tail = (struct imap_status_item *) &items; - - do { - name = p; - while (*p != ' ') - p++; - - item = g_malloc (sizeof (struct imap_status_item)); - item->next = NULL; - item->name = g_strndup (name, p - name); - item->value = strtoul (p, &p, 10); - - tail->next = item; - tail = item; - - while (*p == ' ') - p++; - } while (*p != ')'); - - g_free (status); - - return items; -} - -static CamelFolder * -get_folder_online (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelImapResponse *response; - CamelFolder *new_folder; - char *folder_dir, *storage_path; - - if (!camel_imap_store_connected (imap_store, ex)) - return NULL; - - if (!g_ascii_strcasecmp (folder_name, "INBOX")) - folder_name = "INBOX"; - - /* Lock around the whole lot to check/create atomically */ - CAMEL_SERVICE_LOCK (imap_store, connect_lock); - if (imap_store->current_folder) { - camel_object_unref (imap_store->current_folder); - imap_store->current_folder = NULL; - } - response = camel_imap_command (imap_store, NULL, ex, "SELECT %F", folder_name); - if (!response) { - char *folder_real, *parent_name, *parent_real; - const char *c; - - if (camel_exception_get_id(ex) == CAMEL_EXCEPTION_USER_CANCEL) { - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - return NULL; - } - - camel_exception_clear (ex); - - if (!(flags & CAMEL_STORE_FOLDER_CREATE)) { - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("No such folder %s"), folder_name); - return NULL; - } - - if ((parent_name = strrchr (folder_name, '/'))) { - parent_name = g_strndup (folder_name, parent_name - folder_name); - parent_real = camel_imap_store_summary_path_to_full (imap_store->summary, parent_name, imap_store->dir_sep); - } else { - parent_real = NULL; - } - - c = parent_name ? parent_name : folder_name; - while (*c && *c != imap_store->dir_sep && !strchr ("#%*", *c)) - c++; - - if (*c != '\0') { - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_PATH, - _("The folder name \"%s\" is invalid because it contains the character \"%c\""), - folder_name, *c); - g_free (parent_name); - g_free (parent_real); - return NULL; - } - - if (parent_real != NULL) { - gboolean need_convert = FALSE; - char *resp, *thisone; - guint32 flags; - int i; - - if (!(response = camel_imap_command (imap_store, NULL, ex, "LIST \"\" %S", parent_real))) { - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - g_free (parent_name); - g_free (parent_real); - return NULL; - } - - /* FIXME: does not handle unexpected circumstances very well */ - for (i = 0; i < response->untagged->len; i++) { - resp = response->untagged->pdata[i]; - - if (!imap_parse_list_response (imap_store, resp, &flags, NULL, &thisone)) - continue; - - if (!strcmp (parent_name, thisone)) { - if (flags & CAMEL_FOLDER_NOINFERIORS) - need_convert = TRUE; - } - - g_free (thisone); - } - - camel_imap_response_free (imap_store, response); - - /* if not, check if we can delete it and recreate it */ - if (need_convert) { - struct imap_status_item *items, *item; - guint32 messages = 0; - CamelException lex; - char *name; - - item = items = get_folder_status (imap_store, parent_name, "MESSAGES"); - while (item != NULL) { - if (!g_ascii_strcasecmp (item->name, "MESSAGES")) { - messages = item->value; - break; - } - - item = item->next; - } - - imap_status_item_free (items); - - if (messages > 0) { - camel_exception_set (ex, CAMEL_EXCEPTION_FOLDER_INVALID_STATE, - _("The parent folder is not allowed to contain subfolders")); - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - g_free (parent_name); - g_free (parent_real); - return NULL; - } - - /* delete the old parent and recreate it */ - camel_exception_init (&lex); - delete_folder (store, parent_name, &lex); - if (camel_exception_is_set (&lex)) { - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - camel_exception_xfer (ex, &lex); - g_free (parent_name); - g_free (parent_real); - return NULL; - } - - /* add the dirsep to the end of parent_name */ - name = g_strdup_printf ("%s%c", parent_real, imap_store->dir_sep); - response = camel_imap_command (imap_store, NULL, ex, "CREATE %S", - name); - g_free (name); - - if (!response) { - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - g_free (parent_name); - g_free (parent_real); - return NULL; - } else - camel_imap_response_free (imap_store, response); - } - - g_free (parent_real); - } - - g_free (parent_name); - - folder_real = camel_imap_store_summary_path_to_full(imap_store->summary, folder_name, imap_store->dir_sep); - response = camel_imap_command (imap_store, NULL, ex, "CREATE %S", folder_real); - - if (response) { - camel_imap_store_summary_add_from_full(imap_store->summary, folder_real, imap_store->dir_sep); - - camel_imap_response_free (imap_store, response); - - response = camel_imap_command (imap_store, NULL, NULL, "SELECT %F", folder_name); - } - g_free(folder_real); - if (!response) { - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - return NULL; - } - } else if (flags & CAMEL_STORE_FOLDER_EXCL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create folder `%s': folder exists."), - folder_name); - - camel_imap_response_free_without_processing (imap_store, response); - - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - - return NULL; - } - - storage_path = g_strdup_printf("%s/folders", imap_store->storage_path); - folder_dir = imap_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); - if (new_folder) { - CamelException local_ex; - - imap_store->current_folder = new_folder; - camel_object_ref (new_folder); - camel_exception_init (&local_ex); - camel_imap_folder_selected (new_folder, response, &local_ex); - - if (camel_exception_is_set (&local_ex)) { - camel_exception_xfer (ex, &local_ex); - camel_object_unref (imap_store->current_folder); - imap_store->current_folder = NULL; - camel_object_unref (new_folder); - new_folder = NULL; - } - } - camel_imap_response_free_without_processing (imap_store, response); - - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - - return new_folder; -} - -static CamelFolder * -get_folder_offline (CamelStore *store, const char *folder_name, - guint32 flags, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelFolder *new_folder; - char *folder_dir, *storage_path; - - if (!imap_store->connected && - !camel_service_connect (CAMEL_SERVICE (store), ex)) - return NULL; - - if (!g_ascii_strcasecmp (folder_name, "INBOX")) - folder_name = "INBOX"; - - storage_path = g_strdup_printf("%s/folders", imap_store->storage_path); - folder_dir = imap_path_to_physical (storage_path, folder_name); - g_free(storage_path); - if (!folder_dir || access (folder_dir, F_OK) != 0) { - g_free (folder_dir); - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("No such folder %s"), folder_name); - return NULL; - } - - new_folder = camel_imap_folder_new (store, folder_name, folder_dir, ex); - g_free (folder_dir); - - return new_folder; -} - -static void -delete_folder (CamelStore *store, const char *folder_name, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelImapResponse *response; - - if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex)) - return; - - /* make sure this folder isn't currently SELECTed */ - response = camel_imap_command (imap_store, NULL, ex, "SELECT INBOX"); - if (response) { - camel_imap_response_free_without_processing (imap_store, response); - - CAMEL_SERVICE_LOCK (imap_store, connect_lock); - - if (imap_store->current_folder) - camel_object_unref (imap_store->current_folder); - /* no need to actually create a CamelFolder for INBOX */ - imap_store->current_folder = NULL; - - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - } else - return; - - response = camel_imap_command (imap_store, NULL, ex, "DELETE %F", - folder_name); - - if (response) { - camel_imap_response_free (imap_store, response); - imap_forget_folder (imap_store, folder_name, ex); - } -} - -static void -manage_subscriptions (CamelStore *store, const char *old_name, gboolean subscribe) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelStoreInfo *si; - int olen = strlen(old_name); - const char *path; - int i, count; - - count = camel_store_summary_count((CamelStoreSummary *)imap_store->summary); - for (i=0;i<count;i++) { - si = camel_store_summary_index((CamelStoreSummary *)imap_store->summary, i); - if (si) { - path = camel_store_info_path(imap_store->summary, si); - if (strncmp(path, old_name, olen) == 0) { - if (subscribe) - subscribe_folder(store, path, NULL); - else - unsubscribe_folder(store, path, NULL); - } - camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si); - } - } -} - -static void -rename_folder_info (CamelImapStore *imap_store, const char *old_name, const char *new_name) -{ - int i, count; - CamelStoreInfo *si; - int olen = strlen(old_name); - const char *path; - char *npath, *nfull; - - count = camel_store_summary_count((CamelStoreSummary *)imap_store->summary); - for (i=0;i<count;i++) { - si = camel_store_summary_index((CamelStoreSummary *)imap_store->summary, i); - if (si == NULL) - continue; - path = camel_store_info_path(imap_store->summary, si); - if (strncmp(path, old_name, olen) == 0) { - if (strlen(path) > olen) - npath = g_strdup_printf("%s/%s", new_name, path+olen+1); - else - npath = g_strdup(new_name); - nfull = camel_imap_store_summary_path_to_full(imap_store->summary, npath, imap_store->dir_sep); - - /* workaround for broken server (courier uses '.') that doesn't rename - subordinate folders as required by rfc 2060 */ - if (imap_store->dir_sep == '.') { - CamelImapResponse *response; - - response = camel_imap_command (imap_store, NULL, NULL, "RENAME %F %S", path, nfull); - if (response) - camel_imap_response_free (imap_store, response); - } - - camel_store_info_set_string((CamelStoreSummary *)imap_store->summary, si, CAMEL_STORE_INFO_PATH, npath); - camel_store_info_set_string((CamelStoreSummary *)imap_store->summary, si, CAMEL_IMAP_STORE_INFO_FULL_NAME, nfull); - - camel_store_summary_touch((CamelStoreSummary *)imap_store->summary); - g_free(nfull); - g_free(npath); - } - camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si); - } -} - -static void -rename_folder (CamelStore *store, const char *old_name, const char *new_name_in, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelImapResponse *response; - char *oldpath, *newpath, *storage_path, *new_name; - - if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex)) - return; - - /* make sure this folder isn't currently SELECTed - it's - actually possible to rename INBOX but if you do another - INBOX will immediately be created by the server */ - response = camel_imap_command (imap_store, NULL, ex, "SELECT INBOX"); - if (response) { - camel_imap_response_free_without_processing (imap_store, response); - - CAMEL_SERVICE_LOCK (imap_store, connect_lock); - - if (imap_store->current_folder) - camel_object_unref (imap_store->current_folder); - /* no need to actually create a CamelFolder for INBOX */ - imap_store->current_folder = NULL; - - CAMEL_SERVICE_UNLOCK (imap_store, connect_lock); - } else - return; - - imap_store->renaming = TRUE; - - if (store->flags & CAMEL_STORE_SUBSCRIPTIONS) - manage_subscriptions(store, old_name, FALSE); - - new_name = camel_imap_store_summary_path_to_full(imap_store->summary, new_name_in, imap_store->dir_sep); - response = camel_imap_command (imap_store, NULL, ex, "RENAME %F %S", old_name, new_name); - - if (!response) { - if (store->flags & CAMEL_STORE_SUBSCRIPTIONS) - manage_subscriptions(store, old_name, TRUE); - g_free(new_name); - imap_store->renaming = FALSE; - return; - } - - camel_imap_response_free (imap_store, response); - - /* rename summary, and handle broken server */ - rename_folder_info(imap_store, old_name, new_name_in); - - if (store->flags & CAMEL_STORE_SUBSCRIPTIONS) - 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); - g_free(storage_path); - - /* So do we care if this didn't work? Its just a cache? */ - if (rename (oldpath, newpath) == -1) { - g_warning ("Could not rename message cache '%s' to '%s': %s: cache reset", - oldpath, newpath, strerror (errno)); - } - - g_free (oldpath); - g_free (newpath); - g_free(new_name); - - imap_store->renaming = FALSE; -} - -static CamelFolderInfo * -create_folder (CamelStore *store, const char *parent_name, - const char *folder_name, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - char *full_name, *resp, *thisone, *parent_real, *real_name; - CamelImapResponse *response; - CamelException internal_ex; - CamelFolderInfo *root = NULL; - gboolean need_convert; - int i = 0, flags; - const char *c; - - if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex)) - return NULL; - if (!parent_name) - parent_name = ""; - - c = folder_name; - while (*c && *c != imap_store->dir_sep && !strchr ("#%*", *c)) - c++; - - if (*c != '\0') { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_PATH, - _("The folder name \"%s\" is invalid because it contains the character \"%c\""), - folder_name, *c); - return NULL; - } - - /* check if the parent allows inferiors */ - - /* FIXME: use storesummary directly */ - parent_real = camel_imap_store_summary_full_from_path(imap_store->summary, parent_name); - if (parent_real == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_STATE, - _("Unknown parent folder: %s"), parent_name); - return NULL; - } - - need_convert = FALSE; - response = camel_imap_command (imap_store, NULL, ex, "LIST \"\" %S", - parent_real); - if (!response) /* whoa, this is bad */ { - g_free(parent_real); - return NULL; - } - - /* FIXME: does not handle unexpected circumstances very well */ - for (i = 0; i < response->untagged->len; i++) { - resp = response->untagged->pdata[i]; - - if (!imap_parse_list_response (imap_store, resp, &flags, NULL, &thisone)) - continue; - - if (strcmp (thisone, parent_name) == 0) { - if (flags & CAMEL_FOLDER_NOINFERIORS) - need_convert = TRUE; - break; - } - } - - camel_imap_response_free (imap_store, response); - - camel_exception_init (&internal_ex); - - /* if not, check if we can delete it and recreate it */ - if (need_convert) { - struct imap_status_item *items, *item; - guint32 messages = 0; - char *name; - - item = items = get_folder_status (imap_store, parent_name, "MESSAGES"); - while (item != NULL) { - if (!g_ascii_strcasecmp (item->name, "MESSAGES")) { - messages = item->value; - break; - } - - item = item->next; - } - - imap_status_item_free (items); - - if (messages > 0) { - camel_exception_set (ex, CAMEL_EXCEPTION_FOLDER_INVALID_STATE, - _("The parent folder is not allowed to contain subfolders")); - g_free(parent_real); - return NULL; - } - - /* delete the old parent and recreate it */ - delete_folder (store, parent_name, &internal_ex); - if (camel_exception_is_set (&internal_ex)) { - camel_exception_xfer (ex, &internal_ex); - return NULL; - } - - /* add the dirsep to the end of parent_name */ - name = g_strdup_printf ("%s%c", parent_real, imap_store->dir_sep); - response = camel_imap_command (imap_store, NULL, ex, "CREATE %S", - name); - g_free (name); - - if (!response) { - g_free(parent_real); - return NULL; - } else - camel_imap_response_free (imap_store, response); - - root = imap_build_folder_info(imap_store, parent_name); - } - - /* ok now we can create the folder */ - real_name = camel_imap_store_summary_path_to_full(imap_store->summary, folder_name, imap_store->dir_sep); - full_name = imap_concat (imap_store, parent_real, real_name); - g_free(real_name); - response = camel_imap_command (imap_store, NULL, ex, "CREATE %S", full_name); - - if (response) { - CamelImapStoreInfo *si; - CamelFolderInfo *fi; - - camel_imap_response_free (imap_store, response); - - si = camel_imap_store_summary_add_from_full(imap_store->summary, full_name, imap_store->dir_sep); - camel_store_summary_save((CamelStoreSummary *)imap_store->summary); - fi = imap_build_folder_info(imap_store, camel_store_info_path(imap_store->summary, si)); - fi->flags |= CAMEL_FOLDER_NOCHILDREN; - if (root) { - root->child = fi; - fi->parent = root; - } else { - root = fi; - } - camel_object_trigger_event (CAMEL_OBJECT (store), "folder_created", root); - } else if (root) { - /* need to re-recreate the folder we just deleted */ - camel_object_trigger_event (CAMEL_OBJECT (store), "folder_created", root); - camel_folder_info_free(root); - root = NULL; - } - - g_free (full_name); - g_free(parent_real); - - return root; -} - -static CamelFolderInfo * -parse_list_response_as_folder_info (CamelImapStore *imap_store, - const char *response) -{ - CamelFolderInfo *fi; - int flags; - char sep, *dir, *path; - CamelURL *url; - CamelImapStoreInfo *si; - guint32 newflags; - - if (!imap_parse_list_response (imap_store, response, &flags, &sep, &dir)) - return NULL; - - /* FIXME: should use imap_build_folder_info, note the differences with param setting tho */ - - si = camel_imap_store_summary_add_from_full(imap_store->summary, dir, sep?sep:'/'); - if (si == NULL) - return NULL; - - newflags = (si->info.flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) | (flags & ~CAMEL_STORE_INFO_FOLDER_SUBSCRIBED); - if (si->info.flags != newflags) { - si->info.flags = newflags; - camel_store_summary_touch((CamelStoreSummary *)imap_store->summary); - } - - fi = g_new0 (CamelFolderInfo, 1); - fi->name = g_strdup(camel_store_info_name(imap_store->summary, si)); - fi->full_name = g_strdup(camel_store_info_path(imap_store->summary, si)); - if (!g_ascii_strcasecmp(fi->full_name, "inbox")) - flags |= CAMEL_FOLDER_SYSTEM; - /* HACK: some servers report noinferiors for all folders (uw-imapd) - We just translate this into nochildren, and let the imap layer enforce - it. See create folder */ - if (flags & CAMEL_FOLDER_NOINFERIORS) - flags = (fi->flags & ~CAMEL_FOLDER_NOINFERIORS) | CAMEL_FOLDER_NOCHILDREN; - fi->flags = flags; - - url = camel_url_new (imap_store->base_url, NULL); - path = alloca(strlen(fi->full_name)+2); - sprintf(path, "/%s", fi->full_name); - camel_url_set_path(url, path); - - if (flags & CAMEL_FOLDER_NOSELECT || fi->name[0] == 0) - camel_url_set_param (url, "noselect", "yes"); - fi->uri = camel_url_to_string (url, 0); - camel_url_free (url); - - /* FIXME: redundant */ - if (flags & CAMEL_IMAP_FOLDER_UNMARKED) - fi->unread = -1; - - return fi; -} - -/* returns true if full_name is a sub-folder of top, or is top */ -static int -imap_is_subfolder(const char *full_name, const char *top) -{ - size_t len = strlen(top); - - /* Looks for top being a full-path subset of full_name. - Handle IMAP Inbox case insensitively */ - - if (g_ascii_strncasecmp(top, "inbox", 5) == 0 - && (top[5] == 0 || top[5] == '/') - && g_ascii_strncasecmp(full_name, "inbox", 5) == 0 - && (full_name[5] == 0 || full_name[5] == '/')) { - full_name += 5; - top += 5; - len -= 5; - } - - return top[0] == 0 - || (strncmp(full_name, top, len) == 0 - && (full_name[len] == 0 - || full_name[len] == '/')); -} - -/* this is used when lsub doesn't provide very useful information */ -static GPtrArray * -get_subscribed_folders (CamelImapStore *imap_store, const char *top, CamelException *ex) -{ - GPtrArray *names, *folders; - int i; - CamelStoreInfo *si; - CamelImapResponse *response; - CamelFolderInfo *fi; - char *result; - int haveinbox = FALSE; - - if (camel_debug("imap:folder_info")) - printf(" get_subscribed folders\n"); - - folders = g_ptr_array_new (); - names = g_ptr_array_new (); - for (i=0;(si = camel_store_summary_index((CamelStoreSummary *)imap_store->summary, i));i++) { - if (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED - && imap_is_subfolder(camel_store_info_path(imap_store->summary, si), top)) { - g_ptr_array_add(names, (char *)camel_imap_store_info_full_name(imap_store->summary, si)); - haveinbox = haveinbox || g_ascii_strcasecmp(camel_imap_store_info_full_name(imap_store->summary, si), "INBOX") == 0; - } - camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si); - } - - if (!haveinbox) - g_ptr_array_add (names, "INBOX"); - - for (i = 0; i < names->len; i++) { - response = camel_imap_command (imap_store, NULL, ex, - "LIST \"\" %S", - names->pdata[i]); - if (!response) - break; - - result = camel_imap_response_extract (imap_store, response, "LIST", NULL); - if (!result) { - camel_store_summary_remove_path((CamelStoreSummary *)imap_store->summary, names->pdata[i]); - g_ptr_array_remove_index_fast (names, i); - i--; - continue; - } - - fi = parse_list_response_as_folder_info (imap_store, result); - g_free (result); - if (!fi) - continue; - - if (!imap_is_subfolder(fi->full_name, top)) { - camel_folder_info_free (fi); - continue; - } - - g_ptr_array_add (folders, fi); - } - - g_ptr_array_free (names, TRUE); - - return folders; -} - -static int imap_match_pattern(char dir_sep, const char *pattern, const char *name) -{ - char p, n; - - p = *pattern++; - n = *name++; - while (n && p) { - if (n == p) { - p = *pattern++; - n = *name++; - } else if (p == '%') { - if (n != dir_sep) { - n = *name++; - } else { - p = *pattern++; - } - } else if (p == '*') { - return TRUE; - } else - return FALSE; - } - - return n == 0 && (p == '%' || p == 0); -} - -static void -get_folders_online (CamelImapStore *imap_store, const char *pattern, - GPtrArray *folders, gboolean lsub, CamelException *ex) -{ - CamelImapResponse *response; - CamelFolderInfo *fi; - char *list; - int i, count; - GHashTable *present; - CamelStoreInfo *si; - - response = camel_imap_command (imap_store, NULL, ex, - "%s \"\" %S", lsub ? "LSUB" : "LIST", - pattern); - if (!response) - return; - - present = g_hash_table_new(g_str_hash, g_str_equal); - for (i = 0; i < response->untagged->len; i++) { - list = response->untagged->pdata[i]; - fi = parse_list_response_as_folder_info (imap_store, list); - if (fi) { - g_ptr_array_add(folders, fi); - g_hash_table_insert(present, fi->full_name, fi); - } - } - camel_imap_response_free (imap_store, response); - - /* update our summary to match the server */ - count = camel_store_summary_count((CamelStoreSummary *)imap_store->summary); - for (i=0;i<count;i++) { - si = camel_store_summary_index((CamelStoreSummary *)imap_store->summary, i); - if (si == NULL) - continue; - - if (imap_match_pattern(imap_store->dir_sep, pattern, camel_imap_store_info_full_name(imap_store->summary, si))) { - if (g_hash_table_lookup(present, camel_store_info_path(imap_store->summary, si)) != NULL) { - if (lsub && (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) == 0) { - si->flags |= CAMEL_STORE_INFO_FOLDER_SUBSCRIBED; - camel_store_summary_touch((CamelStoreSummary *)imap_store->summary); - } - } else { - if (lsub) { - if (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) { - si->flags &= ~CAMEL_STORE_INFO_FOLDER_SUBSCRIBED; - camel_store_summary_touch((CamelStoreSummary *)imap_store->summary); - } - } else { - camel_store_summary_remove((CamelStoreSummary *)imap_store->summary, si); - count--; - i--; - } - } - } - camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si); - } - g_hash_table_destroy(present); -} - -#if 0 -static void -dumpfi(CamelFolderInfo *fi) -{ - int depth; - CamelFolderInfo *n = fi; - - if (fi == NULL) - return; - - depth = 0; - while (n->parent) { - depth++; - n = n->parent; - } - - while (fi) { - printf("%-40s %-30s %*s\n", fi->path, fi->full_name, depth*2+strlen(fi->url), fi->url); - if (fi->child) - dumpfi(fi->child); - fi = fi->sibling; - } -} -#endif - -static void -fill_fi(CamelStore *store, CamelFolderInfo *fi, guint32 flags) -{ - CamelFolder *folder; - - fi->unread = -1; - fi->total = -1; - folder = camel_object_bag_peek(store->folders, fi->full_name); - if (folder) { - if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0) - /* we use connect lock for everything, so this should be safe */ - CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(folder))->refresh_info(folder, NULL); - fi->unread = camel_folder_get_unread_message_count(folder); - fi->total = camel_folder_get_message_count(folder); - camel_object_unref(folder); - } else { - char *storage_path, *folder_dir, *path; - CamelFolderSummary *s; - - /* 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); - 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); - camel_folder_summary_set_filename(s, path); - if (camel_folder_summary_header_load(s) != -1) { - fi->unread = s->unread_count; - fi->total = s->saved_count; - } - g_free(storage_path); - g_free(folder_dir); - g_free(path); - - camel_object_unref(s); - } -} - -/* NB: We should have connect_lock at this point */ -static void -get_folder_counts(CamelImapStore *imap_store, CamelFolderInfo *fi, CamelException *ex) -{ - GSList *q; - CamelFolder *folder; - - /* non-recursive breath first search */ - - q = g_slist_append(NULL, fi); - - while (q) { - fi = q->data; - q = g_slist_remove_link(q, q); - - while (fi) { - /* ignore noselect folders, and check only inbox if we only check inbox */ - if ((fi->flags & CAMEL_FOLDER_NOSELECT) == 0 - && ( (imap_store->parameters & IMAP_PARAM_CHECK_ALL) - || g_ascii_strcasecmp(fi->full_name, "inbox") == 0) ) { - - /* For the current folder, poke it to check for new - * messages and then report that number, rather than - * doing a STATUS command. - */ - if (imap_store->current_folder && strcmp(imap_store->current_folder->full_name, fi->full_name) == 0) { - /* we bypass the folder locking otherwise we can deadlock. we use the command lock for - any operations anyway so this is 'safe'. See comment above imap_store_refresh_folders() for info */ - CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(imap_store->current_folder))->refresh_info(imap_store->current_folder, ex); - fi->unread = camel_folder_get_unread_message_count (imap_store->current_folder); - fi->total = camel_folder_get_message_count(imap_store->current_folder); - } else { - struct imap_status_item *items, *item; - - fi->unread = -1; - fi->total = -1; - - item = items = get_folder_status (imap_store, fi->full_name, "MESSAGES UNSEEN"); - while (item != NULL) { - if (!g_ascii_strcasecmp (item->name, "MESSAGES")) { - fi->total = item->value; - } else if (!g_ascii_strcasecmp (item->name, "UNSEEN")) { - fi->unread = item->value; - } - - item = item->next; - } - - imap_status_item_free (items); - - /* if we have this folder open, and the unread count has changed, update */ - folder = camel_object_bag_peek(CAMEL_STORE(imap_store)->folders, fi->full_name); - if (folder) { - if (fi->unread != camel_folder_get_unread_message_count(folder)) { - CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(folder))->refresh_info(folder, ex); - fi->unread = camel_folder_get_unread_message_count(folder); - fi->total = camel_folder_get_message_count(folder); - } - camel_object_unref(folder); - } - } - } else { - /* since its cheap, get it if they're open/consult summary file */ - fill_fi((CamelStore *)imap_store, fi, 0); - } - - if (fi->child) - q = g_slist_append(q, fi->child); - fi = fi->next; - } - } -} - -/* imap needs to treat inbox case insensitive */ -/* we'll assume the names are normalised already */ -static guint folder_hash(const void *ap) -{ - const char *a = ap; - - if (g_ascii_strcasecmp(a, "INBOX") == 0) - a = "INBOX"; - - return g_str_hash(a); -} - -static int folder_eq(const void *ap, const void *bp) -{ - const char *a = ap; - const char *b = bp; - - if (g_ascii_strcasecmp(a, "INBOX") == 0) - a = "INBOX"; - if (g_ascii_strcasecmp(b, "INBOX") == 0) - b = "INBOX"; - - return g_str_equal(a, b); -} - -static GSList * -get_folders_add_folders(GSList *p, int recurse, GHashTable *infos, GPtrArray *folders, GPtrArray *folders_out) -{ - CamelFolderInfo *oldfi, *fi; - int i; - - /* This is a nasty mess, because some servers will return - broken results from LIST or LSUB if you use '%'. e.g. you - may get (many) duplicate names, and worse, names may have - conflicting flags. */ - for (i=0; i<folders->len; i++) { - fi = folders->pdata[i]; - oldfi = g_hash_table_lookup(infos, fi->full_name); - if (oldfi == NULL) { - d(printf(" new folder '%s'\n", fi->full_name)); - g_hash_table_insert(infos, fi->full_name, fi); - if (recurse) - p = g_slist_prepend(p, fi); - g_ptr_array_add(folders_out, fi); - } else { - d(printf(" old folder '%s', old flags %08x new flags %08x\n", fi->full_name, oldfi->flags, fi->flags)); - - /* need to special-case noselect, since it also affects the uri */ - if ((oldfi->flags & CAMEL_FOLDER_NOSELECT) != 0 - && (fi->flags & CAMEL_FOLDER_NOSELECT) == 0) { - g_free(oldfi->uri); - oldfi->uri = fi->uri; - fi->uri = NULL; - } - - /* some flags are anded together, some are or'd */ - - oldfi->flags = (oldfi->flags & fi->flags & (CAMEL_FOLDER_NOSELECT|CAMEL_FOLDER_NOINFERIORS)) - | ((oldfi->flags | fi->flags) & ~(CAMEL_FOLDER_NOSELECT|CAMEL_FOLDER_NOINFERIORS)); - - camel_folder_info_free(fi); - } - } - - g_ptr_array_set_size(folders, 0); - - return p; -} - -static GPtrArray * -get_folders(CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - GSList *q, *p = NULL; - GHashTable *infos; - int i; - GPtrArray *folders, *folders_out; - CamelFolderInfo *fi; - char *name; - int depth = 0; - int haveinbox = 0; - static int imap_max_depth = 0; - - if (!camel_imap_store_connected (imap_store, ex)) - return NULL; - - if (camel_debug("imap:folder_info")) - printf(" get_folders\n"); - - /* allow megalomaniacs to override the max of 10 */ - if (imap_max_depth == 0) { - name = getenv("CAMEL_IMAP_MAX_DEPTH"); - if (name) { - imap_max_depth = atoi (name); - imap_max_depth = MIN (MAX (imap_max_depth, 0), 2); - } else - imap_max_depth = 10; - } - - infos = g_hash_table_new(folder_hash, folder_eq); - - /* get starting point & strip trailing '/' */ - if (top[0] == 0) { - if (imap_store->namespace) { - top = imap_store->namespace; - i = strlen(top)-1; - name = g_malloc(i+2); - strcpy(name, top); - while (i>0 && name[i] == imap_store->dir_sep) - name[i--] = 0; - } else - name = g_strdup(""); - } else { - name = camel_imap_store_summary_full_from_path(imap_store->summary, top); - if (name == NULL) - name = camel_imap_store_summary_path_to_full(imap_store->summary, top, imap_store->dir_sep); - } - - d(printf("\n\nList '%s' %s\n", name, flags&CAMEL_STORE_FOLDER_INFO_RECURSIVE?"RECURSIVE":"NON-RECURSIVE")); - - folders_out = g_ptr_array_new(); - folders = g_ptr_array_new(); - - /* first get working list of names */ - get_folders_online (imap_store, name[0]?name:"%", folders, flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, ex); - if (camel_exception_is_set(ex)) - goto fail; - for (i=0; i<folders->len && !haveinbox; i++) { - fi = folders->pdata[i]; - haveinbox = (g_ascii_strcasecmp(fi->full_name, "INBOX")) == 0; - } - - if (!haveinbox && top == imap_store->namespace) { - get_folders_online (imap_store, "INBOX", folders, - flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, ex); - - if (camel_exception_is_set (ex)) - goto fail; - } - - p = get_folders_add_folders(p, TRUE, infos, folders, folders_out); - - /* p is a reversed list of pending folders for the next level, q is the list of folders for this */ - while (p) { - q = g_slist_reverse(p); - - p = NULL; - while (q) { - fi = q->data; - - q = g_slist_remove_link(q, q); - - d(printf("Checking parent folder '%s'\n", fi->full_name)); - - /* First if we're not recursive mode on the top level, and we know it has or doesn't - or can't have children, no need to go further - a bit ugly */ - if ( top == imap_store->namespace - && (flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) == 0 - && (fi->flags & (CAMEL_FOLDER_CHILDREN|CAMEL_FOLDER_NOCHILDREN|CAMEL_FOLDER_NOINFERIORS)) != 0) { - /* do nothing */ - d(printf(" not interested in folder right now ...\n")); - } - /* Otherwise, if this has (or might have) children, scan it */ - else if ( (fi->flags & (CAMEL_FOLDER_NOCHILDREN|CAMEL_FOLDER_NOINFERIORS)) == 0 - || (fi->flags & CAMEL_FOLDER_CHILDREN) != 0) { - char *n, *real; - - real = camel_imap_store_summary_full_from_path(imap_store->summary, fi->full_name); - n = imap_concat(imap_store, real?real:fi->full_name, "%"); - get_folders_online(imap_store, n, folders, flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, ex); - g_free(n); - g_free(real); - - if (camel_exception_is_set (ex)) - goto fail; - - if (folders->len > 0) - fi->flags |= CAMEL_FOLDER_CHILDREN; - - p = get_folders_add_folders(p, (flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) && depth<imap_max_depth, - infos, folders, folders_out); - } - } - depth++; - } - - g_ptr_array_free(folders, TRUE); - g_hash_table_destroy(infos); - g_free(name); - - return folders_out; -fail: - g_ptr_array_free(folders, TRUE); - g_ptr_array_free(folders_out, TRUE); - g_hash_table_destroy(infos); - g_slist_free (p); - g_free(name); - - return NULL; -} - -static CamelFolderInfo * -get_folder_info_online (CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelFolderInfo *tree = NULL; - GPtrArray *folders; - - if (top == NULL) - top = ""; - - if (camel_debug("imap:folder_info")) - printf("get folder info online\n"); - - CAMEL_SERVICE_LOCK(store, connect_lock); - - if ((flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) - && !(imap_store->capabilities & IMAP_CAPABILITY_useful_lsub) - && (imap_store->parameters & IMAP_PARAM_CHECK_ALL)) - folders = get_subscribed_folders(imap_store, top, ex); - else - folders = get_folders(store, top, flags, ex); - - if (folders == NULL) - goto done; - - tree = camel_folder_info_build(folders, top, '/', TRUE); - g_ptr_array_free(folders, TRUE); - - if (!(flags & CAMEL_STORE_FOLDER_INFO_FAST)) - get_folder_counts(imap_store, tree, ex); - - d(dumpfi(tree)); - camel_store_summary_save((CamelStoreSummary *)imap_store->summary); -done: - CAMEL_SERVICE_UNLOCK(store, connect_lock); - - return tree; -} - -static gboolean -get_one_folder_offline (const char *physical_path, const char *path, gpointer data) -{ - GPtrArray *folders = data; - CamelImapStore *imap_store = folders->pdata[0]; - CamelFolderInfo *fi; - CamelStoreInfo *si; - - if (*path != '/') - return TRUE; - - /* folder_info_build will insert parent nodes as necessary and mark - * them as noselect, which is information we actually don't have at - * the moment. So let it do the right thing by bailing out if it's - * not a folder we're explicitly interested in. - */ - - si = camel_store_summary_path((CamelStoreSummary *)imap_store->summary, path+1); - if (si) { - if ((((CamelStore *)imap_store)->flags & CAMEL_STORE_SUBSCRIPTIONS) == 0 - || (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED)) { - fi = imap_build_folder_info(imap_store, path+1); - fi->flags = si->flags; - /* HACK: some servers report noinferiors for all folders (uw-imapd) - We just translate this into nochildren, and let the imap layer enforce - it. See create folder */ - if (fi->flags & CAMEL_FOLDER_NOINFERIORS) - fi->flags = (fi->flags & ~CAMEL_FOLDER_NOINFERIORS) | CAMEL_FOLDER_NOCHILDREN; - - if (si->flags & CAMEL_FOLDER_NOSELECT) { - CamelURL *url = camel_url_new(fi->uri, NULL); - - camel_url_set_param (url, "noselect", "yes"); - g_free(fi->uri); - fi->uri = camel_url_to_string (url, 0); - camel_url_free (url); - } else { - fill_fi((CamelStore *)imap_store, fi, 0); - } - g_ptr_array_add (folders, fi); - } - camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si); - } - - return TRUE; -} - -static CamelFolderInfo * -get_folder_info_offline (CamelStore *store, const char *top, - guint32 flags, CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelFolderInfo *fi; - GPtrArray *folders; - char *storage_path; - - if (camel_debug("imap:folder_info")) - printf("get folder info offline\n"); - - if (!imap_store->connected && - !camel_service_connect (CAMEL_SERVICE (store), ex)) - return NULL; - - if ((store->flags & CAMEL_STORE_SUBSCRIPTIONS) && - !(flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED)) { - camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex); - return NULL; - } - - /* FIXME: obey other flags */ - - folders = g_ptr_array_new (); - - /* 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)) { - camel_disco_store_check_online (CAMEL_DISCO_STORE (imap_store), ex); - fi = NULL; - } else { - g_ptr_array_remove_index_fast (folders, 0); - fi = camel_folder_info_build (folders, "", '/', TRUE); - } - g_free(storage_path); - - g_ptr_array_free (folders, TRUE); - return fi; -} - -static gboolean -folder_subscribed (CamelStore *store, const char *folder_name) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelStoreInfo *si; - int truth = FALSE; - - si = camel_store_summary_path((CamelStoreSummary *)imap_store->summary, folder_name); - if (si) { - truth = (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) != 0; - camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si); - } - - return truth; -} - -/* Note: folder_name must match a folder as listed with get_folder_info() -> full_name */ -static void -subscribe_folder (CamelStore *store, const char *folder_name, - CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelImapResponse *response; - CamelFolderInfo *fi; - CamelStoreInfo *si; - - if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex)) - return; - if (!camel_imap_store_connected (imap_store, ex)) - return; - - response = camel_imap_command (imap_store, NULL, ex, - "SUBSCRIBE %F", folder_name); - if (!response) - return; - camel_imap_response_free (imap_store, response); - - si = camel_store_summary_path((CamelStoreSummary *)imap_store->summary, folder_name); - if (si) { - if ((si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) == 0) { - si->flags |= CAMEL_STORE_INFO_FOLDER_SUBSCRIBED; - camel_store_summary_touch((CamelStoreSummary *)imap_store->summary); - camel_store_summary_save((CamelStoreSummary *)imap_store->summary); - } - camel_store_summary_info_free((CamelStoreSummary *)imap_store->summary, si); - } - - if (imap_store->renaming) { - /* we don't need to emit a "folder_subscribed" signal - if we are in the process of renaming folders, so we - are done here... */ - return; - } - - fi = imap_build_folder_info(imap_store, folder_name); - fi->flags |= CAMEL_FOLDER_NOCHILDREN; - - camel_object_trigger_event (CAMEL_OBJECT (store), "folder_subscribed", fi); - camel_folder_info_free (fi); -} - -static void -unsubscribe_folder (CamelStore *store, const char *folder_name, - CamelException *ex) -{ - CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - CamelImapResponse *response; - - if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex)) - return; - if (!camel_imap_store_connected (imap_store, ex)) - return; - - response = camel_imap_command (imap_store, NULL, ex, - "UNSUBSCRIBE %F", folder_name); - if (!response) - return; - camel_imap_response_free (imap_store, response); - - imap_folder_effectively_unsubscribed (imap_store, folder_name, ex); -} - -#if 0 -static gboolean -folder_flags_have_changed (CamelFolder *folder) -{ - CamelMessageInfo *info; - int i, max; - - max = camel_folder_summary_count (folder->summary); - for (i = 0; i < max; i++) { - info = camel_folder_summary_index (folder->summary, i); - if (!info) - continue; - if (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) { - return TRUE; - } - } - - return FALSE; -} -#endif - - -gboolean -camel_imap_store_connected (CamelImapStore *store, CamelException *ex) -{ - if (store->istream == NULL || !store->connected) - return camel_service_connect (CAMEL_SERVICE (store), ex); - return TRUE; -} - - -/* FIXME: please god, when will the hurting stop? Thus function is so - fucking broken it's not even funny. */ -ssize_t -camel_imap_store_readline (CamelImapStore *store, char **dest, CamelException *ex) -{ - CamelStreamBuffer *stream; - char linebuf[1024]; - GByteArray *ba; - ssize_t nread; - - g_return_val_if_fail (CAMEL_IS_IMAP_STORE (store), -1); - g_return_val_if_fail (dest, -1); - - *dest = NULL; - - /* Check for connectedness. Failed (or cancelled) operations will - * close the connection. We can't expect a read to have any - * meaning if we reconnect, so always set an exception. - */ - - if (!camel_imap_store_connected (store, ex)) - return -1; - - stream = CAMEL_STREAM_BUFFER (store->istream); - - ba = g_byte_array_new (); - while ((nread = camel_stream_buffer_gets (stream, linebuf, sizeof (linebuf))) > 0) { - g_byte_array_append (ba, linebuf, nread); - if (linebuf[nread - 1] == '\n') - break; - } - - if (nread <= 0) { - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Server unexpectedly disconnected: %s"), - g_strerror (errno)); - - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); - g_byte_array_free (ba, TRUE); - return -1; - } - - if (camel_verbose_debug) { - fprintf (stderr, "received: "); - fwrite (ba->data, 1, ba->len, stderr); - } - - /* camel-imap-command.c:imap_read_untagged expects the CRLFs - to be stripped off and be nul-terminated *sigh* */ - nread = ba->len - 1; - ba->data[nread] = '\0'; - if (ba->data[nread - 1] == '\r') { - ba->data[nread - 1] = '\0'; - nread--; - } - - *dest = ba->data; - g_byte_array_free (ba, FALSE); - - return nread; -} diff --git a/camel/providers/imap/camel-imap-store.h b/camel/providers/imap/camel-imap-store.h deleted file mode 100644 index b1e3226969..0000000000 --- a/camel/providers/imap/camel-imap-store.h +++ /dev/null @@ -1,149 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-store.h : class for an imap store */ - -/* - * Authors: Jeffrey Stedfast <fejj@ximian.com> - * - * Copyright (C) 2000 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_IMAP_STORE_H -#define CAMEL_IMAP_STORE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include "camel-imap-types.h" -#include <camel/camel-disco-store.h> - -#ifdef ENABLE_THREADS -#include <libedataserver/e-msgport.h> - -typedef struct _CamelImapMsg CamelImapMsg; - -struct _CamelImapMsg { - EMsg msg; - - void (*receive)(CamelImapStore *store, struct _CamelImapMsg *m); - void (*free)(CamelImapStore *store, struct _CamelImapMsg *m); -}; - -CamelImapMsg *camel_imap_msg_new(void (*receive)(CamelImapStore *store, struct _CamelImapMsg *m), - void (*free)(CamelImapStore *store, struct _CamelImapMsg *m), - size_t size); -void camel_imap_msg_queue(CamelImapStore *store, CamelImapMsg *msg); - -#endif - -#define CAMEL_IMAP_STORE_TYPE (camel_imap_store_get_type ()) -#define CAMEL_IMAP_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAP_STORE_TYPE, CamelImapStore)) -#define CAMEL_IMAP_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAP_STORE_TYPE, CamelImapStoreClass)) -#define CAMEL_IS_IMAP_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAP_STORE_TYPE)) - -enum { - CAMEL_IMAP_STORE_ARG_FIRST = CAMEL_DISCO_STORE_ARG_FIRST + 100, - CAMEL_IMAP_STORE_ARG_NAMESPACE, - CAMEL_IMAP_STORE_ARG_OVERRIDE_NAMESPACE, - CAMEL_IMAP_STORE_ARG_CHECK_ALL, - CAMEL_IMAP_STORE_ARG_FILTER_INBOX, - CAMEL_IMAP_STORE_ARG_FILTER_JUNK, - CAMEL_IMAP_STORE_ARG_FILTER_JUNK_INBOX, -}; - -#define CAMEL_IMAP_STORE_NAMESPACE (CAMEL_IMAP_STORE_ARG_NAMESPACE | CAMEL_ARG_STR) -#define CAMEL_IMAP_STORE_OVERRIDE_NAMESPACE (CAMEL_IMAP_STORE_ARG_OVERRIDE_NAMESPACE | CAMEL_ARG_INT) -#define CAMEL_IMAP_STORE_CHECK_ALL (CAMEL_IMAP_STORE_ARG_CHECK_ALL | CAMEL_ARG_INT) -#define CAMEL_IMAP_STORE_FILTER_INBOX (CAMEL_IMAP_STORE_ARG_FILTER_INBOX | CAMEL_ARG_INT) -#define CAMEL_IMAP_STORE_FILTER_JUNK (CAMEL_IMAP_STORE_ARG_FILTER_JUNK | CAMEL_ARG_BOO) -#define CAMEL_IMAP_STORE_FILTER_JUNK_INBOX (CAMEL_IMAP_STORE_ARG_FILTER_JUNK_INBOX | CAMEL_ARG_BOO) - -/* CamelFolderInfo flags */ -#define CAMEL_IMAP_FOLDER_MARKED (1<<16) -#define CAMEL_IMAP_FOLDER_UNMARKED (1<<17) - -typedef enum { - IMAP_LEVEL_UNKNOWN, - IMAP_LEVEL_IMAP4, - IMAP_LEVEL_IMAP4REV1 -} CamelImapServerLevel; - -#define IMAP_CAPABILITY_IMAP4 (1 << 0) -#define IMAP_CAPABILITY_IMAP4REV1 (1 << 1) -#define IMAP_CAPABILITY_STATUS (1 << 2) -#define IMAP_CAPABILITY_NAMESPACE (1 << 3) -#define IMAP_CAPABILITY_UIDPLUS (1 << 4) -#define IMAP_CAPABILITY_LITERALPLUS (1 << 5) -#define IMAP_CAPABILITY_STARTTLS (1 << 6) -#define IMAP_CAPABILITY_useful_lsub (1 << 7) -#define IMAP_CAPABILITY_utf8_search (1 << 8) - -#define IMAP_PARAM_OVERRIDE_NAMESPACE (1 << 0) -#define IMAP_PARAM_CHECK_ALL (1 << 1) -#define IMAP_PARAM_FILTER_INBOX (1 << 2) -#define IMAP_PARAM_FILTER_JUNK (1 << 3) -#define IMAP_PARAM_FILTER_JUNK_INBOX (1 << 4) - -struct _CamelImapStore { - CamelDiscoStore parent_object; - - CamelStream *istream; - CamelStream *ostream; - - struct _CamelImapStoreSummary *summary; - - /* Information about the command channel / connection status */ - guint connected:1; - guint preauthed:1; - char tag_prefix; - guint32 command; - CamelFolder *current_folder; - - /* Information about the server */ - CamelImapServerLevel server_level; - guint32 capabilities, parameters; - guint braindamaged:1; - /* NB: namespace should be handled by summary->namespace */ - char *namespace, dir_sep, *base_url, *storage_path; - GHashTable *authtypes; - - guint renaming:1; -}; - - -typedef struct { - CamelDiscoStoreClass parent_class; - -} CamelImapStoreClass; - - -/* Standard Camel function */ -CamelType camel_imap_store_get_type (void); - - -gboolean camel_imap_store_connected (CamelImapStore *store, CamelException *ex); - -ssize_t camel_imap_store_readline (CamelImapStore *store, char **dest, CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_IMAP_STORE_H */ diff --git a/camel/providers/imap/camel-imap-summary.c b/camel/providers/imap/camel-imap-summary.c deleted file mode 100644 index 3e1d024ab4..0000000000 --- a/camel/providers/imap/camel-imap-summary.c +++ /dev/null @@ -1,276 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: - * Michael Zucchi <notzed@ximian.com> - * Dan Winship <danw@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/stat.h> -#include <sys/uio.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> - -#include "camel-imap-summary.h" -#include "camel-file-utils.h" - -#define CAMEL_IMAP_SUMMARY_VERSION (1) - -static int summary_header_load (CamelFolderSummary *, FILE *); -static int summary_header_save (CamelFolderSummary *, FILE *); - -static CamelMessageInfo *message_info_load (CamelFolderSummary *s, FILE *in); -static int message_info_save (CamelFolderSummary *s, FILE *out, - CamelMessageInfo *info); -static CamelMessageContentInfo *content_info_load (CamelFolderSummary *s, FILE *in); -static int content_info_save (CamelFolderSummary *s, FILE *out, - CamelMessageContentInfo *info); - -static void camel_imap_summary_class_init (CamelImapSummaryClass *klass); -static void camel_imap_summary_init (CamelImapSummary *obj); - -static CamelFolderSummaryClass *camel_imap_summary_parent; - -CamelType -camel_imap_summary_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register( - camel_folder_summary_get_type(), "CamelImapSummary", - sizeof (CamelImapSummary), - sizeof (CamelImapSummaryClass), - (CamelObjectClassInitFunc) camel_imap_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_imap_summary_init, - NULL); - } - - return type; -} - -static CamelMessageInfo * -imap_message_info_clone(CamelFolderSummary *s, const CamelMessageInfo *mi) -{ - CamelImapMessageInfo *to; - const CamelImapMessageInfo *from = (const CamelImapMessageInfo *)mi; - - to = (CamelImapMessageInfo *)camel_imap_summary_parent->message_info_clone(s, mi); - to->server_flags = from->server_flags; - - /* FIXME: parent clone should do this */ - to->info.content = camel_folder_summary_content_info_new(s); - - return (CamelMessageInfo *)to; -} - -static void -camel_imap_summary_class_init (CamelImapSummaryClass *klass) -{ - CamelFolderSummaryClass *cfs_class = (CamelFolderSummaryClass *) klass; - - camel_imap_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS (camel_type_get_global_classfuncs (camel_folder_summary_get_type())); - - cfs_class->message_info_clone = imap_message_info_clone; - - cfs_class->summary_header_load = summary_header_load; - cfs_class->summary_header_save = summary_header_save; - cfs_class->message_info_load = message_info_load; - cfs_class->message_info_save = message_info_save; - cfs_class->content_info_load = content_info_load; - cfs_class->content_info_save = content_info_save; -} - -static void -camel_imap_summary_init (CamelImapSummary *obj) -{ - CamelFolderSummary *s = (CamelFolderSummary *)obj; - - /* subclasses need to set the right instance data sizes */ - s->message_info_size = sizeof(CamelImapMessageInfo); - s->content_info_size = sizeof(CamelImapMessageContentInfo); -} - -/** - * camel_imap_summary_new: - * @folder: Parent folder. - * @filename: the file to store the summary in. - * - * This will create a new CamelImapSummary object and read in the - * summary data from disk, if it exists. - * - * Return value: A new CamelImapSummary object. - **/ -CamelFolderSummary * -camel_imap_summary_new (struct _CamelFolder *folder, const char *filename) -{ - CamelFolderSummary *summary = CAMEL_FOLDER_SUMMARY (camel_object_new (camel_imap_summary_get_type ())); - - summary->folder = folder; - - camel_folder_summary_set_build_content (summary, TRUE); - camel_folder_summary_set_filename (summary, filename); - - if (camel_folder_summary_load (summary) == -1) { - camel_folder_summary_clear (summary); - camel_folder_summary_touch (summary); - } - - return summary; -} - -static int -summary_header_load (CamelFolderSummary *s, FILE *in) -{ - CamelImapSummary *ims = CAMEL_IMAP_SUMMARY (s); - - if (camel_imap_summary_parent->summary_header_load (s, in) == -1) - return -1; - - /* Legacy version */ - if (s->version == 0x30c) - return camel_file_util_decode_uint32(in, &ims->validity); - - /* Version 1 */ - if (camel_file_util_decode_fixed_int32(in, &ims->version) == -1 - || camel_file_util_decode_fixed_int32(in, &ims->validity) == -1) - return -1; - - if (ims->version > CAMEL_IMAP_SUMMARY_VERSION) { - g_warning("Unkown summary version\n"); - errno = EINVAL; - return -1; - } - - return 0; -} - -static int -summary_header_save (CamelFolderSummary *s, FILE *out) -{ - CamelImapSummary *ims = CAMEL_IMAP_SUMMARY(s); - - if (camel_imap_summary_parent->summary_header_save (s, out) == -1) - return -1; - - camel_file_util_encode_fixed_int32(out, CAMEL_IMAP_SUMMARY_VERSION); - - return camel_file_util_encode_fixed_int32(out, ims->validity); -} - -static CamelMessageInfo * -message_info_load (CamelFolderSummary *s, FILE *in) -{ - CamelMessageInfo *info; - CamelImapMessageInfo *iinfo; - - info = camel_imap_summary_parent->message_info_load (s, in); - if (info) { - iinfo = (CamelImapMessageInfo *)info; - - if (camel_file_util_decode_uint32 (in, &iinfo->server_flags) == -1) - goto error; - } - - return info; -error: - camel_message_info_free(info); - return NULL; -} - -static int -message_info_save (CamelFolderSummary *s, FILE *out, CamelMessageInfo *info) -{ - CamelImapMessageInfo *iinfo = (CamelImapMessageInfo *)info; - - if (camel_imap_summary_parent->message_info_save (s, out, info) == -1) - return -1; - - return camel_file_util_encode_uint32 (out, iinfo->server_flags); -} - - -static CamelMessageContentInfo * -content_info_load (CamelFolderSummary *s, FILE *in) -{ - if (fgetc (in)) - return camel_imap_summary_parent->content_info_load (s, in); - else - return camel_folder_summary_content_info_new (s); -} - -static int -content_info_save (CamelFolderSummary *s, FILE *out, - CamelMessageContentInfo *info) -{ - if (info->type) { - fputc (1, out); - return camel_imap_summary_parent->content_info_save (s, out, info); - } else - return fputc (0, out); -} - -void -camel_imap_summary_add_offline (CamelFolderSummary *summary, const char *uid, - CamelMimeMessage *message, - const CamelMessageInfo *info) -{ - CamelImapMessageInfo *mi; - const CamelFlag *flag; - const CamelTag *tag; - - /* Create summary entry */ - mi = (CamelImapMessageInfo *)camel_folder_summary_info_new_from_message (summary, message); - - /* Copy flags 'n' tags */ - mi->info.flags = camel_message_info_flags(info); - - flag = camel_message_info_user_flags(info); - while (flag) { - camel_message_info_set_user_flag((CamelMessageInfo *)mi, flag->name, TRUE); - flag = flag->next; - } - tag = camel_message_info_user_tags(info); - while (tag) { - camel_message_info_set_user_tag((CamelMessageInfo *)mi, tag->name, tag->value); - tag = tag->next; - } - - mi->info.size = camel_message_info_size(info); - mi->info.uid = g_strdup (uid); - - camel_folder_summary_add (summary, (CamelMessageInfo *)mi); -} - -void -camel_imap_summary_add_offline_uncached (CamelFolderSummary *summary, const char *uid, - const CamelMessageInfo *info) -{ - CamelImapMessageInfo *mi; - - mi = camel_message_info_clone(info); - mi->info.uid = g_strdup(uid); - camel_folder_summary_add (summary, (CamelMessageInfo *)mi); -} diff --git a/camel/providers/imap/camel-imap-summary.h b/camel/providers/imap/camel-imap-summary.h deleted file mode 100644 index 04fb9b829a..0000000000 --- a/camel/providers/imap/camel-imap-summary.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: - * Michael Zucchi <notzed@ximian.com> - * Dan Winship <danw@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_IMAP_SUMMARY_H -#define _CAMEL_IMAP_SUMMARY_H - -#include "camel-imap-types.h" -#include <camel/camel-folder-summary.h> -#include <camel/camel-exception.h> - -#define CAMEL_IMAP_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_imap_summary_get_type (), CamelImapSummary) -#define CAMEL_IMAP_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imap_summary_get_type (), CamelImapSummaryClass) -#define CAMEL_IS_IMAP_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_imap_summary_get_type ()) - -#define CAMEL_IMAP_SERVER_FLAGS (CAMEL_MESSAGE_ANSWERED | \ - CAMEL_MESSAGE_DELETED | \ - CAMEL_MESSAGE_DRAFT | \ - CAMEL_MESSAGE_FLAGGED | \ - CAMEL_MESSAGE_SEEN) - -#define CAMEL_IMAP_MESSAGE_RECENT (1 << 17) - -typedef struct _CamelImapSummaryClass CamelImapSummaryClass; - -typedef struct _CamelImapMessageContentInfo { - CamelMessageContentInfo info; - -} CamelImapMessageContentInfo; - -typedef struct _CamelImapMessageInfo { - CamelMessageInfoBase info; - - guint32 server_flags; -} CamelImapMessageInfo; - -struct _CamelImapSummary { - CamelFolderSummary parent; - - guint32 version; - guint32 validity; -}; - -struct _CamelImapSummaryClass { - CamelFolderSummaryClass parent_class; - -}; - -CamelType camel_imap_summary_get_type (void); -CamelFolderSummary *camel_imap_summary_new (struct _CamelFolder *folder, const char *filename); - -void camel_imap_summary_add_offline (CamelFolderSummary *summary, - const char *uid, - CamelMimeMessage *message, - const CamelMessageInfo *info); - -void camel_imap_summary_add_offline_uncached (CamelFolderSummary *summary, - const char *uid, - const CamelMessageInfo *info); - -#endif /* ! _CAMEL_IMAP_SUMMARY_H */ - diff --git a/camel/providers/imap/camel-imap-types.h b/camel/providers/imap/camel-imap-types.h deleted file mode 100644 index c5ea41acff..0000000000 --- a/camel/providers/imap/camel-imap-types.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-types.h: IMAP types */ - -/* - * Copyright (C) 2001 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_IMAP_TYPES_H -#define CAMEL_IMAP_TYPES_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-types.h" - -typedef struct _CamelImapFolder CamelImapFolder; -typedef struct _CamelImapMessageCache CamelImapMessageCache; -typedef struct _CamelImapResponse CamelImapResponse; -typedef struct _CamelImapSearch CamelImapSearch; -typedef struct _CamelImapStore CamelImapStore; -typedef struct _CamelImapSummary CamelImapSummary; - -#endif /* CAMEL_IMAP_TYPES_H */ diff --git a/camel/providers/imap/camel-imap-utils.c b/camel/providers/imap/camel-imap-utils.c deleted file mode 100644 index 06028ef79d..0000000000 --- a/camel/providers/imap/camel-imap-utils.c +++ /dev/null @@ -1,1429 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast <fejj@ximian.com> - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <ctype.h> -#include <stdio.h> -#include <string.h> -#include <time.h> -#include <errno.h> -#include <sys/types.h> -#include <dirent.h> -#include <sys/stat.h> -#include <unistd.h> - -#include "camel-imap-utils.h" -#include "camel-imap-summary.h" -#include "camel-imap-store.h" -#include "camel-folder.h" -#include "camel-string-utils.h" -#include "camel-utf8.h" - -#define d(x) - -#define SUBFOLDER_DIR_NAME "subfolders" -#define SUBFOLDER_DIR_NAME_LEN 10 - -const char * -imap_next_word (const char *buf) -{ - const char *word; - - /* skip over current word */ - word = buf; - while (*word && *word != ' ') - word++; - - /* skip over white space */ - while (*word && *word == ' ') - word++; - - return word; -} - - -static void -imap_namespace_destroy (struct _namespace *namespace) -{ - struct _namespace *node, *next; - - node = namespace; - while (node) { - next = node->next; - g_free (node->prefix); - g_free (node); - node = next; - } -} - -void -imap_namespaces_destroy (struct _namespaces *namespaces) -{ - if (namespaces) { - imap_namespace_destroy (namespaces->personal); - imap_namespace_destroy (namespaces->other); - imap_namespace_destroy (namespaces->shared); - g_free (namespaces); - } -} - -static gboolean -imap_namespace_decode (const char **in, struct _namespace **namespace) -{ - struct _namespace *list, *tail, *node; - const char *inptr; - char *astring; - size_t len; - - inptr = *in; - - list = NULL; - tail = (struct _namespace *) &list; - - if (g_ascii_strncasecmp (inptr, "NIL", 3) != 0) { - if (*inptr++ != '(') - goto exception; - - while (*inptr && *inptr != ')') { - if (*inptr++ != '(') - goto exception; - - node = g_new (struct _namespace, 1); - node->next = NULL; - - /* get the namespace prefix */ - astring = imap_parse_astring (&inptr, &len); - if (!astring) { - g_free (node); - goto exception; - } - - /* decode IMAP's modified UTF-7 into UTF-8 */ - node->prefix = imap_mailbox_decode (astring, len); - g_free (astring); - if (!node->prefix) { - g_free (node); - goto exception; - } - - tail->next = node; - tail = node; - - /* get the namespace directory delimiter */ - inptr = imap_next_word (inptr); - - if (!g_ascii_strncasecmp (inptr, "NIL", 3)) { - inptr = imap_next_word (inptr); - node->delim = '\0'; - } else if (*inptr++ == '"') { - if (*inptr == '\\') - inptr++; - - node->delim = *inptr++; - - if (*inptr++ != '"') - goto exception; - } else - goto exception; - - if (*inptr == ' ') { - /* parse extra flags... for now we - don't save them, but in the future - we may want to? */ - while (*inptr == ' ') - inptr++; - - while (*inptr && *inptr != ')') { - /* this should be a QSTRING or ATOM */ - inptr = imap_next_word (inptr); - if (*inptr == '(') { - /* skip over the param list */ - imap_skip_list (&inptr); - } - - while (*inptr == ' ') - inptr++; - } - } - - if (*inptr++ != ')') - goto exception; - - /* there shouldn't be spaces according to the - ABNF grammar, but we all know how closely - people follow specs */ - while (*inptr == ' ') - inptr++; - } - - if (*inptr == ')') - inptr++; - } else { - inptr += 3; - } - - *in = inptr; - *namespace = list; - - return TRUE; - - exception: - - /* clean up any namespaces we may have allocated */ - imap_namespace_destroy (list); - - return FALSE; -} - -#if d(!)0 -static void -namespace_dump (struct _namespace *namespace) -{ - struct _namespace *node; - - if (namespace) { - printf ("("); - node = namespace; - while (node) { - printf ("(\"%s\" ", node->prefix); - if (node->delim) - printf ("\"%c\")", node->delim); - else - printf ("NUL)"); - - node = node->next; - if (node) - printf (" "); - } - - printf (")"); - } else { - printf ("NIL"); - } -} - -static void -namespaces_dump (struct _namespaces *namespaces) -{ - printf ("namespace dump: "); - namespace_dump (namespaces->personal); - printf (" "); - namespace_dump (namespaces->other); - printf (" "); - namespace_dump (namespaces->shared); - printf ("\n"); -} -#endif - -struct _namespaces * -imap_parse_namespace_response (const char *response) -{ - struct _namespaces *namespaces; - const char *inptr; - - d(printf ("parsing: %s\n", response)); - - if (*response != '*') - return NULL; - - inptr = imap_next_word (response); - if (g_ascii_strncasecmp (inptr, "NAMESPACE", 9) != 0) - return NULL; - - inptr = imap_next_word (inptr); - - namespaces = g_new (struct _namespaces, 1); - namespaces->personal = NULL; - namespaces->other = NULL; - namespaces->shared = NULL; - - if (!imap_namespace_decode (&inptr, &namespaces->personal)) - goto exception; - - if (*inptr != ' ') - goto exception; - - while (*inptr == ' ') - inptr++; - - if (!imap_namespace_decode (&inptr, &namespaces->other)) - goto exception; - - if (*inptr != ' ') - goto exception; - - while (*inptr == ' ') - inptr++; - - if (!imap_namespace_decode (&inptr, &namespaces->shared)) - goto exception; - - d(namespaces_dump (namespaces)); - - return namespaces; - - exception: - - imap_namespaces_destroy (namespaces); - - return NULL; -} - -/** - * imap_parse_list_response: - * @store: the IMAP store whose list response we're parsing - * @buf: the LIST or LSUB response - * @flags: a pointer to a variable to store the flags in, or %NULL - * @sep: a pointer to a variable to store the hierarchy separator in, or %NULL - * @folder: a pointer to a variable to store the folder name in, or %NULL - * - * Parses a LIST or LSUB response and returns the desired parts of it. - * If @folder is non-%NULL, its value must be freed by the caller. - * - * Return value: whether or not the response was successfully parsed. - **/ -gboolean -imap_parse_list_response (CamelImapStore *store, const char *buf, int *flags, char *sep, char **folder) -{ - gboolean is_lsub = FALSE; - const char *word; - size_t len; - - if (*buf != '*') - return FALSE; - - word = imap_next_word (buf); - if (g_ascii_strncasecmp (word, "LIST", 4) && g_ascii_strncasecmp (word, "LSUB", 4)) - return FALSE; - - /* check if we are looking at an LSUB response */ - if (word[1] == 'S' || word[1] == 's') - is_lsub = TRUE; - - /* get the flags */ - word = imap_next_word (word); - if (*word != '(') - return FALSE; - - if (flags) - *flags = 0; - - word++; - while (*word != ')') { - len = strcspn (word, " )"); - if (flags) { - if (!g_ascii_strncasecmp (word, "\\NoInferiors", len)) - *flags |= CAMEL_FOLDER_NOINFERIORS; - else if (!g_ascii_strncasecmp (word, "\\NoSelect", len)) - *flags |= CAMEL_FOLDER_NOSELECT; - else if (!g_ascii_strncasecmp (word, "\\Marked", len)) - *flags |= CAMEL_IMAP_FOLDER_MARKED; - else if (!g_ascii_strncasecmp (word, "\\Unmarked", len)) - *flags |= CAMEL_IMAP_FOLDER_UNMARKED; - else if (!g_ascii_strncasecmp (word, "\\HasChildren", len)) - *flags |= CAMEL_FOLDER_CHILDREN; - else if (!g_ascii_strncasecmp (word, "\\HasNoChildren", len)) - *flags |= CAMEL_FOLDER_NOCHILDREN; - } - - word += len; - while (*word == ' ') - word++; - } - - /* get the directory separator */ - word = imap_next_word (word); - if (!strncmp (word, "NIL", 3)) { - if (sep) - *sep = '\0'; - } else if (*word++ == '"') { - if (*word == '\\') - word++; - if (sep) - *sep = *word; - word++; - if (*word++ != '"') - return FALSE; - } else - return FALSE; - - if (folder) { - char *astring; - - /* get the folder name */ - word = imap_next_word (word); - astring = imap_parse_astring (&word, &len); - if (!astring) - return FALSE; - - *folder = astring; -#if 0 - char *mailbox; - - mailbox = imap_mailbox_decode (astring, strlen (astring)); - g_free (astring); - if (!mailbox) - return FALSE; - - /* Kludge around Courier imap's LSUB response for INBOX when it - * isn't subscribed to. - * - * Ignore any \Noselect flags for INBOX when parsing - * an LSUB response to work around the following response: - * - * * LSUB (\Noselect \HasChildren) "." "INBOX" - * - * Fixes bug #28929 (albeight in a very dodgy way imho, but what - * can ya do when ya got the ignorance of marketing breathing - * down your neck?) - */ - if (is_lsub && flags && !g_ascii_strcasecmp (mailbox, "INBOX")) - *flags &= ~CAMEL_FOLDER_NOSELECT; - - *folder = mailbox; -#endif - } - - return TRUE; -} - - -/** - * imap_parse_folder_name: - * @store: - * @folder_name: - * - * Return an array of folder paths representing the folder heirarchy. - * For example: - * Full/Path/"to / from"/Folder - * Results in: - * Full, Full/Path, Full/Path/"to / from", Full/Path/"to / from"/Folder - **/ -char ** -imap_parse_folder_name (CamelImapStore *store, const char *folder_name) -{ - GPtrArray *heirarchy; - char **paths; - const char *p; - - p = folder_name; - if (*p == store->dir_sep) - p++; - - heirarchy = g_ptr_array_new (); - - while (*p) { - if (*p == '"') { - p++; - while (*p && *p != '"') - p++; - if (*p) - p++; - continue; - } - - if (*p == store->dir_sep) - g_ptr_array_add (heirarchy, g_strndup (folder_name, p - folder_name)); - - p++; - } - - g_ptr_array_add (heirarchy, g_strdup (folder_name)); - g_ptr_array_add (heirarchy, NULL); - - paths = (char **) heirarchy->pdata; - g_ptr_array_free (heirarchy, FALSE); - - return paths; -} - -char * -imap_create_flag_list (guint32 flags) -{ - GString *gstr; - char *flag_list; - - gstr = g_string_new ("("); - - if (flags & CAMEL_MESSAGE_ANSWERED) - g_string_append (gstr, "\\Answered "); - if (flags & CAMEL_MESSAGE_DELETED) - g_string_append (gstr, "\\Deleted "); - if (flags & CAMEL_MESSAGE_DRAFT) - g_string_append (gstr, "\\Draft "); - if (flags & CAMEL_MESSAGE_FLAGGED) - g_string_append (gstr, "\\Flagged "); - if (flags & CAMEL_MESSAGE_SEEN) - g_string_append (gstr, "\\Seen "); - - if (gstr->str[gstr->len - 1] == ' ') - gstr->str[gstr->len - 1] = ')'; - else - g_string_append_c (gstr, ')'); - - flag_list = gstr->str; - g_string_free (gstr, FALSE); - return flag_list; -} - -guint32 -imap_parse_flag_list (char **flag_list_p) -{ - char *flag_list = *flag_list_p; - guint32 flags = 0; - int len; - - if (*flag_list++ != '(') { - *flag_list_p = NULL; - return 0; - } - - while (*flag_list && *flag_list != ')') { - len = strcspn (flag_list, " )"); - if (!g_ascii_strncasecmp (flag_list, "\\Answered", len)) - flags |= CAMEL_MESSAGE_ANSWERED; - else if (!g_ascii_strncasecmp (flag_list, "\\Deleted", len)) - flags |= CAMEL_MESSAGE_DELETED; - else if (!g_ascii_strncasecmp (flag_list, "\\Draft", len)) - flags |= CAMEL_MESSAGE_DRAFT; - else if (!g_ascii_strncasecmp (flag_list, "\\Flagged", len)) - flags |= CAMEL_MESSAGE_FLAGGED; - else if (!g_ascii_strncasecmp (flag_list, "\\Seen", len)) - flags |= CAMEL_MESSAGE_SEEN; - else if (!g_ascii_strncasecmp (flag_list, "\\Recent", len)) - flags |= CAMEL_IMAP_MESSAGE_RECENT; - else if (!g_ascii_strncasecmp(flag_list, "\\*", len)) - flags |= CAMEL_MESSAGE_USER; - - flag_list += len; - if (*flag_list == ' ') - flag_list++; - } - - if (*flag_list++ != ')') { - *flag_list_p = NULL; - return 0; - } - - *flag_list_p = flag_list; - return flags; -} - -/* - From rfc2060 - -ATOM_CHAR ::= <any CHAR except atom_specials> - -atom_specials ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards / - quoted_specials / resp_secials - -CHAR ::= <any 7-bit US-ASCII character except NUL, - 0x01 - 0x7f> - -CTL ::= <any ASCII control character and DEL, - 0x00 - 0x1f, 0x7f> - -SPACE ::= <ASCII SP, space, 0x20> - -list_wildcards ::= "%" / "*" - -quoted_specials ::= <"> / "\" - -resp_specials ::= "]" -*/ - -static unsigned char imap_atom_specials[256] = { -/* 00 */0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 10 */0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 20 */0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, -/* 30 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/* 40 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/* 50 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, -/* 60 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/* 70 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; - -#define imap_is_atom_char(c) ((imap_atom_specials[(c)&0xff] & 0x01) != 0) - -gboolean -imap_is_atom(const char *in) -{ - register unsigned char c; - register const char *p = in; - - while ((c = (unsigned char)*p)) { - if (!imap_is_atom_char(c)) - return FALSE; - p++; - } - - /* check for empty string */ - return p!=in; -} - -/** - * imap_parse_string_generic: - * @str_p: a pointer to a string - * @len: a pointer to a size_t to return the length in - * @type: type of string (#IMAP_STRING, #IMAP_ASTRING, or #IMAP_NSTRING) - * to parse. - * - * This parses an IMAP "string" (quoted string or literal), "nstring" - * (NIL or string), or "astring" (atom or string) starting at *@str_p. - * On success, *@str_p will point to the first character after the end - * of the string, and *@len will contain the length of the returned - * string. On failure, *@str_p will be set to %NULL. - * - * This assumes that the string is in the form returned by - * camel_imap_command(): that line breaks are indicated by LF rather - * than CRLF. - * - * Return value: the parsed string, or %NULL if a NIL or no string - * was parsed. (In the former case, *@str_p will be %NULL; in the - * latter, it will point to the character after the NIL.) - **/ -char * -imap_parse_string_generic (const char **str_p, size_t *len, int type) -{ - const char *str = *str_p; - char *out; - - if (!str) - return NULL; - else if (*str == '"') { - char *p; - size_t size; - - str++; - size = strcspn (str, "\"") + 1; - p = out = g_malloc (size); - - /* a quoted string cannot be broken into multiple lines */ - while (*str && *str != '"' && *str != '\n') { - if (*str == '\\') - str++; - *p++ = *str++; - if (p - out == size) { - out = g_realloc (out, size * 2); - p = out + size; - size *= 2; - } - } - if (*str != '"') { - *str_p = NULL; - g_free (out); - return NULL; - } - *p = '\0'; - *str_p = str + 1; - *len = strlen (out); - return out; - } else if (*str == '{') { - *len = strtoul (str + 1, (char **)&str, 10); - if (*str++ != '}' || *str++ != '\n' || strlen (str) < *len) { - *str_p = NULL; - return NULL; - } - - out = g_strndup (str, *len); - *str_p = str + *len; - return out; - } else if (type == IMAP_NSTRING && !g_ascii_strncasecmp (str, "nil", 3)) { - *str_p += 3; - *len = 0; - return NULL; - } else if (type == IMAP_ASTRING && imap_is_atom_char ((unsigned char)*str)) { - while (imap_is_atom_char ((unsigned char) *str)) - str++; - - *len = str - *str_p; - out = g_strndup (*str_p, *len); - *str_p += *len; - return out; - } else { - *str_p = NULL; - return NULL; - } -} - -static inline void -skip_char (const char **in, char ch) -{ - if (*in && **in == ch) - *in = *in + 1; - else - *in = NULL; -} - -/* Skip atom, string, or number */ -static void -skip_asn (const char **str_p) -{ - const char *str = *str_p; - - if (!str) - return; - else if (*str == '"') { - while (*++str && *str != '"') { - if (*str == '\\') { - str++; - if (!*str) - break; - } - } - if (*str == '"') - *str_p = str + 1; - else - *str_p = NULL; - } else if (*str == '{') { - unsigned long len; - - len = strtoul (str + 1, (char **) &str, 10); - if (*str != '}' || *(str + 1) != '\n' || - strlen (str + 2) < len) { - *str_p = NULL; - return; - } - *str_p = str + 2 + len; - } else { - /* We assume the string is well-formed and don't - * bother making sure it's a valid atom. - */ - while (*str && *str != ')' && *str != ' ') - str++; - *str_p = str; - } -} - -void -imap_skip_list (const char **str_p) -{ - skip_char (str_p, '('); - while (*str_p && **str_p != ')') { - if (**str_p == '(') - imap_skip_list (str_p); - else - skip_asn (str_p); - if (*str_p && **str_p == ' ') - skip_char (str_p, ' '); - } - skip_char (str_p, ')'); -} - -static int -parse_params (const char **parms_p, CamelContentType *type) -{ - const char *parms = *parms_p; - char *name, *value; - size_t len; - - if (!g_ascii_strncasecmp (parms, "nil", 3)) { - *parms_p += 3; - return 0; - } - - if (*parms++ != '(') - return -1; - - while (parms && *parms != ')') { - name = imap_parse_nstring (&parms, &len); - skip_char (&parms, ' '); - value = imap_parse_nstring (&parms, &len); - - if (name && value) - camel_content_type_set_param (type, name, value); - g_free (name); - g_free (value); - - if (parms && *parms == ' ') - parms++; - } - - if (!parms || *parms++ != ')') - return -1; - - *parms_p = parms; - - return 0; -} - - -static CamelMessageContentInfo * -imap_body_decode (const char **in, CamelMessageContentInfo *ci, CamelFolder *folder, GPtrArray *cis) -{ - const char *inptr = *in; - CamelMessageContentInfo *child = NULL; - char *type, *subtype, *id = NULL; - CamelContentType *ctype = NULL; - char *description = NULL; - char *encoding = NULL; - size_t len; - size_t size; - char *p; - - if (*inptr++ != '(') - return NULL; - - if (ci == NULL) { - ci = camel_folder_summary_content_info_new (folder->summary); - g_ptr_array_add (cis, ci); - } - - if (*inptr == '(') { - /* body_type_mpart */ - CamelMessageContentInfo *tail, *children = NULL; - - tail = (CamelMessageContentInfo *) &children; - - do { - if (!(child = imap_body_decode (&inptr, NULL, folder, cis))) - return NULL; - - child->parent = ci; - tail->next = child; - tail = child; - } while (*inptr == '('); - - if (*inptr++ != ' ') - return NULL; - - if (g_ascii_strncasecmp (inptr, "nil", 3) != 0) { - subtype = imap_parse_string (&inptr, &len); - } else { - subtype = NULL; - inptr += 3; - } - - ctype = camel_content_type_new ("multipart", subtype ? subtype : "mixed"); - g_free (subtype); - - if (*inptr++ != ')') { - camel_content_type_unref (ctype); - return NULL; - } - - ci->type = ctype; - ci->childs = children; - } else { - /* body_type_1part */ - if (g_ascii_strncasecmp (inptr, "nil", 3) != 0) { - type = imap_parse_string (&inptr, &len); - if (inptr == NULL) - return NULL; - } else { - return NULL; - } - - if (*inptr++ != ' ') { - g_free (type); - return NULL; - } - - if (g_ascii_strncasecmp (inptr, "nil", 3) != 0) { - subtype = imap_parse_string (&inptr, &len); - if (inptr == NULL) { - g_free (type); - return NULL; - } - } else { - if (!g_ascii_strcasecmp (type, "text")) - subtype = g_strdup ("plain"); - else - subtype = NULL; - inptr += 3; - } - - camel_strdown (type); - camel_strdown (subtype); - ctype = camel_content_type_new (type, subtype); - g_free (subtype); - g_free (type); - - if (*inptr++ != ' ') - goto exception; - - /* content-type params */ - if (parse_params (&inptr, ctype) == -1) - goto exception; - - if (*inptr++ != ' ') - goto exception; - - /* content-id */ - if (g_ascii_strncasecmp (inptr, "nil", 3) != 0) { - id = imap_parse_string (&inptr, &len); - if (inptr == NULL) - goto exception; - } else - inptr += 3; - - if (*inptr++ != ' ') - goto exception; - - /* description */ - if (g_ascii_strncasecmp (inptr, "nil", 3) != 0) { - description = imap_parse_string (&inptr, &len); - if (inptr == NULL) - goto exception; - } else - inptr += 3; - - if (*inptr++ != ' ') - goto exception; - - /* encoding */ - if (g_ascii_strncasecmp (inptr, "nil", 3) != 0) { - encoding = imap_parse_string (&inptr, &len); - if (inptr == NULL) - goto exception; - } else - inptr += 3; - - if (*inptr++ != ' ') - goto exception; - - /* size */ - size = strtoul ((const char *) inptr, &p, 10); - inptr = (const unsigned char *) p; - - if (camel_content_type_is (ctype, "message", "rfc822")) { - /* body_type_msg */ - if (*inptr++ != ' ') - goto exception; - - /* envelope */ - imap_skip_list (&inptr); - - if (*inptr++ != ' ') - goto exception; - - /* body */ - if (!(child = imap_body_decode (&inptr, NULL, folder, cis))) - goto exception; - child->parent = ci; - - if (*inptr++ != ' ') - goto exception; - - /* lines */ - strtoul ((const char *) inptr, &p, 10); - inptr = (const unsigned char *) p; - } else if (camel_content_type_is (ctype, "text", "*")) { - if (*inptr++ != ' ') - goto exception; - - /* lines */ - strtoul ((const char *) inptr, &p, 10); - inptr = (const unsigned char *) p; - } else { - /* body_type_basic */ - } - - if (*inptr++ != ')') - goto exception; - - ci->type = ctype; - ci->id = id; - ci->description = description; - ci->encoding = encoding; - ci->size = size; - ci->childs = child; - } - - *in = inptr; - - return ci; - - exception: - - camel_content_type_unref (ctype); - g_free (id); - g_free (description); - g_free (encoding); - - return NULL; -} - - -/** - * imap_parse_body: - * @body_p: pointer to the start of an IMAP "body" - * @folder: an imap folder - * @ci: a CamelMessageContentInfo to fill in - * - * This fills in @ci with data from *@body_p. On success *@body_p - * will point to the character after the body. On failure, it will be - * set to %NULL and @ci will be unchanged. - **/ -void -imap_parse_body (const char **body_p, CamelFolder *folder, - CamelMessageContentInfo *ci) -{ - const char *inptr = *body_p; - CamelMessageContentInfo *child; - GPtrArray *children; - int i; - - if (!inptr || *inptr != '(') { - *body_p = NULL; - return; - } - - children = g_ptr_array_new (); - - if (!(imap_body_decode (&inptr, ci, folder, children))) { - for (i = 0; i < children->len; i++) { - child = children->pdata[i]; - - /* content_info_free will free all the child - * nodes, but we don't want that. */ - child->next = NULL; - child->parent = NULL; - child->childs = NULL; - - camel_folder_summary_content_info_free (folder->summary, child); - } - *body_p = NULL; - } else { - *body_p = inptr; - } - - g_ptr_array_free (children, TRUE); -} - - -/** - * imap_quote_string: - * @str: the string to quote, which must not contain CR or LF - * - * Return value: an IMAP "quoted" corresponding to the string, which - * the caller must free. - **/ -char * -imap_quote_string (const char *str) -{ - const char *p; - char *quoted, *q; - int len; - - g_assert (strchr (str, '\r') == NULL); - - len = strlen (str); - p = str; - while ((p = strpbrk (p, "\"\\"))) { - len++; - p++; - } - - quoted = q = g_malloc (len + 3); - *q++ = '"'; - for (p = str; *p; ) { - if (strchr ("\"\\", *p)) - *q++ = '\\'; - *q++ = *p++; - } - *q++ = '"'; - *q = '\0'; - - return quoted; -} - - -static inline unsigned long -get_summary_uid_numeric (CamelFolderSummary *summary, int index) -{ - CamelMessageInfo *info; - unsigned long uid; - - info = camel_folder_summary_index (summary, index); - uid = strtoul (camel_message_info_uid (info), NULL, 10); - camel_message_info_free(info); - return uid; -} - -/* the max number of chars that an unsigned 32-bit int can be is 10 chars plus 1 for a possible : */ -#define UID_SET_FULL(setlen, maxlen) (maxlen > 0 ? setlen + 11 >= maxlen : FALSE) - -/** - * imap_uid_array_to_set: - * @summary: summary for the folder the UIDs come from - * @uids: a (sorted) array of UIDs - * @uid: uid index to start at - * @maxlen: max length of the set string (or -1 for infinite) - * @lastuid: index offset of the last uid used - * - * Creates an IMAP "set" up to @maxlen bytes long, covering the listed - * UIDs starting at index @uid and not covering any UIDs that are in - * @summary but not in @uids. It doesn't actually require that all (or - * any) of the UIDs be in @summary. - * - * After calling, @lastuid will be set the index of the first uid - * *not* included in the returned set string. - * - * Note: @uids MUST be in sorted order for this code to work properly. - * - * Return value: the set, which the caller must free with g_free() - **/ -char * -imap_uid_array_to_set (CamelFolderSummary *summary, GPtrArray *uids, int uid, ssize_t maxlen, int *lastuid) -{ - unsigned long last_uid, next_summary_uid, this_uid; - gboolean range = FALSE; - int si, scount; - GString *gset; - char *set; - - g_return_val_if_fail (uids->len > uid, NULL); - - gset = g_string_new (uids->pdata[uid]); - last_uid = strtoul (uids->pdata[uid], NULL, 10); - next_summary_uid = 0; - scount = camel_folder_summary_count (summary); - - for (uid++, si = 0; uid < uids->len && !UID_SET_FULL (gset->len, maxlen); uid++) { - /* Find the next UID in the summary after the one we - * just wrote out. - */ - for ( ; last_uid >= next_summary_uid && si < scount; si++) - next_summary_uid = get_summary_uid_numeric (summary, si); - if (last_uid >= next_summary_uid) - next_summary_uid = (unsigned long) -1; - - /* Now get the next UID from @uids */ - this_uid = strtoul (uids->pdata[uid], NULL, 10); - if (this_uid == next_summary_uid || this_uid == last_uid + 1) - range = TRUE; - else { - if (range) { - g_string_append_printf (gset, ":%lu", last_uid); - range = FALSE; - } - g_string_append_printf (gset, ",%lu", this_uid); - } - - last_uid = this_uid; - } - - if (range) - g_string_append_printf (gset, ":%lu", last_uid); - - *lastuid = uid; - - set = gset->str; - g_string_free (gset, FALSE); - - return set; -} - -/** - * imap_uid_set_to_array: - * @summary: summary for the folder the UIDs come from - * @uids: a pointer to the start of an IMAP "set" of UIDs - * - * Fills an array with the UIDs corresponding to @uids and @summary. - * There can be text after the uid set in @uids, which will be - * ignored. - * - * If @uids specifies a range of UIDs that extends outside the range - * of @summary, the function will assume that all of the "missing" UIDs - * do exist. - * - * Return value: the array of uids, which the caller must free with - * imap_uid_array_free(). (Or %NULL if the uid set can't be parsed.) - **/ -GPtrArray * -imap_uid_set_to_array (CamelFolderSummary *summary, const char *uids) -{ - GPtrArray *arr; - char *p, *q; - unsigned long uid, suid; - int si, scount; - - arr = g_ptr_array_new (); - scount = camel_folder_summary_count (summary); - - p = (char *)uids; - si = 0; - do { - uid = strtoul (p, &q, 10); - if (p == q) - goto lose; - g_ptr_array_add (arr, g_strndup (p, q - p)); - - if (*q == ':') { - /* Find the summary entry for the UID after the one - * we just saw. - */ - while (++si < scount) { - suid = get_summary_uid_numeric (summary, si); - if (suid > uid) - break; - } - if (si >= scount) - suid = uid + 1; - - uid = strtoul (q + 1, &p, 10); - if (p == q + 1) - goto lose; - - /* Add each summary UID until we find one - * larger than the end of the range - */ - while (suid <= uid) { - g_ptr_array_add (arr, g_strdup_printf ("%lu", suid)); - if (++si < scount) - suid = get_summary_uid_numeric (summary, si); - else - suid++; - } - } else - p = q; - } while (*p++ == ','); - - return arr; - - lose: - g_warning ("Invalid uid set %s", uids); - imap_uid_array_free (arr); - return NULL; -} - -/** - * imap_uid_array_free: - * @arr: an array returned from imap_uid_set_to_array() - * - * Frees @arr - **/ -void -imap_uid_array_free (GPtrArray *arr) -{ - int i; - - for (i = 0; i < arr->len; i++) - g_free (arr->pdata[i]); - g_ptr_array_free (arr, TRUE); -} - -char * -imap_concat (CamelImapStore *imap_store, const char *prefix, const char *suffix) -{ - size_t len; - - len = strlen (prefix); - if (len == 0 || prefix[len - 1] == imap_store->dir_sep) - return g_strdup_printf ("%s%s", prefix, suffix); - else - return g_strdup_printf ("%s%c%s", prefix, imap_store->dir_sep, suffix); -} - -char * -imap_mailbox_encode (const unsigned char *in, size_t inlen) -{ - char *buf; - - buf = g_alloca (inlen + 1); - memcpy (buf, in, inlen); - buf[inlen] = 0; - - return camel_utf8_utf7 (buf); -} - -char * -imap_mailbox_decode (const unsigned char *in, size_t inlen) -{ - char *buf; - - buf = g_alloca (inlen + 1); - memcpy (buf, in, inlen); - buf[inlen] = 0; - - return camel_utf7_utf8 (buf); -} - -char * -imap_path_to_physical (const char *prefix, const char *vpath) -{ - const char *p, *newp; - char *dp; - char *ppath; - int ppath_len; - int prefix_len; - - while (*vpath == '/') - vpath++; - if (!prefix) - prefix = ""; - - /* Calculate the length of the real path. */ - ppath_len = strlen (vpath); - ppath_len++; /* For the ending zero. */ - - prefix_len = strlen (prefix); - ppath_len += prefix_len; - ppath_len++; /* For the separating slash. */ - - /* Take account of the fact that we need to translate every - * separator into `subfolders/'. - */ - p = vpath; - while (1) { - newp = strchr (p, '/'); - if (newp == NULL) - break; - - ppath_len += SUBFOLDER_DIR_NAME_LEN; - ppath_len++; /* For the separating slash. */ - - /* Skip consecutive slashes. */ - while (*newp == '/') - newp++; - - p = newp; - }; - - ppath = g_malloc (ppath_len); - dp = ppath; - - memcpy (dp, prefix, prefix_len); - dp += prefix_len; - *(dp++) = '/'; - - /* Copy the mangled path. */ - p = vpath; - while (1) { - newp = strchr (p, '/'); - if (newp == NULL) { - strcpy (dp, p); - break; - } - - memcpy (dp, p, newp - p + 1); /* `+ 1' to copy the slash too. */ - dp += newp - p + 1; - - memcpy (dp, SUBFOLDER_DIR_NAME, SUBFOLDER_DIR_NAME_LEN); - dp += SUBFOLDER_DIR_NAME_LEN; - - *(dp++) = '/'; - - /* Skip consecutive slashes. */ - while (*newp == '/') - newp++; - - p = newp; - } - - return ppath; -} - -static gboolean -find_folders_recursive (const char *physical_path, const char *path, - IMAPPathFindFoldersCallback callback, gpointer data) -{ - DIR *dir; - char *subfolder_directory_path; - gboolean ok; - - if (*path) { - if (!callback (physical_path, path, data)) - return FALSE; - - subfolder_directory_path = g_strdup_printf ("%s/%s", physical_path, SUBFOLDER_DIR_NAME); - } else { - /* On the top level, we have no folders and, - * consequently, no subfolder directory. - */ - - subfolder_directory_path = g_strdup (physical_path); - } - - /* Now scan the subfolders and load them. */ - dir = opendir (subfolder_directory_path); - if (dir == NULL) { - g_free (subfolder_directory_path); - return TRUE; - } - - ok = TRUE; - while (ok) { - struct stat file_stat; - struct dirent *dirent; - char *file_path; - char *new_path; - - dirent = readdir (dir); - if (dirent == NULL) - break; - - if (strcmp (dirent->d_name, ".") == 0 || strcmp (dirent->d_name, "..") == 0) - continue; - - file_path = g_strdup_printf ("%s/%s", subfolder_directory_path, - dirent->d_name); - - if (stat (file_path, &file_stat) < 0 || - ! S_ISDIR (file_stat.st_mode)) { - g_free (file_path); - continue; - } - - new_path = g_strdup_printf ("%s/%s", path, dirent->d_name); - - ok = find_folders_recursive (file_path, new_path, callback, data); - - g_free (file_path); - g_free (new_path); - } - - closedir (dir); - g_free (subfolder_directory_path); - - return ok; -} - -/** - * imap_path_find_folders: - * @prefix: directory to start from - * @callback: Callback to invoke on each folder - * @data: Data for @callback - * - * Walks the folder tree starting at @prefix and calls @callback - * on each folder. - * - * Return value: %TRUE on success, %FALSE if an error occurs at any point - **/ -gboolean -imap_path_find_folders (const char *prefix, IMAPPathFindFoldersCallback callback, gpointer data) -{ - return find_folders_recursive (prefix, "", callback, data); -} diff --git a/camel/providers/imap/camel-imap-utils.h b/camel/providers/imap/camel-imap-utils.h deleted file mode 100644 index 7278843a6b..0000000000 --- a/camel/providers/imap/camel-imap-utils.h +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast <fejj@ximian.com> - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef CAMEL_IMAP_UTILS_H -#define CAMEL_IMAP_UTILS_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include <sys/types.h> - -#include "camel-folder-summary.h" -#include "camel-imap-types.h" - -const char *imap_next_word (const char *buf); - -struct _namespace { - struct _namespace *next; - char *prefix; - char delim; -}; - -struct _namespaces { - struct _namespace *personal; - struct _namespace *other; - struct _namespace *shared; -}; - -void imap_namespaces_destroy (struct _namespaces *namespaces); -struct _namespaces *imap_parse_namespace_response (const char *response); - -gboolean imap_parse_list_response (CamelImapStore *store, const char *buf, int *flags, - char *sep, char **folder); - -char **imap_parse_folder_name (CamelImapStore *store, const char *folder_name); - -char *imap_create_flag_list (guint32 flags); -guint32 imap_parse_flag_list (char **flag_list); - - -enum { IMAP_STRING, IMAP_NSTRING, IMAP_ASTRING }; - -char *imap_parse_string_generic (const char **str_p, size_t *len, int type); - -#define imap_parse_string(str_p, len_p) \ - imap_parse_string_generic (str_p, len_p, IMAP_STRING) -#define imap_parse_nstring(str_p, len_p) \ - imap_parse_string_generic (str_p, len_p, IMAP_NSTRING) -#define imap_parse_astring(str_p, len_p) \ - imap_parse_string_generic (str_p, len_p, IMAP_ASTRING) - -void imap_parse_body (const char **body_p, CamelFolder *folder, - CamelMessageContentInfo *ci); - -gboolean imap_is_atom (const char *in); -char *imap_quote_string (const char *str); - -void imap_skip_list (const char **str_p); - -char *imap_uid_array_to_set (CamelFolderSummary *summary, GPtrArray *uids, int uid, ssize_t maxlen, int *lastuid); -GPtrArray *imap_uid_set_to_array (CamelFolderSummary *summary, const char *uids); -void imap_uid_array_free (GPtrArray *arr); - -char *imap_concat (CamelImapStore *imap_store, const char *prefix, const char *suffix); -char *imap_namespace_concat (CamelImapStore *store, const char *name); - -char *imap_mailbox_encode (const unsigned char *in, size_t inlen); -char *imap_mailbox_decode (const unsigned char *in, size_t inlen); - -typedef gboolean (*IMAPPathFindFoldersCallback) (const char *physical_path, const char *path, gpointer user_data); - -char *imap_path_to_physical (const char *prefix, const char *vpath); -gboolean imap_path_find_folders (const char *prefix, IMAPPathFindFoldersCallback callback, gpointer data); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_IMAP_UTILS_H */ diff --git a/camel/providers/imap/camel-imap-wrapper.c b/camel/providers/imap/camel-imap-wrapper.c deleted file mode 100644 index 7ee496dd5f..0000000000 --- a/camel/providers/imap/camel-imap-wrapper.c +++ /dev/null @@ -1,187 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; -*- */ -/* camel-imap-wrapper.c: data wrapper for offline IMAP data */ - -/* - * Author: Dan Winship <danw@ximian.com> - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <errno.h> -#include <string.h> - -#include "camel-imap-folder.h" -#include "camel-imap-wrapper.h" -#include "camel-imap-private.h" -#include "camel-exception.h" -#include "camel-stream-filter.h" -#include "camel-mime-filter-basic.h" -#include "camel-mime-filter-crlf.h" -#include "camel-mime-filter-charset.h" -#include "camel-mime-part.h" - -static CamelDataWrapperClass *parent_class = NULL; - -/* Returns the class for a CamelDataWrapper */ -#define CDW_CLASS(so) CAMEL_DATA_WRAPPER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static ssize_t write_to_stream (CamelDataWrapper *imap_wrapper, CamelStream *stream); - -static void -camel_imap_wrapper_class_init (CamelImapWrapperClass *camel_imap_wrapper_class) -{ - CamelDataWrapperClass *camel_data_wrapper_class = - CAMEL_DATA_WRAPPER_CLASS (camel_imap_wrapper_class); - - parent_class = CAMEL_DATA_WRAPPER_CLASS (camel_type_get_global_classfuncs (camel_data_wrapper_get_type ())); - - /* virtual method override */ - camel_data_wrapper_class->write_to_stream = write_to_stream; -} - -static void -camel_imap_wrapper_finalize (CamelObject *object) -{ - CamelImapWrapper *imap_wrapper = CAMEL_IMAP_WRAPPER (object); - - if (imap_wrapper->folder) - camel_object_unref (CAMEL_OBJECT (imap_wrapper->folder)); - if (imap_wrapper->uid) - g_free (imap_wrapper->uid); - if (imap_wrapper->part) - g_free (imap_wrapper->part_spec); - -#ifdef ENABLE_THREADS - g_mutex_free (imap_wrapper->priv->lock); -#endif - g_free (imap_wrapper->priv); -} - -static void -camel_imap_wrapper_init (gpointer object, gpointer klass) -{ - CamelImapWrapper *imap_wrapper = CAMEL_IMAP_WRAPPER (object); - - imap_wrapper->priv = g_new0 (struct _CamelImapWrapperPrivate, 1); -#ifdef ENABLE_THREADS - imap_wrapper->priv->lock = g_mutex_new (); -#endif -} - -CamelType -camel_imap_wrapper_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register ( - CAMEL_DATA_WRAPPER_TYPE, - "CamelImapWrapper", - sizeof (CamelImapWrapper), - sizeof (CamelImapWrapperClass), - (CamelObjectClassInitFunc) camel_imap_wrapper_class_init, - NULL, - (CamelObjectInitFunc) camel_imap_wrapper_init, - (CamelObjectFinalizeFunc) camel_imap_wrapper_finalize); - } - - return type; -} - - -static void -imap_wrapper_hydrate (CamelImapWrapper *imap_wrapper, CamelStream *stream) -{ - CamelDataWrapper *data_wrapper = (CamelDataWrapper *) imap_wrapper; - - camel_object_ref (stream); - data_wrapper->stream = stream; - data_wrapper->offline = FALSE; - - camel_object_unref (imap_wrapper->folder); - imap_wrapper->folder = NULL; - g_free (imap_wrapper->uid); - imap_wrapper->uid = NULL; - g_free (imap_wrapper->part_spec); - imap_wrapper->part = NULL; -} - - -static ssize_t -write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) -{ - CamelImapWrapper *imap_wrapper = CAMEL_IMAP_WRAPPER (data_wrapper); - - CAMEL_IMAP_WRAPPER_LOCK (imap_wrapper, lock); - if (data_wrapper->offline) { - CamelStream *datastream; - - datastream = camel_imap_folder_fetch_data ( - imap_wrapper->folder, imap_wrapper->uid, - imap_wrapper->part_spec, FALSE, NULL); - if (!datastream) { - CAMEL_IMAP_WRAPPER_UNLOCK (imap_wrapper, lock); - errno = ENETUNREACH; - return -1; - } - - imap_wrapper_hydrate (imap_wrapper, datastream); - camel_object_unref (datastream); - } - CAMEL_IMAP_WRAPPER_UNLOCK (imap_wrapper, lock); - - return parent_class->write_to_stream (data_wrapper, stream); -} - - -CamelDataWrapper * -camel_imap_wrapper_new (CamelImapFolder *imap_folder, - CamelContentType *type, CamelTransferEncoding encoding, - const char *uid, const char *part_spec, - CamelMimePart *part) -{ - CamelImapWrapper *imap_wrapper; - CamelStream *stream; - - imap_wrapper = (CamelImapWrapper *)camel_object_new(camel_imap_wrapper_get_type()); - - camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (imap_wrapper), type); - ((CamelDataWrapper *)imap_wrapper)->offline = TRUE; - ((CamelDataWrapper *)imap_wrapper)->encoding = encoding; - - imap_wrapper->folder = imap_folder; - camel_object_ref (imap_folder); - imap_wrapper->uid = g_strdup (uid); - imap_wrapper->part_spec = g_strdup (part_spec); - - /* Don't ref this, it's our parent. */ - imap_wrapper->part = part; - - /* Try the cache. */ - stream = camel_imap_folder_fetch_data (imap_folder, uid, part_spec, - TRUE, NULL); - if (stream) { - imap_wrapper_hydrate (imap_wrapper, stream); - camel_object_unref (stream); - } - - return (CamelDataWrapper *)imap_wrapper; -} diff --git a/camel/providers/imap/camel-imap-wrapper.h b/camel/providers/imap/camel-imap-wrapper.h deleted file mode 100644 index bbb4c9468b..0000000000 --- a/camel/providers/imap/camel-imap-wrapper.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-wrapper.h: data wrapper for offline IMAP data */ - -/* - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_IMAP_WRAPPER_H -#define CAMEL_IMAP_WRAPPER_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include <camel/camel-data-wrapper.h> -#include "camel-imap-types.h" - -#define CAMEL_IMAP_WRAPPER_TYPE (camel_imap_wrapper_get_type ()) -#define CAMEL_IMAP_WRAPPER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAP_WRAPPER_TYPE, CamelImapWrapper)) -#define CAMEL_IMAP_WRAPPER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAP_WRAPPER_TYPE, CamelImapWrapperClass)) -#define CAMEL_IS_IMAP_WRAPPER(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAP_WRAPPER_TYPE)) - -typedef struct -{ - CamelDataWrapper parent_object; - - struct _CamelImapWrapperPrivate *priv; - - CamelImapFolder *folder; - char *uid, *part_spec; - CamelMimePart *part; -} CamelImapWrapper; - -typedef struct { - CamelDataWrapperClass parent_class; - -} CamelImapWrapperClass; - -/* Standard Camel function */ -CamelType camel_imap_wrapper_get_type (void); - -/* Constructor */ -CamelDataWrapper *camel_imap_wrapper_new (CamelImapFolder *imap_folder, - CamelContentType *type, - CamelTransferEncoding encoding, - const char *uid, - const char *part_spec, - CamelMimePart *part); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_DATA_WRAPPER_H */ diff --git a/camel/providers/imap/libcamelimap.urls b/camel/providers/imap/libcamelimap.urls deleted file mode 100644 index c301c0ffac..0000000000 --- a/camel/providers/imap/libcamelimap.urls +++ /dev/null @@ -1 +0,0 @@ -imap diff --git a/camel/providers/imap4/.cvsignore b/camel/providers/imap4/.cvsignore deleted file mode 100644 index 08f5ed37d8..0000000000 --- a/camel/providers/imap4/.cvsignore +++ /dev/null @@ -1,7 +0,0 @@ -Makefile -Makefile.in -*.o -*.lo -*.la -.deps -.libs diff --git a/camel/providers/imap4/Makefile.am b/camel/providers/imap4/Makefile.am deleted file mode 100644 index 3cdf897f6a..0000000000 --- a/camel/providers/imap4/Makefile.am +++ /dev/null @@ -1,42 +0,0 @@ -## Process this file with automake to produce Makefile.in - -camel_provider_LTLIBRARIES = libcamelimap4.la -camel_provider_DATA = libcamelimap4.urls - -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/e-util \ - -I$(top_srcdir) \ - $(CAMEL_CFLAGS) \ - $(GNOME_INCLUDEDIR) \ - $(GTK_INCLUDEDIR) \ - -DG_LOG_DOMAIN=\"camel-imap4-provider\" - -libcamelimap4_la_SOURCES = \ - camel-imap4-command.c \ - camel-imap4-command.h \ - camel-imap4-engine.c \ - camel-imap4-engine.h \ - camel-imap4-folder.c \ - camel-imap4-folder.h \ - camel-imap4-provider.c \ - camel-imap4-search.c \ - camel-imap4-search.h \ - camel-imap4-specials.c \ - camel-imap4-specials.h \ - camel-imap4-store.c \ - camel-imap4-store.h \ - camel-imap4-store-summary.c \ - camel-imap4-store-summary.h \ - camel-imap4-stream.c \ - camel-imap4-stream.h \ - camel-imap4-summary.c \ - camel-imap4-summary.h \ - camel-imap4-utils.c \ - camel-imap4-utils.h - -libcamelimap4_la_LDFLAGS = -avoid-version -module - -EXTRA_DIST = libcamelimap4.urls diff --git a/camel/providers/imap4/camel-imap4-command.c b/camel/providers/imap4/camel-imap4-command.c deleted file mode 100644 index e869bee9c3..0000000000 --- a/camel/providers/imap4/camel-imap4-command.c +++ /dev/null @@ -1,706 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include <camel/camel-stream-null.h> -#include <camel/camel-stream-filter.h> -#include <camel/camel-mime-filter-crlf.h> -#include <camel/camel-i18n.h> - -#include "camel-imap4-stream.h" -#include "camel-imap4-engine.h" -#include "camel-imap4-folder.h" -#include "camel-imap4-specials.h" - -#include "camel-imap4-command.h" - - -#define d(x) x - - -enum { - IMAP4_STRING_ATOM, - IMAP4_STRING_QSTRING, - IMAP4_STRING_LITERAL, -}; - -static int -imap4_string_get_type (const char *str) -{ - int type = 0; - - while (*str) { - if (!is_atom (*str)) { - if (is_qsafe (*str)) - type = IMAP4_STRING_QSTRING; - else - return IMAP4_STRING_LITERAL; - } - str++; - } - - return type; -} - -#if 0 -static gboolean -imap4_string_is_atom_safe (const char *str) -{ - while (is_atom (*str)) - str++; - - return *str == '\0'; -} - -static gboolean -imap4_string_is_quote_safe (const char *str) -{ - while (is_qsafe (*str)) - str++; - - return *str == '\0'; -} -#endif - -static size_t -camel_imap4_literal_length (CamelIMAP4Literal *literal) -{ - CamelStream *stream, *null; - CamelMimeFilter *crlf; - size_t len; - - if (literal->type == CAMEL_IMAP4_LITERAL_STRING) - return strlen (literal->literal.string); - - null = camel_stream_null_new (); - crlf = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); - stream = (CamelStream *) camel_stream_filter_new_with_stream (null); - camel_stream_filter_add ((CamelStreamFilter *) stream, crlf); - camel_object_unref (crlf); - - switch (literal->type) { - case CAMEL_IMAP4_LITERAL_STREAM: - camel_stream_write_to_stream (literal->literal.stream, stream); - camel_stream_reset (literal->literal.stream); - break; - case CAMEL_IMAP4_LITERAL_WRAPPER: - camel_data_wrapper_write_to_stream (literal->literal.wrapper, stream); - break; - default: - g_assert_not_reached (); - break; - } - - len = ((CamelStreamNull *) null)->written; - - camel_object_unref (stream); - camel_object_unref (null); - - return len; -} - -static CamelIMAP4CommandPart * -command_part_new (void) -{ - CamelIMAP4CommandPart *part; - - part = g_new (CamelIMAP4CommandPart, 1); - part->next = NULL; - part->buffer = NULL; - part->buflen = 0; - part->literal = NULL; - - return part; -} - -static void -imap4_command_append_string (CamelIMAP4Engine *engine, CamelIMAP4CommandPart **tail, GString *str, const char *string) -{ - CamelIMAP4CommandPart *part; - CamelIMAP4Literal *literal; - - switch (imap4_string_get_type (string)) { - case IMAP4_STRING_ATOM: - /* string is safe as it is... */ - g_string_append (str, string); - break; - case IMAP4_STRING_QSTRING: - /* we need to quote the string */ - /* FIXME: need to escape stuff */ - g_string_append_printf (str, "\"%s\"", string); - break; - case IMAP4_STRING_LITERAL: - if (engine->capa & CAMEL_IMAP4_CAPABILITY_LITERALPLUS) { - /* we have to send a literal, but the server supports LITERAL+ so use that */ - g_string_append_printf (str, "{%u+}\r\n%s", strlen (string), string); - } else { - /* we have to make it a literal */ - literal = g_new (CamelIMAP4Literal, 1); - literal->type = CAMEL_IMAP4_LITERAL_STRING; - literal->literal.string = g_strdup (string); - - g_string_append_printf (str, "{%u}\r\n", strlen (string)); - - (*tail)->buffer = g_strdup (str->str); - (*tail)->buflen = str->len; - (*tail)->literal = literal; - - part = command_part_new (); - (*tail)->next = part; - (*tail) = part; - - g_string_truncate (str, 0); - } - break; - } -} - -CamelIMAP4Command * -camel_imap4_command_newv (CamelIMAP4Engine *engine, CamelIMAP4Folder *imap4_folder, const char *format, va_list args) -{ - CamelIMAP4CommandPart *parts, *part, *tail; - CamelIMAP4Command *ic; - const char *start; - GString *str; - - tail = parts = command_part_new (); - - str = g_string_new (""); - start = format; - - while (*format) { - register char ch = *format++; - - if (ch == '%') { - CamelIMAP4Literal *literal; - CamelIMAP4Folder *folder; - char *function, **strv; - unsigned int u; - char *string; - size_t len; - void *obj; - int c, d; - - g_string_append_len (str, start, format - start - 1); - - switch (*format) { - case '%': - /* literal % */ - g_string_append_c (str, '%'); - break; - case 'c': - /* character */ - c = va_arg (args, int); - g_string_append_c (str, c); - break; - case 'd': - /* integer */ - d = va_arg (args, int); - g_string_append_printf (str, "%d", d); - break; - case 'u': - /* unsigned integer */ - u = va_arg (args, unsigned int); - g_string_append_printf (str, "%u", u); - break; - case 'F': - /* CamelIMAP4Folder */ - folder = va_arg (args, CamelIMAP4Folder *); - string = (char *) camel_imap4_folder_utf7_name (folder); - imap4_command_append_string (engine, &tail, str, string); - break; - case 'L': - /* Literal */ - obj = va_arg (args, void *); - - literal = g_new (CamelIMAP4Literal, 1); - if (CAMEL_IS_DATA_WRAPPER (obj)) { - literal->type = CAMEL_IMAP4_LITERAL_WRAPPER; - literal->literal.wrapper = obj; - } else if (CAMEL_IS_STREAM (obj)) { - literal->type = CAMEL_IMAP4_LITERAL_STREAM; - literal->literal.stream = obj; - } else { - g_assert_not_reached (); - } - - camel_object_ref (obj); - - /* FIXME: take advantage of LITERAL+? */ - len = camel_imap4_literal_length (literal); - g_string_append_printf (str, "{%u}\r\n", len); - - tail->buffer = g_strdup (str->str); - tail->buflen = str->len; - tail->literal = literal; - - part = command_part_new (); - tail->next = part; - tail = part; - - g_string_truncate (str, 0); - - break; - case 'V': - /* a string vector of arguments which may need to be quoted or made into literals */ - function = str->str + str->len - 2; - while (*function != ' ') - function--; - function++; - - function = g_strdup (function); - - strv = va_arg (args, char **); - for (d = 0; strv[d]; d++) { - if (d > 0) - g_string_append (str, function); - imap4_command_append_string (engine, &tail, str, strv[d]); - } - - g_free (function); - break; - case 'S': - /* string which may need to be quoted or made into a literal */ - string = va_arg (args, char *); - imap4_command_append_string (engine, &tail, str, string); - break; - case 's': - /* safe atom string */ - string = va_arg (args, char *); - g_string_append (str, string); - break; - default: - g_warning ("unknown formatter %%%c", *format); - g_string_append_c (str, '%'); - g_string_append_c (str, *format); - break; - } - - format++; - - start = format; - } - } - - g_string_append (str, start); - tail->buffer = str->str; - tail->buflen = str->len; - tail->literal = NULL; - g_string_free (str, FALSE); - - ic = g_new0 (CamelIMAP4Command, 1); - ((EDListNode *) ic)->next = NULL; - ((EDListNode *) ic)->prev = NULL; - ic->untagged = g_hash_table_new (g_str_hash, g_str_equal); - ic->status = CAMEL_IMAP4_COMMAND_QUEUED; - ic->resp_codes = g_ptr_array_new (); - ic->engine = engine; - ic->ref_count = 1; - ic->parts = parts; - ic->part = parts; - - camel_exception_init (&ic->ex); - - if (imap4_folder) { - camel_object_ref (imap4_folder); - ic->folder = imap4_folder; - } else - ic->folder = NULL; - - return ic; -} - -CamelIMAP4Command * -camel_imap4_command_new (CamelIMAP4Engine *engine, CamelIMAP4Folder *folder, const char *format, ...) -{ - CamelIMAP4Command *command; - va_list args; - - va_start (args, format); - command = camel_imap4_command_newv (engine, folder, format, args); - va_end (args); - - return command; -} - -void -camel_imap4_command_register_untagged (CamelIMAP4Command *ic, const char *atom, CamelIMAP4UntaggedCallback untagged) -{ - g_hash_table_insert (ic->untagged, g_strdup (atom), untagged); -} - -void -camel_imap4_command_ref (CamelIMAP4Command *ic) -{ - ic->ref_count++; -} - -void -camel_imap4_command_unref (CamelIMAP4Command *ic) -{ - CamelIMAP4CommandPart *part, *next; - int i; - - if (ic == NULL) - return; - - ic->ref_count--; - if (ic->ref_count == 0) { - if (ic->folder) - camel_object_unref (ic->folder); - - g_free (ic->tag); - - for (i = 0; i < ic->resp_codes->len; i++) { - CamelIMAP4RespCode *resp_code; - - resp_code = ic->resp_codes->pdata[i]; - camel_imap4_resp_code_free (resp_code); - } - g_ptr_array_free (ic->resp_codes, TRUE); - - g_hash_table_foreach (ic->untagged, (GHFunc) g_free, NULL); - g_hash_table_destroy (ic->untagged); - - camel_exception_clear (&ic->ex); - - part = ic->parts; - while (part != NULL) { - g_free (part->buffer); - if (part->literal) { - switch (part->literal->type) { - case CAMEL_IMAP4_LITERAL_STRING: - g_free (part->literal->literal.string); - break; - case CAMEL_IMAP4_LITERAL_STREAM: - camel_object_unref (part->literal->literal.stream); - break; - case CAMEL_IMAP4_LITERAL_WRAPPER: - camel_object_unref (part->literal->literal.wrapper); - break; - } - - g_free (part->literal); - } - - next = part->next; - g_free (part); - part = next; - } - - g_free (ic); - } -} - - -static int -imap4_literal_write_to_stream (CamelIMAP4Literal *literal, CamelStream *stream) -{ - CamelStream *istream, *ostream = NULL; - CamelDataWrapper *wrapper; - CamelMimeFilter *crlf; - char *string; - - if (literal->type == CAMEL_IMAP4_LITERAL_STRING) { - string = literal->literal.string; - if (camel_stream_write (stream, string, strlen (string)) == -1) - return -1; - - return 0; - } - - crlf = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); - ostream = (CamelStream *) camel_stream_filter_new_with_stream (stream); - camel_stream_filter_add ((CamelStreamFilter *) ostream, crlf); - camel_object_unref (crlf); - - /* write the literal */ - switch (literal->type) { - case CAMEL_IMAP4_LITERAL_STREAM: - istream = literal->literal.stream; - if (camel_stream_write_to_stream (istream, ostream) == -1) - goto exception; - break; - case CAMEL_IMAP4_LITERAL_WRAPPER: - wrapper = literal->literal.wrapper; - if (camel_data_wrapper_write_to_stream (wrapper, ostream) == -1) - goto exception; - break; - } - - camel_object_unref (ostream); - ostream = NULL; - -#if 0 - if (camel_stream_write (stream, "\r\n", 2) == -1) - return -1; -#endif - - return 0; - - exception: - - camel_object_unref (ostream); - - return -1; -} - - -static void -unexpected_token (camel_imap4_token_t *token) -{ - switch (token->token) { - case CAMEL_IMAP4_TOKEN_NO_DATA: - fprintf (stderr, "*** NO DATA ***"); - break; - case CAMEL_IMAP4_TOKEN_ERROR: - fprintf (stderr, "*** ERROR ***"); - break; - case CAMEL_IMAP4_TOKEN_NIL: - fprintf (stderr, "NIL"); - break; - case CAMEL_IMAP4_TOKEN_ATOM: - fprintf (stderr, "%s", token->v.atom); - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - fprintf (stderr, "\"%s\"", token->v.qstring); - break; - case CAMEL_IMAP4_TOKEN_LITERAL: - fprintf (stderr, "{%u}", token->v.literal); - break; - default: - fprintf (stderr, "%c", (unsigned char) (token->token & 0xff)); - break; - } -} - -int -camel_imap4_command_step (CamelIMAP4Command *ic) -{ - CamelIMAP4Engine *engine = ic->engine; - int result = CAMEL_IMAP4_RESULT_NONE; - CamelIMAP4Literal *literal; - camel_imap4_token_t token; - unsigned char *linebuf; - ssize_t nwritten; - size_t len; - - g_assert (ic->part != NULL); - - if (ic->part == ic->parts) { - ic->tag = g_strdup_printf ("%c%.5u", engine->tagprefix, engine->tag++); - camel_stream_printf (engine->ostream, "%s ", ic->tag); - d(fprintf (stderr, "sending: %s ", ic->tag)); - } - -#if d(!)0 - { - int sending = ic->part != ic->parts; - unsigned char *eoln, *eob; - - linebuf = ic->part->buffer; - eob = linebuf + ic->part->buflen; - - do { - eoln = linebuf; - while (eoln < eob && *eoln != '\n') - eoln++; - - if (eoln < eob) - eoln++; - - if (sending) - fwrite ("sending: ", 1, 10, stderr); - fwrite (linebuf, 1, eoln - linebuf, stderr); - - linebuf = eoln + 1; - sending = 1; - } while (linebuf < eob); - } -#endif - - linebuf = ic->part->buffer; - len = ic->part->buflen; - - if ((nwritten = camel_stream_write (engine->ostream, linebuf, len)) == -1) { - camel_exception_setv (&ic->ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed sending command to IMAP server %s: %s"), - engine->url->host, g_strerror (errno)); - goto exception; - } - - if (camel_stream_flush (engine->ostream) == -1) { - camel_exception_setv (&ic->ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed sending command to IMAP server %s: %s"), - engine->url->host, g_strerror (errno)); - goto exception; - } - - /* now we need to read the response(s) from the IMAP4 server */ - - do { - if (camel_imap4_engine_next_token (engine, &token, &ic->ex) == -1) - goto exception; - - if (token.token == '+') { - /* we got a continuation response from the server */ - literal = ic->part->literal; - - if (camel_imap4_engine_line (engine, &linebuf, &len, &ic->ex) == -1) - goto exception; - - if (literal) { - if (imap4_literal_write_to_stream (literal, engine->ostream) == -1) - goto exception; - - g_free (linebuf); - linebuf = NULL; - - break; - } else if (ic->plus) { - /* command expected a '+' response - probably AUTHENTICATE? */ - if (ic->plus (engine, ic, linebuf, len, &ic->ex) == -1) { - g_free (linebuf); - return -1; - } - - /* now we need to wait for a "<tag> OK/NO/BAD" response */ - } else { - /* FIXME: error?? */ - g_assert_not_reached (); - } - - g_free (linebuf); - linebuf = NULL; - } else if (token.token == '*') { - /* we got an untagged response, let the engine handle this */ - if (camel_imap4_engine_handle_untagged_1 (engine, &token, &ic->ex) == -1) - goto exception; - } else if (token.token == CAMEL_IMAP4_TOKEN_ATOM && !strcmp (token.v.atom, ic->tag)) { - /* we got "<tag> OK/NO/BAD" */ - d(fprintf (stderr, "got %s response\n", token.v.atom)); - - if (camel_imap4_engine_next_token (engine, &token, &ic->ex) == -1) - goto exception; - - if (token.token == CAMEL_IMAP4_TOKEN_ATOM) { - if (!strcmp (token.v.atom, "OK")) - result = CAMEL_IMAP4_RESULT_OK; - else if (!strcmp (token.v.atom, "NO")) - result = CAMEL_IMAP4_RESULT_NO; - else if (!strcmp (token.v.atom, "BAD")) - result = CAMEL_IMAP4_RESULT_BAD; - - if (result == CAMEL_IMAP4_RESULT_NONE) { - d(fprintf (stderr, "expected OK/NO/BAD but got %s\n", token.v.atom)); - goto unexpected; - } - - if (camel_imap4_engine_next_token (engine, &token, &ic->ex) == -1) - goto exception; - - if (token.token == '[') { - /* we have a response code */ - camel_imap4_stream_unget_token (engine->istream, &token); - if (camel_imap4_engine_parse_resp_code (engine, &ic->ex) == -1) - goto exception; - } else if (token.token != '\n') { - /* just gobble up the rest of the line */ - if (camel_imap4_engine_line (engine, NULL, NULL, &ic->ex) == -1) - goto exception; - } - } else { -#if d(!)0 - fprintf (stderr, "expected anything but this: "); - unexpected_token (&token); - fprintf (stderr, "\n"); -#endif - - goto unexpected; - } - - break; - } else { -#if d(!)0 - fprintf (stderr, "wtf is this: "); - unexpected_token (&token); - fprintf (stderr, "\n"); -#endif - - unexpected: - - /* no fucking clue what we got... */ - if (camel_imap4_engine_line (engine, &linebuf, &len, &ic->ex) == -1) - goto exception; - - camel_exception_setv (&ic->ex, CAMEL_EXCEPTION_SYSTEM, - _("Unexpected response from IMAP4 server %s: %s"), - engine->url->host, linebuf); - - g_free (linebuf); - - goto exception; - } - } while (1); - - /* status should always be ACTIVE here... */ - if (ic->status == CAMEL_IMAP4_COMMAND_ACTIVE) { - ic->part = ic->part->next; - if (ic->part == NULL || result) { - ic->status = CAMEL_IMAP4_COMMAND_COMPLETE; - ic->result = result; - return 1; - } - } - - return 0; - - exception: - - ic->status = CAMEL_IMAP4_COMMAND_ERROR; - - return -1; -} - - -void -camel_imap4_command_reset (CamelIMAP4Command *ic) -{ - int i; - - for (i = 0; i < ic->resp_codes->len; i++) - camel_imap4_resp_code_free (ic->resp_codes->pdata[i]); - g_ptr_array_set_size (ic->resp_codes, 0); - - ic->status = CAMEL_IMAP4_COMMAND_QUEUED; - ic->result = CAMEL_IMAP4_RESULT_NONE; - ic->part = ic->parts; - g_free (ic->tag); - ic->tag = NULL; - - camel_exception_clear (&ic->ex); -} diff --git a/camel/providers/imap4/camel-imap4-command.h b/camel/providers/imap4/camel-imap4-command.h deleted file mode 100644 index 112695a0db..0000000000 --- a/camel/providers/imap4/camel-imap4-command.h +++ /dev/null @@ -1,144 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifndef __CAMEL_IMAP4_COMMAND_H__ -#define __CAMEL_IMAP4_COMMAND_H__ - -#include <stdarg.h> - -#include <glib.h> - -#include <libedataserver/e-msgport.h> - -#include <camel/camel-stream.h> -#include <camel/camel-exception.h> -#include <camel/camel-data-wrapper.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -struct _CamelIMAP4Engine; -struct _CamelIMAP4Folder; -struct _camel_imap4_token_t; - -typedef struct _CamelIMAP4Command CamelIMAP4Command; -typedef struct _CamelIMAP4Literal CamelIMAP4Literal; - -typedef int (* CamelIMAP4PlusCallback) (struct _CamelIMAP4Engine *engine, - CamelIMAP4Command *ic, - const unsigned char *linebuf, - size_t linelen, CamelException *ex); - -typedef int (* CamelIMAP4UntaggedCallback) (struct _CamelIMAP4Engine *engine, - CamelIMAP4Command *ic, - guint32 index, - struct _camel_imap4_token_t *token, - CamelException *ex); - -enum { - CAMEL_IMAP4_LITERAL_STRING, - CAMEL_IMAP4_LITERAL_STREAM, - CAMEL_IMAP4_LITERAL_WRAPPER, -}; - -struct _CamelIMAP4Literal { - int type; - union { - char *string; - CamelStream *stream; - CamelDataWrapper *wrapper; - } literal; -}; - -typedef struct _CamelIMAP4CommandPart { - struct _CamelIMAP4CommandPart *next; - unsigned char *buffer; - size_t buflen; - - CamelIMAP4Literal *literal; -} CamelIMAP4CommandPart; - -enum { - CAMEL_IMAP4_COMMAND_QUEUED, - CAMEL_IMAP4_COMMAND_ACTIVE, - CAMEL_IMAP4_COMMAND_COMPLETE, - CAMEL_IMAP4_COMMAND_ERROR, -}; - -enum { - CAMEL_IMAP4_RESULT_NONE, - CAMEL_IMAP4_RESULT_OK, - CAMEL_IMAP4_RESULT_NO, - CAMEL_IMAP4_RESULT_BAD, -}; - -struct _CamelIMAP4Command { - EDListNode node; - - struct _CamelIMAP4Engine *engine; - - unsigned int ref_count:26; - unsigned int status:3; - unsigned int result:3; - int id; - - char *tag; - - GPtrArray *resp_codes; - - struct _CamelIMAP4Folder *folder; - CamelException ex; - - /* command parts - logical breaks in the overall command based on literals */ - CamelIMAP4CommandPart *parts; - - /* current part */ - CamelIMAP4CommandPart *part; - - /* untagged handlers */ - GHashTable *untagged; - - /* '+' callback/data */ - CamelIMAP4PlusCallback plus; - void *user_data; -}; - -CamelIMAP4Command *camel_imap4_command_new (struct _CamelIMAP4Engine *engine, struct _CamelIMAP4Folder *folder, - const char *format, ...); -CamelIMAP4Command *camel_imap4_command_newv (struct _CamelIMAP4Engine *engine, struct _CamelIMAP4Folder *folder, - const char *format, va_list args); - -void camel_imap4_command_register_untagged (CamelIMAP4Command *ic, const char *atom, CamelIMAP4UntaggedCallback untagged); - -void camel_imap4_command_ref (CamelIMAP4Command *ic); -void camel_imap4_command_unref (CamelIMAP4Command *ic); - -/* returns 1 when complete, 0 if there is more to do, or -1 on error */ -int camel_imap4_command_step (CamelIMAP4Command *ic); - -void camel_imap4_command_reset (CamelIMAP4Command *ic); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_IMAP4_COMMAND_H__ */ diff --git a/camel/providers/imap4/camel-imap4-engine.c b/camel/providers/imap4/camel-imap4-engine.c deleted file mode 100644 index d6f17532ee..0000000000 --- a/camel/providers/imap4/camel-imap4-engine.c +++ /dev/null @@ -1,1698 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <ctype.h> -#include <errno.h> - -#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" -#include "camel-imap4-stream.h" -#include "camel-imap4-folder.h" -#include "camel-imap4-utils.h" - -#include "camel-imap4-engine.h" - -#define d(x) x - - -static void camel_imap4_engine_class_init (CamelIMAP4EngineClass *klass); -static void camel_imap4_engine_init (CamelIMAP4Engine *engine, CamelIMAP4EngineClass *klass); -static void camel_imap4_engine_finalize (CamelObject *object); - - -static CamelObjectClass *parent_class = NULL; - - -CamelType -camel_imap4_engine_get_type (void) -{ - static CamelType type = 0; - - if (!type) { - type = camel_type_register (camel_object_get_type (), - "CamelIMAP4Engine", - sizeof (CamelIMAP4Engine), - sizeof (CamelIMAP4EngineClass), - (CamelObjectClassInitFunc) camel_imap4_engine_class_init, - NULL, - (CamelObjectInitFunc) camel_imap4_engine_init, - (CamelObjectFinalizeFunc) camel_imap4_engine_finalize); - } - - return type; -} - -static void -camel_imap4_engine_class_init (CamelIMAP4EngineClass *klass) -{ - parent_class = camel_type_get_global_classfuncs (CAMEL_OBJECT_TYPE); - - klass->tagprefix = 'A'; -} - -static void -camel_imap4_engine_init (CamelIMAP4Engine *engine, CamelIMAP4EngineClass *klass) -{ - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - engine->level = CAMEL_IMAP4_LEVEL_UNKNOWN; - - engine->session = NULL; - engine->service = NULL; - engine->url = NULL; - - engine->istream = NULL; - engine->ostream = NULL; - - engine->authtypes = g_hash_table_new (g_str_hash, g_str_equal); - - engine->capa = 0; - - /* this is the suggested default, impacts the max command line length we'll send */ - engine->maxlentype = CAMEL_IMAP4_ENGINE_MAXLEN_LINE; - engine->maxlen = 1000; - - engine->namespaces.personal = NULL; - engine->namespaces.other = NULL; - engine->namespaces.shared = NULL; - - if (klass->tagprefix > 'Z') - klass->tagprefix = 'A'; - - engine->tagprefix = klass->tagprefix++; - engine->tag = 0; - - engine->nextid = 1; - - engine->folder = NULL; - - e_dlist_init (&engine->queue); -} - -static void -camel_imap4_engine_finalize (CamelObject *object) -{ - CamelIMAP4Engine *engine = (CamelIMAP4Engine *) object; - EDListNode *node; - - if (engine->istream) - camel_object_unref (engine->istream); - - if (engine->ostream) - camel_object_unref (engine->ostream); - - 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); - - if (engine->folder) - camel_object_unref (engine->folder); - - while ((node = e_dlist_remhead (&engine->queue))) { - node->next = NULL; - node->prev = NULL; - - camel_imap4_command_unref ((CamelIMAP4Command *) node); - } -} - - -/** - * camel_imap4_engine_new: - * @service: service - * @reconnect: reconnect callback function - * - * Returns a new imap4 engine - **/ -CamelIMAP4Engine * -camel_imap4_engine_new (CamelService *service, CamelIMAP4ReconnectFunc reconnect) -{ - CamelIMAP4Engine *engine; - - g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL); - - engine = (CamelIMAP4Engine *) camel_object_new (CAMEL_TYPE_IMAP4_ENGINE); - engine->session = service->session; - engine->url = service->url; - engine->service = service; - engine->reconnect = reconnect; - - return engine; -} - - -/** - * camel_imap4_engine_take_stream: - * @engine: imap4 engine - * @stream: tcp stream - * @ex: exception - * - * Gives ownership of @stream to @engine and reads the greeting from - * the stream. - * - * Returns 0 on success or -1 on fail. - * - * Note: on error, @stream will be unref'd. - **/ -int -camel_imap4_engine_take_stream (CamelIMAP4Engine *engine, CamelStream *stream, CamelException *ex) -{ - camel_imap4_token_t token; - int code; - - g_return_val_if_fail (CAMEL_IS_IMAP4_ENGINE (engine), -1); - g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1); - - if (engine->istream) - camel_object_unref (engine->istream); - - if (engine->ostream) - camel_object_unref (engine->ostream); - - engine->istream = (CamelIMAP4Stream *) camel_imap4_stream_new (stream); - engine->ostream = camel_stream_buffer_new (stream, CAMEL_STREAM_BUFFER_WRITE); - engine->state = CAMEL_IMAP4_ENGINE_CONNECTED; - camel_object_unref (stream); - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - if (token.token != '*') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if ((code = camel_imap4_engine_handle_untagged_1 (engine, &token, ex)) == -1) { - goto exception; - } else if (code != CAMEL_IMAP4_UNTAGGED_OK && code != CAMEL_IMAP4_UNTAGGED_PREAUTH) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Unexpected greeting from IMAP server %s."), - engine->url->host); - goto exception; - } - - return 0; - - exception: - - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - - camel_object_unref (engine->istream); - engine->istream = NULL; - camel_object_unref (engine->ostream); - engine->ostream = NULL; - - return -1; -} - - -/** - * camel_imap4_engine_capability: - * @engine: IMAP4 engine - * @ex: exception - * - * Forces the IMAP4 engine to query the IMAP4 server for a list of capabilities. - * - * Returns 0 on success or -1 on fail. - **/ -int -camel_imap4_engine_capability (CamelIMAP4Engine *engine, CamelException *ex) -{ - CamelIMAP4Command *ic; - int id, retval = 0; - - ic = camel_imap4_engine_prequeue (engine, NULL, "CAPABILITY\r\n"); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - retval = -1; - } - - camel_imap4_command_unref (ic); - - return retval; -} - - -/** - * camel_imap4_engine_namespace: - * @engine: IMAP4 engine - * @ex: exception - * - * Forces the IMAP4 engine to query the IMAP4 server for a list of namespaces. - * - * Returns 0 on success or -1 on fail. - **/ -int -camel_imap4_engine_namespace (CamelIMAP4Engine *engine, CamelException *ex) -{ - camel_imap4_list_t *list; - GPtrArray *array = NULL; - CamelIMAP4Command *ic; - int id, i; - - if (engine->capa & CAMEL_IMAP4_CAPABILITY_NAMESPACE) { - ic = camel_imap4_engine_prequeue (engine, NULL, "NAMESPACE\r\n"); - } else { - ic = camel_imap4_engine_prequeue (engine, NULL, "LIST \"\" \"\"\r\n"); - camel_imap4_command_register_untagged (ic, "LIST", camel_imap4_untagged_list); - ic->user_data = array = g_ptr_array_new (); - } - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - - if (array != NULL) - g_ptr_array_free (array, TRUE); - - return -1; - } - - if (array != NULL) { - if (ic->result == CAMEL_IMAP4_RESULT_OK) { - CamelIMAP4Namespace *namespace; - - g_assert (array->len == 1); - list = array->pdata[0]; - - namespace = g_new (CamelIMAP4Namespace, 1); - namespace->next = NULL; - namespace->path = g_strdup (""); - namespace->sep = list->delim; - - engine->namespaces.personal = namespace; - } else { - /* should never *ever* happen */ - } - - for (i = 0; i < array->len; i++) { - list = array->pdata[i]; - g_free (list->name); - g_free (list); - } - - g_ptr_array_free (array, TRUE); - } - - camel_imap4_command_unref (ic); - - return 0; -} - - -/** - * 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) -{ - CamelIMAP4RespCode *resp; - CamelIMAP4Command *ic; - int id, retval = 0; - int i; - - g_return_val_if_fail (CAMEL_IS_IMAP4_ENGINE (engine), -1); - g_return_val_if_fail (CAMEL_IS_IMAP4_FOLDER (folder), -1); - - /* POSSIBLE FIXME: if the folder to be selected will already - * be selected by the time the queue is emptied, simply - * no-op? */ - - ic = camel_imap4_engine_queue (engine, folder, "SELECT %F\r\n", folder); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - return -1; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - /*folder->mode = 0;*/ - for (i = 0; i < ic->resp_codes->len; i++) { - resp = ic->resp_codes->pdata[i]; - switch (resp->code) { - case CAMEL_IMAP4_RESP_CODE_PERM_FLAGS: - folder->permanent_flags = resp->v.flags; - break; - case CAMEL_IMAP4_RESP_CODE_READONLY: - /*folder->mode = CAMEL_FOLDER_MODE_READ_ONLY;*/ - break; - case CAMEL_IMAP4_RESP_CODE_READWRITE: - /*folder->mode = CAMEL_FOLDER_MODE_READ_WRITE;*/ - break; - case CAMEL_IMAP4_RESP_CODE_UIDNEXT: - camel_imap4_summary_set_uidnext (folder->summary, resp->v.uidnext); - break; - case CAMEL_IMAP4_RESP_CODE_UIDVALIDITY: - camel_imap4_summary_set_uidvalidity (folder->summary, resp->v.uidvalidity); - break; - case CAMEL_IMAP4_RESP_CODE_UNSEEN: - camel_imap4_summary_set_unseen (folder->summary, resp->v.unseen); - break; - default: - break; - } - } - - /*if (folder->mode == 0) { - folder->mode = CAMEL_FOLDER_MODE_READ_ONLY; - g_warning ("Expected to find [READ-ONLY] or [READ-WRITE] in SELECT response"); - }*/ - - break; - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot select folder `%s': Invalid mailbox name"), - folder->full_name); - retval = -1; - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot select folder `%s': Bad command"), - folder->full_name); - retval = -1; - break; - default: - g_assert_not_reached (); - retval = -1; - } - - camel_imap4_command_unref (ic); - - return retval; -} - - -static struct { - const char *name; - guint32 flag; -} imap4_capabilities[] = { - { "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 */ - { "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 } -}; - -static gboolean -auth_free (gpointer key, gpointer value, gpointer user_data) -{ - g_free (key); - return TRUE; -} - -static int -engine_parse_capability (CamelIMAP4Engine *engine, int sentinel, CamelException *ex) -{ - camel_imap4_token_t token; - int i; - - engine->capa = CAMEL_IMAP4_CAPABILITY_utf8_search; - engine->level = 0; - - g_hash_table_foreach_remove (engine->authtypes, (GHRFunc) auth_free, NULL); - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - while (token.token == CAMEL_IMAP4_TOKEN_ATOM) { - if (!g_ascii_strncasecmp ("AUTH=", token.v.atom, 5)) { - CamelServiceAuthType *auth; - - if ((auth = camel_sasl_authtype (token.v.atom + 5)) != NULL) - g_hash_table_insert (engine->authtypes, g_strdup (token.v.atom + 5), auth); - } else { - for (i = 0; imap4_capabilities[i].name; i++) { - if (!g_ascii_strcasecmp (imap4_capabilities[i].name, token.v.atom)) - engine->capa |= imap4_capabilities[i].flag; - } - } - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - } - - if (token.token != sentinel) { - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - /* unget our sentinel token */ - camel_imap4_stream_unget_token (engine->istream, &token); - - /* figure out which version of IMAP4 we are dealing with */ - if (engine->capa & CAMEL_IMAP4_CAPABILITY_IMAP4REV1) { - engine->level = CAMEL_IMAP4_LEVEL_IMAP4REV1; - engine->capa |= CAMEL_IMAP4_CAPABILITY_STATUS; - } else if (engine->capa & CAMEL_IMAP4_CAPABILITY_IMAP4) { - engine->level = CAMEL_IMAP4_LEVEL_IMAP4; - } else { - engine->level = CAMEL_IMAP4_LEVEL_UNKNOWN; - } - - return 0; -} - -static int -engine_parse_flags_list (CamelIMAP4Engine *engine, CamelIMAP4RespCode *resp, int perm, CamelException *ex) -{ - guint32 flags = 0; - - if (camel_imap4_parse_flags_list (engine, &flags, ex) == -1) - return-1; - - if (resp != NULL) - resp->v.flags = flags; - - if (engine->current && engine->current->folder) { - if (perm) - ((CamelFolder *) engine->current->folder)->permanent_flags = flags; - /*else - ((CamelFolder *) engine->current->folder)->folder_flags = flags;*/ - } else if (engine->folder) { - if (perm) - ((CamelFolder *) engine->folder)->permanent_flags = flags; - /*else - ((CamelFolder *) engine->folder)->folder_flags = flags;*/ - } else { - fprintf (stderr, "We seem to be in a bit of a pickle. we've just parsed an untagged %s\n" - "response for a folder, yet we do not currently have a folder selected?\n", - perm ? "PERMANENTFLAGS" : "FLAGS"); - } - - return 0; -} - -static int -engine_parse_flags (CamelIMAP4Engine *engine, CamelException *ex) -{ - camel_imap4_token_t token; - - if (engine_parse_flags_list (engine, NULL, FALSE, ex) == -1) - return -1; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != '\n') { - d(fprintf (stderr, "Expected to find a '\\n' token after the FLAGS response\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - return 0; -} - -static int -engine_parse_namespace (CamelIMAP4Engine *engine, CamelException *ex) -{ - CamelIMAP4Namespace *namespaces[3], *node, *tail; - 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); - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - do { - namespaces[n] = NULL; - tail = (CamelIMAP4Namespace *) &namespaces[n]; - - if (token.token == '(') { - /* decode the list of namespace pairs */ - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - while (token.token == '(') { - /* decode a namespace pair */ - - /* get the path name token */ - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - if (token.token != CAMEL_IMAP4_TOKEN_QSTRING) { - d(fprintf (stderr, "Expected to find a qstring token as first element in NAMESPACE pair\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - node = g_new (CamelIMAP4Namespace, 1); - node->next = NULL; - node->path = g_strdup (token.v.qstring); - - /* get the path delimiter token */ - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) { - g_free (node->path); - g_free (node); - - 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")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - g_free (node->path); - g_free (node); - - goto exception; - } - - tail->next = node; - tail = node; - - /* canonicalise the namespace path */ - if (node->path[strlen (node->path) - 1] == node->sep) - node->path[strlen (node->path) - 1] = '\0'; - - /* canonicalise if this is an INBOX namespace */ - if (!g_ascii_strncasecmp (node->path, "INBOX", 5) && - (node->path[6] == '\0' || node->path[6] == node->sep)) - memcpy (node->path, "INBOX", 5); - - /* get the closing ')' for this namespace pair */ - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - if (token.token != ')') { - d(fprintf (stderr, "Expected to find a ')' token to close the current namespace pair\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - - goto exception; - } - - /* get the next token (should be either '(' or ')') */ - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - } - - if (token.token != ')') { - d(fprintf (stderr, "Expected to find a ')' to close the current namespace list\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - } else if (token.token == CAMEL_IMAP4_TOKEN_NIL) { - /* namespace list is NIL */ - namespaces[n] = NULL; - } else { - d(fprintf (stderr, "Expected to find either NIL or '(' token in untagged NAMESPACE response\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - /* get the next token (should be either '(', NIL, or '\n') */ - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - n++; - } while (n < 3); - - engine->namespaces.personal = namespaces[0]; - engine->namespaces.other = namespaces[1]; - engine->namespaces.shared = namespaces[2]; - - return 0; - - exception: - - for (i = 0; i <= n; i++) - camel_imap4_namespace_clear (&namespaces[i]); - - return -1; -} - - -/** - * - * resp-text-code = "ALERT" / - * "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / - * capability-data / "PARSE" / - * "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / - * "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / - * "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / - * "UNSEEN" SP nz-number / - * atom [SP 1*<any TEXT-CHAR except "]">] - **/ - -static struct { - const char *name; - camel_imap4_resp_code_t code; - int save; -} imap4_resp_codes[] = { - { "ALERT", CAMEL_IMAP4_RESP_CODE_ALERT, 0 }, - { "BADCHARSET", CAMEL_IMAP4_RESP_CODE_BADCHARSET, 0 }, - { "CAPABILITY", CAMEL_IMAP4_RESP_CODE_CAPABILITY, 0 }, - { "PARSE", CAMEL_IMAP4_RESP_CODE_PARSE, 1 }, - { "PERMANENTFLAGS", CAMEL_IMAP4_RESP_CODE_PERM_FLAGS, 1 }, - { "READ-ONLY", CAMEL_IMAP4_RESP_CODE_READONLY, 1 }, - { "READ-WRITE", CAMEL_IMAP4_RESP_CODE_READWRITE, 1 }, - { "TRYCREATE", CAMEL_IMAP4_RESP_CODE_TRYCREATE, 1 }, - { "UIDNEXT", CAMEL_IMAP4_RESP_CODE_UIDNEXT, 1 }, - { "UIDVALIDITY", CAMEL_IMAP4_RESP_CODE_UIDVALIDITY, 1 }, - { "UNSEEN", CAMEL_IMAP4_RESP_CODE_UNSEEN, 1 }, - { "NEWNAME", CAMEL_IMAP4_RESP_CODE_NEWNAME, 1 }, - { "APPENDUID", CAMEL_IMAP4_RESP_CODE_APPENDUID, 1 }, - { "COPYUID", CAMEL_IMAP4_RESP_CODE_COPYUID, 1 }, - { NULL, CAMEL_IMAP4_RESP_CODE_UNKNOWN, 0 } -}; - - -/** - * 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) -{ - CamelIMAP4RespCode *resp = NULL; - camel_imap4_resp_code_t code; - camel_imap4_token_t token; - unsigned char *linebuf; - size_t len; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != '[') { - d(fprintf (stderr, "Expected a '[' token (followed by a RESP-CODE)\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != CAMEL_IMAP4_TOKEN_ATOM) { - d(fprintf (stderr, "Expected an atom token containing a RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - for (code = 0; imap4_resp_codes[code].name; code++) { - if (!strcmp (imap4_resp_codes[code].name, token.v.atom)) { - if (engine->current && imap4_resp_codes[code].save) { - resp = g_new0 (CamelIMAP4RespCode, 1); - resp->code = code; - } - break; - } - } - - switch (code) { - case CAMEL_IMAP4_RESP_CODE_BADCHARSET: - /* apparently we don't support UTF-8 afterall */ - engine->capa &= ~CAMEL_IMAP4_CAPABILITY_utf8_search; - break; - case CAMEL_IMAP4_RESP_CODE_CAPABILITY: - /* capability list follows */ - if (engine_parse_capability (engine, ']', ex) == -1) - goto exception; - break; - case CAMEL_IMAP4_RESP_CODE_PERM_FLAGS: - /* flag list follows */ - if (engine_parse_flags_list (engine, resp, TRUE, ex) == -1) - goto exception; - break; - case CAMEL_IMAP4_RESP_CODE_READONLY: - break; - case CAMEL_IMAP4_RESP_CODE_READWRITE: - break; - case CAMEL_IMAP4_RESP_CODE_TRYCREATE: - break; - case CAMEL_IMAP4_RESP_CODE_UIDNEXT: - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - if (token.token != CAMEL_IMAP4_TOKEN_NUMBER) { - d(fprintf (stderr, "Expected an nz_number token as an argument to the UIDNEXT RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) - resp->v.uidnext = token.v.number; - - break; - case CAMEL_IMAP4_RESP_CODE_UIDVALIDITY: - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - if (token.token != CAMEL_IMAP4_TOKEN_NUMBER) { - d(fprintf (stderr, "Expected an nz_number token as an argument to the UIDVALIDITY RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) - resp->v.uidvalidity = token.v.number; - - break; - case CAMEL_IMAP4_RESP_CODE_UNSEEN: - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != CAMEL_IMAP4_TOKEN_NUMBER) { - d(fprintf (stderr, "Expected an nz_number token as an argument to the UNSEEN RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) - resp->v.unseen = token.v.number; - - break; - case CAMEL_IMAP4_RESP_CODE_NEWNAME: - /* this RESP-CODE may actually be removed - see here: - * http://www.washington.edu/imap4/listarch/2001/msg00058.html */ - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != CAMEL_IMAP4_TOKEN_ATOM && token.token != CAMEL_IMAP4_TOKEN_QSTRING) { - d(fprintf (stderr, "Expected an atom or qstring token as the first argument to the NEWNAME RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) - resp->v.newname[0] = g_strdup (token.v.atom); - - if (token.token != CAMEL_IMAP4_TOKEN_ATOM && token.token != CAMEL_IMAP4_TOKEN_QSTRING) { - d(fprintf (stderr, "Expected an atom or qstring token as the second argument to the NEWNAME RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) - resp->v.newname[1] = g_strdup (token.v.atom); - - break; - case CAMEL_IMAP4_RESP_CODE_APPENDUID: - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != CAMEL_IMAP4_TOKEN_NUMBER) { - d(fprintf (stderr, "Expected an nz_number token as the first argument to the APPENDUID RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) - resp->v.appenduid.uidvalidity = token.v.number; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != CAMEL_IMAP4_TOKEN_NUMBER) { - d(fprintf (stderr, "Expected an nz_number token as the second argument to the APPENDUID RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) - resp->v.appenduid.uid = token.v.number; - - break; - case CAMEL_IMAP4_RESP_CODE_COPYUID: - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != CAMEL_IMAP4_TOKEN_NUMBER) { - d(fprintf (stderr, "Expected an nz_number token as the first argument to the COPYUID RESP-CODE\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - if (resp != NULL) - resp->v.copyuid.uidvalidity = token.v.number; - - 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")); - 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 (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")); - 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); - } - - break; - default: - d(fprintf (stderr, "Unknown RESP-CODE encountered: %s\n", token.v.atom)); - - /* extensions are of the form: "[" atom [SPACE 1*<any TEXT_CHAR except "]">] "]" */ - - /* eat up the TEXT_CHARs */ - while (token.token != ']' && token.token != '\n') { - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - } - - break; - } - - while (token.token != ']' && token.token != '\n') { - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - } - - if (token.token != ']') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - d(fprintf (stderr, "Expected to find a ']' token after the RESP-CODE\n")); - return -1; - } - - if (code == CAMEL_IMAP4_RESP_CODE_ALERT) { - if (camel_imap4_engine_line (engine, &linebuf, &len, ex) == -1) - goto exception; - - camel_session_alert_user (engine->session, CAMEL_SESSION_ALERT_INFO, linebuf, FALSE); - g_free (linebuf); - } else if (resp != NULL && code == CAMEL_IMAP4_RESP_CODE_PARSE) { - if (camel_imap4_engine_line (engine, &linebuf, &len, ex) == -1) - goto exception; - - resp->v.parse = linebuf; - } else { - /* eat up the rest of the response */ - if (camel_imap4_engine_line (engine, NULL, NULL, ex) == -1) - goto exception; - } - - if (resp != NULL) - g_ptr_array_add (engine->current->resp_codes, resp); - - return 0; - - exception: - - if (resp != NULL) - camel_imap4_resp_code_free (resp); - - return -1; -} - - -/** - * 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 - **/ -int -camel_imap4_engine_handle_untagged_1 (CamelIMAP4Engine *engine, camel_imap4_token_t *token, CamelException *ex) -{ - int code = CAMEL_IMAP4_UNTAGGED_HANDLED; - CamelIMAP4Command *ic = engine->current; - CamelIMAP4UntaggedCallback untagged; - CamelFolder *folder; - unsigned int v; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token == CAMEL_IMAP4_TOKEN_ATOM) { - if (!strcmp ("BYE", token->v.atom)) { - /* we don't care if we fail here, either way we've been disconnected */ - if (camel_imap4_engine_next_token (engine, token, NULL) == 0) { - if (token->token == '[') { - camel_imap4_stream_unget_token (engine->istream, token); - camel_imap4_engine_parse_resp_code (engine, NULL); - } else { - camel_imap4_engine_line (engine, NULL, NULL, NULL); - } - } - - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - - /* we don't return -1 here because there may be more untagged responses after the BYE */ - } else if (!strcmp ("CAPABILITY", token->v.atom)) { - /* capability tokens follow */ - if (engine_parse_capability (engine, '\n', ex) == -1) - return -1; - - /* find the eoln token */ - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token != '\n') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - return -1; - } - } else if (!strcmp ("FLAGS", token->v.atom)) { - /* flags list follows */ - if (engine_parse_flags (engine, ex) == -1) - return -1; - } else if (!strcmp ("NAMESPACE", token->v.atom)) { - if (engine_parse_namespace (engine, ex) == -1) - return -1; - } else if (!strcmp ("NO", token->v.atom) || !strcmp ("BAD", token->v.atom)) { - code = !strcmp ("NO", token->v.atom) ? CAMEL_IMAP4_UNTAGGED_NO : CAMEL_IMAP4_UNTAGGED_BAD; - - /* our command has been rejected */ - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token == '[') { - /* we have a resp code */ - camel_imap4_stream_unget_token (engine->istream, token); - if (camel_imap4_engine_parse_resp_code (engine, ex) == -1) - return -1; - } else if (token->token != '\n') { - /* we just have resp text */ - if (camel_imap4_engine_line (engine, NULL, NULL, ex) == -1) - return -1; - } - } else if (!strcmp ("OK", token->v.atom)) { - code = CAMEL_IMAP4_UNTAGGED_OK; - - if (engine->state == CAMEL_IMAP4_ENGINE_CONNECTED) { - /* initial server greeting */ - engine->state = CAMEL_IMAP4_ENGINE_PREAUTH; - } - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token == '[') { - /* we have a resp code */ - camel_imap4_stream_unget_token (engine->istream, token); - if (camel_imap4_engine_parse_resp_code (engine, ex) == -1) - return -1; - } else { - /* we just have resp text */ - if (camel_imap4_engine_line (engine, NULL, NULL, ex) == -1) - return -1; - } - } else if (!strcmp ("PREAUTH", token->v.atom)) { - code = CAMEL_IMAP4_UNTAGGED_PREAUTH; - - if (engine->state == CAMEL_IMAP4_ENGINE_CONNECTED) - engine->state = CAMEL_IMAP4_ENGINE_AUTHENTICATED; - - if (camel_imap4_engine_parse_resp_code (engine, ex) == -1) - return -1; - } else if (ic && (untagged = g_hash_table_lookup (ic->untagged, token->v.atom))) { - /* registered untagged handler for imap4 command */ - if (untagged (engine, ic, 0, token, ex) == -1) - return -1; - } else { - d(fprintf (stderr, "Unhandled atom token in untagged response: %s", token->v.atom)); - - if (camel_imap4_engine_eat_line (engine, ex) == -1) - return -1; - } - } else if (token->token == CAMEL_IMAP4_TOKEN_NUMBER) { - /* we probably have something like "* 1 EXISTS" */ - v = token->v.number; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token != CAMEL_IMAP4_TOKEN_ATOM) { - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - - return -1; - } - - /* which folder is this EXISTS/EXPUNGE/RECENT acting on? */ - if (engine->current && engine->current->folder) - folder = (CamelFolder *) engine->current->folder; - else if (engine->folder) - folder = (CamelFolder *) engine->folder; - else - folder = NULL; - - /* NOTE: these can be over-ridden by a registered untagged response handler */ - if (!strcmp ("EXISTS", token->v.atom)) { - camel_imap4_summary_set_exists (folder->summary, v); - } else if (!strcmp ("EXPUNGE", token->v.atom)) { - camel_imap4_summary_expunge (folder->summary, (int) v); - } else if (!strcmp ("RECENT", token->v.atom)) { - camel_imap4_summary_set_recent (folder->summary, v); - } else if (ic && (untagged = g_hash_table_lookup (ic->untagged, token->v.atom))) { - /* registered untagged handler for imap4 command */ - if (untagged (engine, ic, v, token, ex) == -1) - return -1; - } else { - d(fprintf (stderr, "Unrecognized untagged response: * %u %s\n", v, token->v.atom)); - } - - /* find the eoln token */ - if (camel_imap4_engine_eat_line (engine, ex) == -1) - return -1; - } else { - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - - return -1; - } - - return code; -} - - -/** - * 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) -{ - camel_imap4_token_t token; - - g_return_if_fail (CAMEL_IS_IMAP4_ENGINE (engine)); - - do { - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - if (token.token != '*') - break; - - if (camel_imap4_engine_handle_untagged_1 (engine, &token, ex) == -1) - goto exception; - } while (1); - - camel_imap4_stream_unget_token (engine->istream, &token); - - return; - - exception: - - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; -} - - -static int -imap4_process_command (CamelIMAP4Engine *engine, CamelIMAP4Command *ic) -{ - int retval; - - while ((retval = camel_imap4_command_step (ic)) == 0) - ; - - if (retval == -1) { - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - return -1; - } - - return 0; -} - - -static void -engine_prequeue_folder_select (CamelIMAP4Engine *engine) -{ - CamelIMAP4Command *ic; - const char *cmd; - - ic = (CamelIMAP4Command *) engine->queue.head; - cmd = (const char *) ic->parts->buffer; - - if (!ic->folder || ic->folder == engine->folder || - !strncmp (cmd, "SELECT ", 7) || !strncmp (cmd, "EXAMINE ", 8)) { - /* no need to pre-queue a SELECT */ - return; - } - - /* we need to pre-queue a SELECT */ - ic = camel_imap4_engine_prequeue (engine, (CamelFolder *) ic->folder, "SELECT %F\r\n", ic->folder); - ic->user_data = engine; - - camel_imap4_command_unref (ic); -} - - -static int -engine_state_change (CamelIMAP4Engine *engine, CamelIMAP4Command *ic) -{ - const char *cmd; - int retval = 0; - - cmd = ic->parts->buffer; - if (!strncmp (cmd, "SELECT ", 7) || !strncmp (cmd, "EXAMINE ", 8)) { - if (ic->result == CAMEL_IMAP4_RESULT_OK) { - /* Update the selected folder */ - camel_object_ref (ic->folder); - if (engine->folder) - camel_object_unref (engine->folder); - engine->folder = ic->folder; - - engine->state = CAMEL_IMAP4_ENGINE_SELECTED; - } else if (ic->user_data == engine) { - /* the engine pre-queued this SELECT command */ - retval = -1; - } - } else if (!strncmp (cmd, "CLOSE", 5)) { - if (ic->result == CAMEL_IMAP4_RESULT_OK) - engine->state = CAMEL_IMAP4_ENGINE_AUTHENTICATED; - } else if (!strncmp (cmd, "LOGOUT", 6)) { - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - } - - return retval; -} - - -/** - * camel_imap4_engine_iterate: - * @engine: IMAP4 engine - * - * Processes the first command in the queue. - * - * Returns the id of the processed command, 0 if there were no - * commands to process, or -1 on error. - * - * Note: more details on the error will be held on the - * CamelIMAP4Command that failed. - **/ -int -camel_imap4_engine_iterate (CamelIMAP4Engine *engine) -{ - CamelIMAP4Command *ic, *nic; - GPtrArray *resp_codes; - int retval = -1; - - if (e_dlist_empty (&engine->queue)) - return 0; - - /* This sucks... it would be nicer if we didn't have to check the stream's disconnected status */ - if ((engine->state == CAMEL_IMAP4_ENGINE_DISCONNECTED || engine->istream->disconnected) && !engine->reconnecting) { - CamelException rex; - gboolean connected; - - camel_exception_init (&rex); - engine->reconnecting = TRUE; - connected = engine->reconnect (engine, &rex); - engine->reconnecting = FALSE; - - if (!connected) { - /* pop the first command and act as tho it failed (which, technically, it did...) */ - ic = (CamelIMAP4Command *) e_dlist_remhead (&engine->queue); - ic->status = CAMEL_IMAP4_COMMAND_ERROR; - camel_exception_xfer (&ic->ex, &rex); - return -1; - } - } - - /* check to see if we need to pre-queue a SELECT, if so do it */ - engine_prequeue_folder_select (engine); - - engine->current = ic = (CamelIMAP4Command *) e_dlist_remhead (&engine->queue); - ic->status = CAMEL_IMAP4_COMMAND_ACTIVE; - - if (imap4_process_command (engine, ic) != -1) { - if (engine_state_change (engine, ic) == -1) { - /* This can ONLY happen if @ic was the pre-queued SELECT command - * and it got a NO or BAD response. - * - * We have to pop the next imap4 command or we'll get into an - * infinite loop. In order to provide @nic's owner with as much - * information as possible, we move all @ic status information - * over to @nic and pretend we just processed @nic. - **/ - - nic = (CamelIMAP4Command *) e_dlist_remhead (&engine->queue); - - nic->status = ic->status; - nic->result = ic->result; - resp_codes = nic->resp_codes; - nic->resp_codes = ic->resp_codes; - ic->resp_codes = resp_codes; - - camel_exception_xfer (&nic->ex, &ic->ex); - - camel_imap4_command_unref (ic); - ic = nic; - } - - retval = ic->id; - } - - camel_imap4_command_unref (ic); - - return retval; -} - - -/** - * camel_imap4_engine_queue: - * @engine: IMAP4 engine - * @folder: IMAP4 folder that the command will affect (or %NULL if it doesn't matter) - * @format: command format - * @Varargs: arguments - * - * Basically the same as camel_imap4_command_new() except that this - * function also places the command in the engine queue. - * - * Returns the CamelIMAP4Command. - **/ -CamelIMAP4Command * -camel_imap4_engine_queue (CamelIMAP4Engine *engine, CamelFolder *folder, const char *format, ...) -{ - CamelIMAP4Command *ic; - va_list args; - - g_return_val_if_fail (CAMEL_IS_IMAP4_ENGINE (engine), NULL); - - va_start (args, format); - ic = camel_imap4_command_newv (engine, (CamelIMAP4Folder *) folder, format, args); - va_end (args); - - ic->id = engine->nextid++; - e_dlist_addtail (&engine->queue, (EDListNode *) ic); - camel_imap4_command_ref (ic); - - return ic; -} - - -/** - * camel_imap4_engine_prequeue: - * @engine: IMAP4 engine - * @folder: IMAP4 folder that the command will affect (or %NULL if it doesn't matter) - * @format: command format - * @Varargs: arguments - * - * Same as camel_imap4_engine_queue() except this places the new - * command at the head of the queue. - * - * Returns the CamelIMAP4Command. - **/ -CamelIMAP4Command * -camel_imap4_engine_prequeue (CamelIMAP4Engine *engine, CamelFolder *folder, const char *format, ...) -{ - CamelIMAP4Command *ic; - va_list args; - - g_return_val_if_fail (CAMEL_IS_IMAP4_ENGINE (engine), NULL); - - va_start (args, format); - ic = camel_imap4_command_newv (engine, (CamelIMAP4Folder *) folder, format, args); - va_end (args); - - if (e_dlist_empty (&engine->queue)) { - e_dlist_addtail (&engine->queue, (EDListNode *) ic); - ic->id = engine->nextid++; - } else { - CamelIMAP4Command *nic; - EDListNode *node; - - node = (EDListNode *) ic; - e_dlist_addhead (&engine->queue, node); - nic = (CamelIMAP4Command *) node->next; - ic->id = nic->id - 1; - - if (ic->id == 0) { - /* increment all command ids */ - node = engine->queue.head; - while (node->next) { - nic = (CamelIMAP4Command *) node; - node = node->next; - nic->id++; - } - } - } - - camel_imap4_command_ref (ic); - - return ic; -} - - -/** - * 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) -{ - EDListNode *node = (EDListNode *) ic; - - if (node->next == NULL && node->prev == NULL) - return; - - e_dlist_remove (node); - node->next = NULL; - node->prev = NULL; - - camel_imap4_command_unref (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) -{ - if (camel_imap4_stream_next_token (engine->istream, token) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("IMAP4 server %s unexpectedly disconnected: %s"), - engine->url->host, errno ? g_strerror (errno) : _("Unknown")); - - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - - return -1; - } - - return 0; -} - - -/** - * 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) -{ - camel_imap4_token_t token; - unsigned char *literal; - int retval; - size_t n; - - do { - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token == CAMEL_IMAP4_TOKEN_LITERAL) { - while ((retval = camel_imap4_stream_literal (engine->istream, &literal, &n)) == 1) - ; - - if (retval == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("IMAP4 server %s unexpectedly disconnected: %s"), - engine->url->host, errno ? g_strerror (errno) : _("Unknown")); - - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - - return -1; - } - } - } while (token.token != '\n'); - - return 0; -} - - -/** - * 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) -{ - GByteArray *linebuf = NULL; - unsigned char *buf; - size_t buflen; - int retval; - - if (line != NULL) - linebuf = g_byte_array_new (); - - while ((retval = camel_imap4_stream_line (engine->istream, &buf, &buflen)) > 0) { - if (linebuf != NULL) - g_byte_array_append (linebuf, buf, buflen); - } - - if (retval == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("IMAP4 server %s unexpectedly disconnected: %s"), - engine->url->host, errno ? g_strerror (errno) : _("Unknown")); - - if (linebuf != NULL) - g_byte_array_free (linebuf, TRUE); - - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - - return -1; - } - - if (linebuf != NULL) { - g_byte_array_append (linebuf, buf, buflen); - - *line = linebuf->data; - *len = linebuf->len; - - g_byte_array_free (linebuf, FALSE); - } - - return 0; -} - - -/** - * 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) -{ - GByteArray *literalbuf = NULL; - unsigned char *buf; - size_t buflen; - int retval; - - if (literal != NULL) - literalbuf = g_byte_array_new (); - - while ((retval = camel_imap4_stream_literal (engine->istream, &buf, &buflen)) > 0) { - if (literalbuf != NULL) - g_byte_array_append (literalbuf, buf, buflen); - } - - if (retval == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("IMAP4 server %s unexpectedly disconnected: %s"), - engine->url->host, errno ? g_strerror (errno) : _("Unknown")); - - if (literalbuf != NULL) - g_byte_array_free (literalbuf, TRUE); - - engine->state = CAMEL_IMAP4_ENGINE_DISCONNECTED; - - return -1; - } - - if (literalbuf != NULL) { - g_byte_array_append (literalbuf, buf, buflen); - g_byte_array_append (literalbuf, "", 1); - - *literal = literalbuf->data; - *len = literalbuf->len - 1; - - g_byte_array_free (literalbuf, FALSE); - } - - return 0; -} - - -/** - * 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) -{ - switch (rcode->code) { - case CAMEL_IMAP4_RESP_CODE_PARSE: - g_free (rcode->v.parse); - break; - case CAMEL_IMAP4_RESP_CODE_NEWNAME: - g_free (rcode->v.newname[0]); - g_free (rcode->v.newname[1]); - break; - case CAMEL_IMAP4_RESP_CODE_COPYUID: - g_free (rcode->v.copyuid.srcset); - g_free (rcode->v.copyuid.destset); - break; - default: - break; - } - - g_free (rcode); -} diff --git a/camel/providers/imap4/camel-imap4-engine.h b/camel/providers/imap4/camel-imap4-engine.h deleted file mode 100644 index b4d8df2e8d..0000000000 --- a/camel/providers/imap4/camel-imap4-engine.h +++ /dev/null @@ -1,234 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifndef __CAMEL_IMAP4_ENGINE_H__ -#define __CAMEL_IMAP4_ENGINE_H__ - -#include <stdarg.h> - -#include <glib.h> - -#include <libedataserver/e-msgport.h> - -#include <camel/camel-stream.h> -#include <camel/camel-folder.h> -#include <camel/camel-session.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define CAMEL_TYPE_IMAP4_ENGINE (camel_imap4_engine_get_type ()) -#define CAMEL_IMAP4_ENGINE(obj) (CAMEL_CHECK_CAST ((obj), CAMEL_TYPE_IMAP4_ENGINE, CamelIMAP4Engine)) -#define CAMEL_IMAP4_ENGINE_CLASS(klass) (CAMEL_CHECK_CLASS_CAST ((klass), CAMEL_TYPE_IMAP4_ENGINE, CamelIMAP4EngineClass)) -#define CAMEL_IS_IMAP4_ENGINE(obj) (CAMEL_CHECK_TYPE ((obj), CAMEL_TYPE_IMAP4_ENGINE)) -#define CAMEL_IS_IMAP4_ENGINE_CLASS(klass) (CAMEL_CHECK_CLASS_TYPE ((klass), CAMEL_TYPE_IMAP4_ENGINE)) -#define CAMEL_IMAP4_ENGINE_GET_CLASS(obj) (CAMEL_CHECK_GET_CLASS ((obj), CAMEL_TYPE_IMAP4_ENGINE, CamelIMAP4EngineClass)) - -typedef struct _CamelIMAP4Engine CamelIMAP4Engine; -typedef struct _CamelIMAP4EngineClass CamelIMAP4EngineClass; - -struct _camel_imap4_token_t; -struct _CamelIMAP4Command; -struct _CamelIMAP4Folder; -struct _CamelIMAP4Stream; - -typedef enum { - CAMEL_IMAP4_ENGINE_DISCONNECTED, - CAMEL_IMAP4_ENGINE_CONNECTED, - CAMEL_IMAP4_ENGINE_PREAUTH, - CAMEL_IMAP4_ENGINE_AUTHENTICATED, - CAMEL_IMAP4_ENGINE_SELECTED, -} camel_imap4_engine_t; - -typedef enum { - CAMEL_IMAP4_LEVEL_UNKNOWN, - CAMEL_IMAP4_LEVEL_IMAP4, - CAMEL_IMAP4_LEVEL_IMAP4REV1 -} camel_imap4_level_t; - -enum { - CAMEL_IMAP4_CAPABILITY_IMAP4 = (1 << 0), - CAMEL_IMAP4_CAPABILITY_IMAP4REV1 = (1 << 1), - CAMEL_IMAP4_CAPABILITY_STATUS = (1 << 2), - CAMEL_IMAP4_CAPABILITY_NAMESPACE = (1 << 3), - CAMEL_IMAP4_CAPABILITY_UIDPLUS = (1 << 4), - CAMEL_IMAP4_CAPABILITY_LITERALPLUS = (1 << 5), - CAMEL_IMAP4_CAPABILITY_LOGINDISABLED = (1 << 6), - CAMEL_IMAP4_CAPABILITY_STARTTLS = (1 << 7), - CAMEL_IMAP4_CAPABILITY_IDLE = (1 << 8), - CAMEL_IMAP4_CAPABILITY_QUOTA = (1 << 9), - CAMEL_IMAP4_CAPABILITY_ACL = (1 << 10), - CAMEL_IMAP4_CAPABILITY_MULTIAPPEND = (1 << 11), - CAMEL_IMAP4_CAPABILITY_useful_lsub = (1 << 12), - CAMEL_IMAP4_CAPABILITY_utf8_search = (1 << 13), -}; - -typedef enum { - CAMEL_IMAP4_RESP_CODE_ALERT, - CAMEL_IMAP4_RESP_CODE_BADCHARSET, - CAMEL_IMAP4_RESP_CODE_CAPABILITY, - CAMEL_IMAP4_RESP_CODE_PARSE, - CAMEL_IMAP4_RESP_CODE_PERM_FLAGS, - CAMEL_IMAP4_RESP_CODE_READONLY, - CAMEL_IMAP4_RESP_CODE_READWRITE, - CAMEL_IMAP4_RESP_CODE_TRYCREATE, - CAMEL_IMAP4_RESP_CODE_UIDNEXT, - CAMEL_IMAP4_RESP_CODE_UIDVALIDITY, - CAMEL_IMAP4_RESP_CODE_UNSEEN, - CAMEL_IMAP4_RESP_CODE_NEWNAME, - CAMEL_IMAP4_RESP_CODE_APPENDUID, - CAMEL_IMAP4_RESP_CODE_COPYUID, - CAMEL_IMAP4_RESP_CODE_UNKNOWN, -} camel_imap4_resp_code_t; - -typedef struct _CamelIMAP4RespCode { - camel_imap4_resp_code_t code; - union { - guint32 flags; - char *parse; - guint32 uidnext; - guint32 uidvalidity; - guint32 unseen; - char *newname[2]; - struct { - guint32 uidvalidity; - guint32 uid; - } appenduid; - struct { - guint32 uidvalidity; - char *srcset; - char *destset; - } copyuid; - } v; -} CamelIMAP4RespCode; - -enum { - CAMEL_IMAP4_UNTAGGED_ERROR = -1, - CAMEL_IMAP4_UNTAGGED_OK, - CAMEL_IMAP4_UNTAGGED_NO, - CAMEL_IMAP4_UNTAGGED_BAD, - CAMEL_IMAP4_UNTAGGED_PREAUTH, - CAMEL_IMAP4_UNTAGGED_HANDLED, -}; - -typedef struct _CamelIMAP4Namespace { - struct _CamelIMAP4Namespace *next; - char *path; - char sep; -} CamelIMAP4Namespace; - -typedef struct _CamelIMAP4NamespaceList { - CamelIMAP4Namespace *personal; - CamelIMAP4Namespace *other; - CamelIMAP4Namespace *shared; -} CamelIMAP4NamespaceList; - -enum { - CAMEL_IMAP4_ENGINE_MAXLEN_LINE, - CAMEL_IMAP4_ENGINE_MAXLEN_TOKEN -}; - -typedef gboolean (* CamelIMAP4ReconnectFunc) (CamelIMAP4Engine *engine, CamelException *ex); - -struct _CamelIMAP4Engine { - CamelObject parent_object; - - CamelIMAP4ReconnectFunc reconnect; - gboolean reconnecting; - - CamelSession *session; - CamelService *service; - CamelURL *url; - - camel_imap4_engine_t state; - camel_imap4_level_t level; - guint32 capa; - - guint32 maxlen:31; - guint32 maxlentype:1; - - CamelIMAP4NamespaceList namespaces; - GHashTable *authtypes; /* supported authtypes */ - - struct _CamelIMAP4Stream *istream; - CamelStream *ostream; - - unsigned char tagprefix; /* 'A'..'Z' */ - unsigned int tag; /* next command tag */ - int nextid; - - struct _CamelIMAP4Folder *folder; /* currently selected folder */ - - EDList queue; /* queue of waiting commands */ - struct _CamelIMAP4Command *current; -}; - -struct _CamelIMAP4EngineClass { - CamelObjectClass parent_class; - - unsigned char tagprefix; -}; - - -CamelType camel_imap4_engine_get_type (void); - -CamelIMAP4Engine *camel_imap4_engine_new (CamelService *service, CamelIMAP4ReconnectFunc reconnect); - -/* returns 0 on success or -1 on error */ -int camel_imap4_engine_take_stream (CamelIMAP4Engine *engine, CamelStream *stream, CamelException *ex); - -int camel_imap4_engine_capability (CamelIMAP4Engine *engine, CamelException *ex); -int camel_imap4_engine_namespace (CamelIMAP4Engine *engine, CamelException *ex); - -int camel_imap4_engine_select_folder (CamelIMAP4Engine *engine, CamelFolder *folder, CamelException *ex); - -struct _CamelIMAP4Command *camel_imap4_engine_queue (CamelIMAP4Engine *engine, CamelFolder *folder, - const char *format, ...); -struct _CamelIMAP4Command *camel_imap4_engine_prequeue (CamelIMAP4Engine *engine, CamelFolder *folder, - const char *format, ...); - -void camel_imap4_engine_dequeue (CamelIMAP4Engine *engine, struct _CamelIMAP4Command *ic); - -int camel_imap4_engine_iterate (CamelIMAP4Engine *engine); - - -/* untagged response utility functions */ -int camel_imap4_engine_handle_untagged_1 (CamelIMAP4Engine *engine, struct _camel_imap4_token_t *token, CamelException *ex); -void camel_imap4_engine_handle_untagged (CamelIMAP4Engine *engine, CamelException *ex); - -/* stream wrapper utility functions */ -int camel_imap4_engine_next_token (CamelIMAP4Engine *engine, struct _camel_imap4_token_t *token, CamelException *ex); -int camel_imap4_engine_line (CamelIMAP4Engine *engine, unsigned char **line, size_t *len, CamelException *ex); -int camel_imap4_engine_literal (CamelIMAP4Engine *engine, unsigned char **literal, size_t *len, CamelException *ex); -int camel_imap4_engine_nstring (CamelIMAP4Engine *engine, unsigned char **nstring, CamelException *ex); -int camel_imap4_engine_eat_line (CamelIMAP4Engine *engine, CamelException *ex); - - -/* response code stuff */ -int camel_imap4_engine_parse_resp_code (CamelIMAP4Engine *engine, CamelException *ex); -void camel_imap4_resp_code_free (CamelIMAP4RespCode *rcode); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_IMAP4_ENGINE_H__ */ diff --git a/camel/providers/imap4/camel-imap4-folder.c b/camel/providers/imap4/camel-imap4-folder.c deleted file mode 100644 index 9326dd418f..0000000000 --- a/camel/providers/imap4/camel-imap4-folder.c +++ /dev/null @@ -1,1178 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <glib.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <dirent.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <time.h> - -#include <camel/camel-utf8.h> -#include <camel/camel-private.h> -#include <camel/camel-file-utils.h> -#include <camel/camel-mime-message.h> -#include <camel/camel-stream-mem.h> -#include <camel/camel-stream-filter.h> -#include <camel/camel-mime-filter-crlf.h> -#include <camel/camel-i18n.h> - -#include "camel-imap4-utils.h" -#include "camel-imap4-store.h" -#include "camel-imap4-engine.h" -#include "camel-imap4-folder.h" -#include "camel-imap4-stream.h" -#include "camel-imap4-command.h" -#include "camel-imap4-summary.h" -#include "camel-imap4-search.h" - -#define d(x) x - -static GSList *imap4_folder_props = NULL; - -static CamelProperty imap4_prop_list[] = { - { CAMEL_IMAP4_FOLDER_SYNC_OFFLINE, "sync_offline", N_("Copy folder content locally for offline operation") }, -}; - -static void camel_imap4_folder_class_init (CamelIMAP4FolderClass *klass); -static void camel_imap4_folder_init (CamelIMAP4Folder *folder, CamelIMAP4FolderClass *klass); -static void camel_imap4_folder_finalize (CamelObject *object); - -static int imap4_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args); -static int imap4_setv (CamelObject *object, CamelException *ex, CamelArgV *args); - -static void imap4_sync (CamelFolder *folder, gboolean expunge, CamelException *ex); -static void imap4_refresh_info (CamelFolder *folder, CamelException *ex); -static void imap4_expunge (CamelFolder *folder, CamelException *ex); -static CamelMimeMessage *imap4_get_message (CamelFolder *folder, const char *uid, CamelException *ex); -static void imap4_append_message (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **appended_uid, CamelException *ex); -static void imap4_transfer_messages_to (CamelFolder *src, GPtrArray *uids, CamelFolder *dest, - GPtrArray **transferred_uids, gboolean move, CamelException *ex); -static GPtrArray *imap4_search_by_expression (CamelFolder *folder, const char *expr, CamelException *ex); -static GPtrArray *imap4_search_by_uids (CamelFolder *folder, const char *expr, GPtrArray *uids, CamelException *ex); -static void imap4_search_free (CamelFolder *folder, GPtrArray *uids); - - -static CamelFolderClass *parent_class = NULL; - - -CamelType -camel_imap4_folder_get_type (void) -{ - static CamelType type = 0; - - if (!type) { - type = camel_type_register (CAMEL_FOLDER_TYPE, - "CamelIMAP4Folder", - sizeof (CamelIMAP4Folder), - sizeof (CamelIMAP4FolderClass), - (CamelObjectClassInitFunc) camel_imap4_folder_class_init, - NULL, - (CamelObjectInitFunc) camel_imap4_folder_init, - (CamelObjectFinalizeFunc) camel_imap4_folder_finalize); - } - - return type; -} - -static void -camel_imap4_folder_class_init (CamelIMAP4FolderClass *klass) -{ - CamelFolderClass *folder_class = (CamelFolderClass *) klass; - CamelObjectClass *object_class = (CamelObjectClass *) klass; - int i; - - parent_class = (CamelFolderClass *) camel_type_get_global_classfuncs (CAMEL_FOLDER_TYPE); - - for (i = 0; i < G_N_ELEMENTS (imap4_prop_list); i++) { - imap4_prop_list[i].description = _(imap4_prop_list[i].description); - imap4_folder_props = g_slist_prepend (imap4_folder_props, &imap4_prop_list[i]); - } - - object_class->getv = imap4_getv; - object_class->setv = imap4_setv; - - folder_class->sync = imap4_sync; - folder_class->refresh_info = imap4_refresh_info; - folder_class->expunge = imap4_expunge; - folder_class->get_message = imap4_get_message; - folder_class->append_message = imap4_append_message; - folder_class->transfer_messages_to = imap4_transfer_messages_to; - folder_class->search_by_expression = imap4_search_by_expression; - folder_class->search_by_uids = imap4_search_by_uids; - folder_class->search_free = imap4_search_free; -} - -static void -camel_imap4_folder_init (CamelIMAP4Folder *folder, CamelIMAP4FolderClass *klass) -{ - ((CamelFolder *) folder)->folder_flags |= CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | CAMEL_FOLDER_HAS_SEARCH_CAPABILITY; - - folder->sync_offline = FALSE; - folder->utf7_name = NULL; - folder->cachedir = NULL; - folder->search = NULL; -} - -static void -camel_imap4_folder_finalize (CamelObject *object) -{ - CamelIMAP4Folder *folder = (CamelIMAP4Folder *) object; - - camel_object_unref (folder->search); - - if (folder->cache) - camel_object_unref (folder->cache); - - g_free (folder->utf7_name); - g_free (folder->cachedir); -} - -static int -imap4_getv (CamelObject *object, CamelException *ex, CamelArgGetV *args) -{ - CamelArgGetV props; - int i, count = 0; - guint32 tag; - - for (i = 0; i <args->argc; i++) { - CamelArgGet *arg = &args->argv[i]; - - tag = arg->tag; - - switch (tag & CAMEL_ARG_TAG) { - case CAMEL_OBJECT_ARG_PERSISTENT_PROPERTIES: - case CAMEL_FOLDER_ARG_PROPERTIES: - props.argc = 1; - props.argv[0] = *arg; - ((CamelObjectClass *) parent_class)->getv (object, ex, &props); - *arg->ca_ptr = g_slist_concat (*arg->ca_ptr, g_slist_copy (imap4_folder_props)); - break; - case CAMEL_IMAP4_FOLDER_ARG_SYNC_OFFLINE: - *arg->ca_int = ((CamelIMAP4Folder *) object)->sync_offline; - break; - default: - count++; - continue; - } - - arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE; - } - - if (count) - return ((CamelObjectClass *) parent_class)->getv (object, ex, args); - - return 0; -} - -static int -imap4_setv (CamelObject *object, CamelException *ex, CamelArgV *args) -{ - CamelIMAP4Folder *folder = (CamelIMAP4Folder *) object; - gboolean save = FALSE; - guint32 tag; - int i; - - for (i = 0; i < args->argc; i++) { - CamelArg *arg = &args->argv[i]; - - tag = arg->tag; - - switch (tag & CAMEL_ARG_TAG) { - case CAMEL_IMAP4_FOLDER_ARG_SYNC_OFFLINE: - if (folder->sync_offline != arg->ca_int) { - folder->sync_offline = arg->ca_int; - save = TRUE; - } - break; - default: - continue; - } - - arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE; - } - - if (save) - camel_object_state_write (object); - - return ((CamelObjectClass *) parent_class)->setv (object, ex, args); -} - - -static char * -imap_get_summary_filename (const char *path) -{ - /* /path/to/imap/summary */ - return g_build_filename (path, "summary", NULL); -} - -static char * -imap_build_filename (const char *toplevel_dir, const char *full_name) -{ - const char *inptr = full_name; - int subdirs = 0; - char *path, *p; - - if (*full_name == '\0') - return g_strdup (toplevel_dir); - - while (*inptr != '\0') { - if (*inptr == '/') - subdirs++; - inptr++; - } - - path = g_malloc (strlen (toplevel_dir) + (inptr - full_name) + (12 * subdirs) + 2); - p = g_stpcpy (path, toplevel_dir); - - if (p[-1] != '/') - *p++ = '/'; - - inptr = full_name; - while (*inptr != '\0') { - while (*inptr != '/' && *inptr != '\0') - *p++ = *inptr++; - - if (*inptr == '/') { - p = g_stpcpy (p, "/subfolders/"); - inptr++; - - /* strip extranaeous '/'s */ - while (*inptr == '/') - inptr++; - } - } - - *p = '\0'; - - return path; -} - -static char * -imap_store_build_filename (void *store, const char *full_name) -{ - CamelIMAP4Store *imap_store = (CamelIMAP4Store *) store; - char *toplevel_dir; - char *path; - - toplevel_dir = g_strdup_printf ("%s/folders", imap_store->storage_path); - path = imap_build_filename (toplevel_dir, full_name); - g_free (toplevel_dir); - - return path; -} - - -CamelFolder * -camel_imap4_folder_new (CamelStore *store, const char *full_name, CamelException *ex) -{ - CamelIMAP4Folder *imap_folder; - char *utf7_name, *name, *p; - CamelFolder *folder; - char *path; - char sep; - - if (!(p = strrchr (full_name, '/'))) - p = (char *) full_name; - else - p++; - - name = g_alloca (strlen (p) + 1); - strcpy (name, p); - - utf7_name = g_alloca (strlen (full_name) + 1); - strcpy (utf7_name, full_name); - - sep = camel_imap4_get_path_delim (((CamelIMAP4Store *) store)->summary, full_name); - if (sep != '/') { - p = utf7_name; - while (*p != '\0') { - if (*p == '/') - *p = sep; - p++; - } - } - - utf7_name = camel_utf8_utf7 (utf7_name); - - folder = (CamelFolder *) (imap_folder = (CamelIMAP4Folder *) camel_object_new (CAMEL_TYPE_IMAP4_FOLDER)); - camel_folder_construct (folder, store, full_name, name); - imap_folder->utf7_name = utf7_name; - - folder->summary = camel_imap4_summary_new (folder); - imap_folder->cachedir = imap_store_build_filename (store, folder->full_name); - camel_mkdir (imap_folder->cachedir, 0777); - - imap_folder->cache = camel_data_cache_new (imap_folder->cachedir, 0, NULL); - - path = imap_get_summary_filename (imap_folder->cachedir); - camel_folder_summary_set_filename (folder->summary, path); - g_free (path); - - imap_folder->search = camel_imap4_search_new (((CamelIMAP4Store *) store)->engine, imap_folder->cachedir); - - if (camel_session_is_online (((CamelService *) store)->session)) { - /* we don't care if the summary loading fails here */ - camel_folder_summary_load (folder->summary); - - if (camel_imap4_engine_select_folder (((CamelIMAP4Store *) store)->engine, folder, ex) == -1) { - camel_object_unref (folder); - folder = NULL; - } - - if (folder && camel_imap4_summary_flush_updates (folder->summary, ex) == -1) { - camel_object_unref (folder); - folder = NULL; - } - } else { - /* we *do* care if summary loading fails here though */ - if (camel_folder_summary_load (folder->summary) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_PATH, - _("Cannot access folder `%s': %s"), - full_name, g_strerror (ENOENT)); - - camel_object_unref (folder); - folder = NULL; - } - } - - return folder; -} - -const char * -camel_imap4_folder_utf7_name (CamelIMAP4Folder *folder) -{ - return folder->utf7_name; -} - - -static struct { - const char *name; - guint32 flag; -} imap4_flags[] = { - { "\\Answered", CAMEL_MESSAGE_ANSWERED }, - { "\\Deleted", CAMEL_MESSAGE_DELETED }, - { "\\Draft", CAMEL_MESSAGE_DRAFT }, - { "\\Flagged", CAMEL_MESSAGE_FLAGGED }, - /*{ "$Forwarded", CAMEL_MESSAGE_FORWARDED },*/ - { "\\Seen", CAMEL_MESSAGE_SEEN }, -}; - - -static int -imap4_sync_flag (CamelFolder *folder, GPtrArray *infos, char onoff, const char *flag, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - CamelIMAP4Command *ic; - int i, id, retval = 0; - char *set = NULL; - - for (i = 0; i < infos->len; ) { - i += camel_imap4_get_uid_set (engine, folder->summary, infos, i, 30 + strlen (flag), &set); - - ic = camel_imap4_engine_queue (engine, folder, "UID STORE %s %cFLAGS.SILENT (%s)\r\n", set, onoff, flag); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - g_free (set); - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - - return -1; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot sync flags to folder `%s': Unknown"), - folder->full_name); - retval = -1; - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot sync flags to folder `%s': Bad command"), - folder->full_name); - retval = -1; - break; - } - - camel_imap4_command_unref (ic); - - if (retval == -1) - return -1; - } - - return 0; -} - -static int -imap4_sync_changes (CamelFolder *folder, GPtrArray *sync, CamelException *ex) -{ - CamelIMAP4MessageInfo *iinfo; - GPtrArray *on_set, *off_set; - CamelMessageInfo *info; - flags_diff_t diff; - int retval = 0; - int i, j; - - if (folder->permanent_flags == 0) - return 0; - - on_set = g_ptr_array_new (); - off_set = g_ptr_array_new (); - - /* construct commands to sync system and user flags */ - for (i = 0; i < G_N_ELEMENTS (imap4_flags); i++) { - if (!(imap4_flags[i].flag & folder->permanent_flags)) - continue; - - for (j = 0; j < sync->len; j++) { - iinfo = (CamelIMAP4MessageInfo *) (info = sync->pdata[j]); - camel_imap4_flags_diff (&diff, iinfo->server_flags, iinfo->info.flags); - if (diff.changed & imap4_flags[i].flag) { - if (diff.bits & imap4_flags[i].flag) { - g_ptr_array_add (on_set, info); - } else { - g_ptr_array_add (off_set, info); - } - } - } - - if (on_set->len > 0) { - if ((retval = imap4_sync_flag (folder, on_set, '+', imap4_flags[i].name, ex)) == -1) - break; - - g_ptr_array_set_size (on_set, 0); - } - - if (off_set->len > 0) { - if ((retval = imap4_sync_flag (folder, off_set, '-', imap4_flags[i].name, ex)) == -1) - break; - - g_ptr_array_set_size (off_set, 0); - } - } - - g_ptr_array_free (on_set, TRUE); - g_ptr_array_free (off_set, TRUE); - - if (retval == -1) - return-1; - - for (i = 0; i < sync->len; i++) { - iinfo = (CamelIMAP4MessageInfo *) (info = sync->pdata[i]); - iinfo->info.flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED; - iinfo->server_flags = iinfo->info.flags & folder->permanent_flags; - } - - return 0; -} - -static void -imap4_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - CamelSession *session = ((CamelService *) folder->parent_store)->session; - CamelIMAP4MessageInfo *iinfo; - CamelMessageInfo *info; - CamelIMAP4Command *ic; - flags_diff_t diff; - GPtrArray *sync; - int id, max, i; - int retval; - - if (!camel_session_is_online (session)) - return; - - CAMEL_SERVICE_LOCK (folder->parent_store, connect_lock); - - /* gather a list of changes to sync to the server */ - sync = g_ptr_array_new (); - max = camel_folder_summary_count (folder->summary); - for (i = 0; i < max; i++) { - iinfo = (CamelIMAP4MessageInfo *) (info = camel_folder_summary_index (folder->summary, i)); - if (iinfo->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) { - camel_imap4_flags_diff (&diff, iinfo->server_flags, iinfo->info.flags); - diff.changed &= folder->permanent_flags; - - /* weed out flag changes that we can't sync to the server */ - if (!diff.changed) - camel_message_info_free(info); - else - g_ptr_array_add (sync, info); - } else { - camel_message_info_free(info); - } - } - - if (sync->len > 0) { - retval = imap4_sync_changes (folder, sync, ex); - - for (i = 0; i < sync->len; i++) - camel_message_info_free(sync->pdata[i]); - - g_ptr_array_free (sync, TRUE); - - if (retval == -1) - goto done; - } else { - g_ptr_array_free (sync, TRUE); - } - - if (expunge) { - ic = camel_imap4_engine_queue (engine, folder, "EXPUNGE\r\n"); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - camel_imap4_summary_flush_updates (folder->summary, ex); - break; - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot expunge folder `%s': Unknown"), - folder->full_name); - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot expunge folder `%s': Bad command"), - folder->full_name); - break; - } - - camel_imap4_command_unref (ic); - } else { - camel_imap4_summary_flush_updates (folder->summary, ex); - } - - camel_folder_summary_save (folder->summary); - - done: - - CAMEL_SERVICE_UNLOCK (folder->parent_store, connect_lock); -} - -static void -imap4_expunge (CamelFolder *folder, CamelException *ex) -{ - imap4_sync (folder, TRUE, ex); -} - -static void -imap4_refresh_info (CamelFolder *folder, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - CamelSession *session = ((CamelService *) folder->parent_store)->session; - CamelFolder *selected = (CamelFolder *) engine->folder; - CamelIMAP4Command *ic; - int id; - - if (!camel_session_is_online (session)) - return; - - CAMEL_SERVICE_LOCK (folder->parent_store, connect_lock); - - if (folder != selected) { - if (camel_imap4_engine_select_folder (engine, folder, ex) == -1) - goto done; - - ((CamelIMAP4Summary *) folder->summary)->update_flags = TRUE; - } else { - ic = camel_imap4_engine_queue (engine, NULL, "NOOP\r\n"); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) - camel_exception_xfer (ex, &ic->ex); - - camel_imap4_command_unref (ic); - - if (camel_exception_is_set (ex)) - goto done; - } - - camel_imap4_summary_flush_updates (folder->summary, ex); - - done: - - CAMEL_SERVICE_UNLOCK (folder->parent_store, connect_lock); -} - -static int -untagged_fetch (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, guint32 index, camel_imap4_token_t *token, CamelException *ex) -{ - CamelFolderSummary *summary = ((CamelFolder *) engine->folder)->summary; - CamelStream *fstream, *stream = ic->user_data; - CamelFolderChangeInfo *changes; - CamelIMAP4MessageInfo *iinfo; - CamelMessageInfo *info; - CamelMimeFilter *crlf; - guint32 flags; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - /* parse the FETCH response list */ - if (token->token != '(') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - return -1; - } - - do { - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token == ')' || token->token == '\n') - break; - - if (token->token != CAMEL_IMAP4_TOKEN_ATOM) - goto unexpected; - - if (!strcmp (token->v.atom, "BODY[")) { - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token != ']') - goto unexpected; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token != CAMEL_IMAP4_TOKEN_LITERAL) - goto unexpected; - - fstream = (CamelStream *) camel_stream_filter_new_with_stream (stream); - crlf = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_DECODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); - camel_stream_filter_add ((CamelStreamFilter *) fstream, crlf); - camel_object_unref (crlf); - - camel_stream_write_to_stream ((CamelStream *) engine->istream, fstream); - camel_stream_flush (fstream); - camel_object_unref (fstream); - } else if (!strcmp (token->v.atom, "UID")) { - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token != CAMEL_IMAP4_TOKEN_NUMBER || token->v.number == 0) - goto unexpected; - } else if (!strcmp (token->v.atom, "FLAGS")) { - /* even though we didn't request this bit of information, it might be - * given to us if another client recently changed the flags... */ - if (camel_imap4_parse_flags_list (engine, &flags, ex) == -1) - goto exception; - - if ((info = camel_folder_summary_index (summary, index - 1))) { - iinfo = (CamelIMAP4MessageInfo *) info; - iinfo->info.flags = camel_imap4_merge_flags (iinfo->server_flags, iinfo->info.flags, flags); - iinfo->server_flags = flags; - - changes = camel_folder_change_info_new (); - camel_folder_change_info_change_uid (changes, camel_message_info_uid (info)); - camel_object_trigger_event (engine->folder, "folder_changed", changes); - camel_folder_change_info_free (changes); - - camel_message_info_free(info); - } - } else { - /* wtf? */ - fprintf (stderr, "huh? %s?...\n", token->v.atom); - } - } while (1); - - if (token->token != ')') { - fprintf (stderr, "expected ')' to close untagged FETCH response\n"); - goto unexpected; - } - - return 0; - - unexpected: - - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - - exception: - - return -1; -} - -static CamelMimeMessage * -imap4_get_message (CamelFolder *folder, const char *uid, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - CamelSession *session = ((CamelService *) folder->parent_store)->session; - CamelIMAP4Folder *imap_folder = (CamelIMAP4Folder *) folder; - CamelMimeMessage *message = NULL; - CamelStream *stream, *cache; - CamelIMAP4Command *ic; - int id; - - CAMEL_SERVICE_LOCK (folder->parent_store, connect_lock); - - if (imap_folder->cache && (stream = camel_data_cache_get (imap_folder->cache, "cache", uid, ex))) { - message = camel_mime_message_new (); - - if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) message, stream) == -1) { - if (errno == EINTR) { - CAMEL_SERVICE_UNLOCK (folder->parent_store, connect_lock); - camel_exception_setv (ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); - camel_object_unref (message); - camel_object_unref (stream); - return NULL; - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get message %s: %s"), - uid, g_strerror (errno)); - camel_object_unref (message); - message = NULL; - } - } - - camel_object_unref (stream); - } - - if (message != NULL) { - CAMEL_SERVICE_UNLOCK (folder->parent_store, connect_lock); - return message; - } - - if (!camel_session_is_online (session)) { - CAMEL_SERVICE_UNLOCK (folder->parent_store, connect_lock); - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("This message is not available in offline mode.")); - return NULL; - } - - /* Note: While some hard-core IMAP extremists are probably - * going to flame me for fetching entire messages here, it's - * the *only* sure-fire way of working with all IMAP - * servers. There are numerous problems with fetching - * individual MIME parts from a good handful of IMAP servers - * which makes this a pain to do the Right Way (tm). For - * example: Courier-IMAP has "issues" parsing some multipart - * messages apparently, because BODY responses are often - * inaccurate. I'm also not very trusting of the free German - * IMAP hosting either (such as mail.gmx.net and imap.web.de) - * as they have proven themselves to be quite flakey wrt FETCH - * requests (they seem to be written exclusively for - * Outlook). Also, some IMAP servers such as GroupWise don't - * store mail in MIME format and so must re-construct the - * entire message in order to extract the requested part, so - * it is *mush* more efficient (generally) to just request the - * entire message anyway. */ - ic = camel_imap4_engine_queue (engine, folder, "UID FETCH %s BODY.PEEK[]\r\n", uid); - camel_imap4_command_register_untagged (ic, "FETCH", untagged_fetch); - ic->user_data = stream = camel_stream_mem_new (); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - camel_object_unref (stream); - goto done; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - camel_stream_reset (stream); - message = camel_mime_message_new (); - camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) message, stream); - camel_stream_reset (stream); - - /* cache the message locally */ - if (imap_folder->cache && (cache = camel_data_cache_add (imap_folder->cache, "cache", uid, NULL))) { - if (camel_stream_write_to_stream (stream, cache) == -1 - || camel_stream_flush (cache) == -1) - camel_data_cache_remove (imap_folder->cache, "cache", uid, NULL); - camel_object_unref (cache); - } - - break; - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get message %s from folder `%s': No such message"), - uid, folder->full_name); - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get message %s from folder `%s': Bad command"), - uid, folder->full_name); - break; - } - - camel_imap4_command_unref (ic); - - camel_object_unref (stream); - - done: - - CAMEL_SERVICE_UNLOCK (folder->parent_store, connect_lock); - - return message; -} - -static char *tm_months[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -static void -imap4_append_message (CamelFolder *folder, CamelMimeMessage *message, - const CamelMessageInfo *info, char **appended_uid, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - CamelSession *session = ((CamelService *) folder->parent_store)->session; - CamelIMAP4Summary *summary = (CamelIMAP4Summary *) folder->summary; - const CamelIMAP4MessageInfo *iinfo = (const CamelIMAP4MessageInfo *)info; - CamelIMAP4RespCode *resp; - CamelIMAP4Command *ic; - CamelFolderInfo *fi; - CamelException lex; - char flags[100], *p; - char date[50]; - struct tm tm; - int id, i; - - if (appended_uid) - *appended_uid = NULL; - - if (!camel_session_is_online (session)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot append messages to IMAP folders in offline mode.")); - return; - } - - CAMEL_SERVICE_LOCK (folder->parent_store, connect_lock); - - /* construct the option flags list */ - if (iinfo->info.flags & folder->permanent_flags) { - p = g_stpcpy (flags, " ("); - - for (i = 0; i < G_N_ELEMENTS (imap4_flags); i++) { - if ((iinfo->info.flags & imap4_flags[i].flag) & folder->permanent_flags) { - p = g_stpcpy (p, imap4_flags[i].name); - *p++ = ' '; - } - } - - p[-1] = ')'; - *p = '\0'; - } else { - flags[0] = '\0'; - } - - /* construct the optional date_time string */ - if (iinfo->info.date_received != (time_t) -1) { - int tzone; - -#ifdef HAVE_LOCALTIME_R - localtime_r (&info->date_received, &tm); -#else - memcpy (&tm, localtime (&iinfo->info.date_received), sizeof (tm)); -#endif - -#if defined (HAVE_TM_GMTOFF) - tzone = -tm.tm_gmtoff; -#elif defined (HAVE_TIMEZONE) - if (tm.tm_isdst > 0) { -#if defined (HAVE_ALTZONE) - tzone = altzone; -#else /* !defined (HAVE_ALTZONE) */ - tzone = (timezone - 3600); -#endif - } else { - tzone = timezone; - } -#else -#error Neither HAVE_TIMEZONE nor HAVE_TM_GMTOFF defined. Rerun autoheader, autoconf, etc. -#endif - - sprintf (date, " \"%02d-%s-%04d %02d:%02d:%02d %+05d\"", - tm.tm_mday, tm_months[tm.tm_mon], tm.tm_year + 1900, - tm.tm_hour, tm.tm_min, tm.tm_sec, tzone); - } else { - date[0] = '\0'; - } - - retry: - - if (engine->capa & CAMEL_IMAP4_CAPABILITY_UIDPLUS) - ic = camel_imap4_engine_queue (engine, NULL, "UID APPEND %F%s%s %L\r\n", flags, date, message); - else - ic = camel_imap4_engine_queue (engine, NULL, "APPEND %F%s%s %L\r\n", flags, date, message); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - CAMEL_SERVICE_UNLOCK (folder->parent_store, connect_lock); - return; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - if (!(engine->capa & CAMEL_IMAP4_CAPABILITY_UIDPLUS)) - break; - - if (!appended_uid) - break; - - for (i = 0; i < ic->resp_codes->len; i++) { - resp = ic->resp_codes->pdata[i]; - if (resp->code == CAMEL_IMAP4_RESP_CODE_APPENDUID) { - if (resp->v.appenduid.uidvalidity == summary->uidvalidity) - *appended_uid = g_strdup_printf ("%u", resp->v.appenduid.uid); - break; - } - } - break; - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: can we give the user any more information? */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message to folder `%s': Unknown error"), - folder->full_name); - - for (i = 0; i < ic->resp_codes->len; i++) { - resp = ic->resp_codes->pdata[i]; - if (resp->code == CAMEL_IMAP4_RESP_CODE_TRYCREATE) { - char *parent_name, *p; - - parent_name = g_alloca (strlen (folder->full_name) + 1); - if (!(p = strrchr (parent_name, '/'))) - *parent_name = '\0'; - else - *p = '\0'; - - if (!(fi = camel_store_create_folder (folder->parent_store, parent_name, folder->name, &lex))) { - camel_exception_clear (&lex); - break; - } - - camel_store_free_folder_info (folder->parent_store, fi); - camel_imap4_command_unref (ic); - camel_exception_clear (ex); - goto retry; - } - } - - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message to folder `%s': Bad command"), - folder->full_name); - - break; - default: - g_assert_not_reached (); - } - - camel_imap4_command_unref (ic); - - CAMEL_SERVICE_UNLOCK (folder->parent_store, connect_lock); -} - - -static int -info_uid_sort (const CamelMessageInfo **info0, const CamelMessageInfo **info1) -{ - guint32 uid0, uid1; - - uid0 = strtoul (camel_message_info_uid (*info0), NULL, 10); - uid1 = strtoul (camel_message_info_uid (*info1), NULL, 10); - - if (uid0 == uid1) - return 0; - - return uid0 < uid1 ? -1 : 1; -} - -static void -imap4_transfer_messages_to (CamelFolder *src, GPtrArray *uids, CamelFolder *dest, - GPtrArray **transferred_uids, gboolean move, CamelException *ex) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) src->parent_store)->engine; - CamelSession *session = ((CamelService *) src->parent_store)->session; - int i, j, n, id, dest_namelen; - CamelMessageInfo *info; - CamelIMAP4Command *ic; - GPtrArray *infos; - char *set; - - if (!camel_session_is_online (session)) { - if (move) - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot move messages to or from IMAP folders in offline mode.")); - else - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot copy messages to or from IMAP folders in offline mode.")); - - return; - } - - infos = g_ptr_array_new (); - for (i = 0; i < uids->len; i++) { - if (!(info = camel_folder_summary_uid (src->summary, uids->pdata[i]))) - continue; - - g_ptr_array_add (infos, info); - } - - if (infos->len == 0) { - g_ptr_array_free (infos, TRUE); - return; - } - - g_ptr_array_sort (infos, (GCompareFunc) info_uid_sort); - - CAMEL_SERVICE_LOCK (src->parent_store, connect_lock); - - dest_namelen = strlen (camel_imap4_folder_utf7_name ((CamelIMAP4Folder *) dest)); - - for (i = 0; i < infos->len; i += n) { - n = camel_imap4_get_uid_set (engine, src->summary, infos, i, 10 + dest_namelen, &set); - - ic = camel_imap4_engine_queue (engine, src, "UID COPY %s %F\r\n", set, dest); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - g_free (set); - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - g_free (set); - goto done; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - if (move) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot move messages from folder `%s' to folder `%s': Unknown"), - src->full_name, dest->full_name); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot copy messages from folder `%s' to folder `%s': Unknown"), - src->full_name, dest->full_name); - } - - goto done; - case CAMEL_IMAP4_RESULT_BAD: - if (move) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot move messages from folder `%s' to folder `%s': Bad command"), - src->full_name, dest->full_name); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot copy messages from folder `%s' to folder `%s': Bad command"), - src->full_name, dest->full_name); - } - - goto done; - } - - camel_imap4_command_unref (ic); - - if (move) { - for (j = i; j < n; j++) { - info = infos->pdata[j]; - camel_folder_set_message_flags (src, camel_message_info_uid (info), - CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_DELETED); - } - - camel_folder_summary_touch (src->summary); - } - } - - done: - - for (i = 0; i < infos->len; i++) - camel_message_info_free(infos->pdata[i]); - g_ptr_array_free (infos, TRUE); - - CAMEL_SERVICE_LOCK (src->parent_store, connect_lock); -} - -static GPtrArray * -imap4_search_by_expression (CamelFolder *folder, const char *expr, CamelException *ex) -{ - CamelIMAP4Folder *imap4_folder = (CamelIMAP4Folder *) folder; - GPtrArray *matches; - - CAMEL_SERVICE_LOCK(folder->parent_store, connect_lock); - - camel_folder_search_set_folder (imap4_folder->search, folder); - matches = camel_folder_search_search (imap4_folder->search, expr, NULL, ex); - - CAMEL_SERVICE_UNLOCK(folder->parent_store, connect_lock); - - return matches; -} - -static GPtrArray * -imap4_search_by_uids (CamelFolder *folder, const char *expr, GPtrArray *uids, CamelException *ex) -{ - CamelIMAP4Folder *imap4_folder = (CamelIMAP4Folder *) folder; - GPtrArray *matches; - - if (uids->len == 0) - return g_ptr_array_new (); - - CAMEL_SERVICE_LOCK(folder->parent_store, connect_lock); - - camel_folder_search_set_folder (imap4_folder->search, folder); - matches = camel_folder_search_search (imap4_folder->search, expr, uids, ex); - - CAMEL_SERVICE_UNLOCK(folder->parent_store, connect_lock); - - return matches; -} - -static void -imap4_search_free (CamelFolder *folder, GPtrArray *uids) -{ - CamelIMAP4Folder *imap4_folder = (CamelIMAP4Folder *) folder; - - g_return_if_fail (imap4_folder->search); - - CAMEL_SERVICE_LOCK(folder->parent_store, connect_lock); - - camel_folder_search_free_result (imap4_folder->search, uids); - - CAMEL_SERVICE_UNLOCK(folder->parent_store, connect_lock); -} diff --git a/camel/providers/imap4/camel-imap4-folder.h b/camel/providers/imap4/camel-imap4-folder.h deleted file mode 100644 index ae0263f31d..0000000000 --- a/camel/providers/imap4/camel-imap4-folder.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifndef __CAMEL_IMAP4_FOLDER_H__ -#define __CAMEL_IMAP4_FOLDER_H__ - -#include <camel/camel-store.h> -#include <camel/camel-folder.h> -#include <camel/camel-data-cache.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define CAMEL_TYPE_IMAP4_FOLDER (camel_imap4_folder_get_type ()) -#define CAMEL_IMAP4_FOLDER(obj) (CAMEL_CHECK_CAST ((obj), CAMEL_TYPE_IMAP4_FOLDER, CamelIMAP4Folder)) -#define CAMEL_IMAP4_FOLDER_CLASS(klass) (CAMEL_CHECK_CLASS_CAST ((klass), CAMEL_TYPE_IMAP4_FOLDER, CamelIMAP4FolderClass)) -#define CAMEL_IS_IMAP4_FOLDER(obj) (CAMEL_CHECK_TYPE ((obj), CAMEL_TYPE_IMAP4_FOLDER)) -#define CAMEL_IS_IMAP4_FOLDER_CLASS(klass) (CAMEL_CHECK_CLASS_TYPE ((klass), CAMEL_TYPE_IMAP4_FOLDER)) -#define CAMEL_IMAP4_FOLDER_GET_CLASS(obj) (CAMEL_CHECK_GET_CLASS ((obj), CAMEL_TYPE_IMAP4_FOLDER, CamelIMAP4FolderClass)) - -typedef struct _CamelIMAP4Folder CamelIMAP4Folder; -typedef struct _CamelIMAP4FolderClass CamelIMAP4FolderClass; - -enum { - CAMEL_IMAP4_FOLDER_ARG_SYNC_OFFLINE = CAMEL_FOLDER_ARG_LAST, - CAMEL_IMAP4_FOLDER_ARG_LAST = CAMEL_FOLDER_ARG_LAST + 0x100 -}; - - -enum { - CAMEL_IMAP4_FOLDER_SYNC_OFFLINE = CAMEL_IMAP4_FOLDER_ARG_SYNC_OFFLINE | CAMEL_ARG_BOO, -}; - -struct _CamelIMAP4Folder { - CamelFolder parent_object; - - unsigned int sync_offline:1; - - CamelFolderSearch *search; - CamelDataCache *cache; - - char *cachedir; - char *utf7_name; -}; - -struct _CamelIMAP4FolderClass { - CamelFolderClass parent_class; - -}; - - -CamelType camel_imap4_folder_get_type (void); - -CamelFolder *camel_imap4_folder_new (CamelStore *store, const char *full_name, CamelException *ex); - -const char *camel_imap4_folder_utf7_name (CamelIMAP4Folder *folder); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_IMAP4_FOLDER_H__ */ diff --git a/camel/providers/imap4/camel-imap4-provider.c b/camel/providers/imap4/camel-imap4-provider.c deleted file mode 100644 index fa529e0c2a..0000000000 --- a/camel/providers/imap4/camel-imap4-provider.c +++ /dev/null @@ -1,151 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> - -#include <camel/camel-sasl.h> -#include <camel/camel-provider.h> -#include <camel/camel-i18n.h> - -#include "camel-imap4-store.h" - - -CamelProviderConfEntry imap4_conf_entries[] = { - { CAMEL_PROVIDER_CONF_SECTION_START, "mailcheck", NULL, - N_("Checking for new mail") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "check_all", NULL, - N_("Check for new messages in all folders"), "1" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_SECTION_START, "folders", NULL, - N_("Folders") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "use_lsub", NULL, - N_("Show only subscribed folders"), "1" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "override_namespace", NULL, - N_("Override server-supplied folder namespace"), "0" }, - { CAMEL_PROVIDER_CONF_ENTRY, "namespace", "override_namespace", - N_("Namespace") }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_SECTION_START, "general", NULL, N_("Options") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter", NULL, - N_("Apply filters to new messages in INBOX on this server"), "0" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter_junk", NULL, - N_("Check new messages for Junk contents"), "0" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter_junk_inbox", "filter_junk", - N_("Only check for Junk messages in the INBOX folder"), "0" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "sync_offline", NULL, - N_("Automatically synchronize remote mail locally"), "0" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider imap4_provider = { - "imap4", - N_("IMAPv4rev1"), - - N_("For reading and storing mail on IMAPv4rev1 servers. EXPERIMENTAL !!"), - - "mail", - - CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE | - CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_SUPPORTS_SSL, - - CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH | CAMEL_URL_FRAGMENT_IS_PATH, - - imap4_conf_entries, - - /* ... */ -}; - -CamelServiceAuthType camel_imap4_password_authtype = { - N_("Password"), - - N_("This option will connect to the IMAPv4rev1 server using a " - "plaintext password."), - - "", - TRUE -}; - - -static void -add_hash (guint *hash, char *s) -{ - if (s) - *hash ^= g_str_hash(s); -} - -static guint -imap4_url_hash (gconstpointer key) -{ - const CamelURL *u = (CamelURL *)key; - guint hash = 0; - - add_hash (&hash, u->user); - add_hash (&hash, u->authmech); - add_hash (&hash, u->host); - hash ^= u->port; - - return hash; -} - -static int -check_equal (char *s1, char *s2) -{ - if (s1 == NULL) { - if (s2 == NULL) - return TRUE; - else - return FALSE; - } - - if (s2 == NULL) - return FALSE; - - return strcmp (s1, s2) == 0; -} - -static int -imap4_url_equal (gconstpointer a, gconstpointer b) -{ - const CamelURL *u1 = a, *u2 = b; - - return check_equal (u1->protocol, u2->protocol) - && check_equal (u1->user, u2->user) - && check_equal (u1->authmech, u2->authmech) - && check_equal (u1->host, u2->host) - && u1->port == u2->port; -} - - -void -camel_provider_module_init (void) -{ - imap4_provider.object_types[CAMEL_PROVIDER_STORE] = camel_imap4_store_get_type (); - imap4_provider.url_hash = imap4_url_hash; - imap4_provider.url_equal = imap4_url_equal; - imap4_provider.authtypes = camel_sasl_authtype_list (FALSE); - imap4_provider.authtypes = g_list_prepend (imap4_provider.authtypes, &camel_imap4_password_authtype); - - camel_provider_register (&imap4_provider); -} diff --git a/camel/providers/imap4/camel-imap4-search.c b/camel/providers/imap4/camel-imap4-search.c deleted file mode 100644 index 7102e2fa0f..0000000000 --- a/camel/providers/imap4/camel-imap4-search.c +++ /dev/null @@ -1,314 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast <fejj@novell.com> - * Michael Zucchi <notzed@ximian.com> - * - * Copyright 2004 Novell, Inc. (www.novell.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <ctype.h> - -#include "camel-imap4-command.h" -#include "camel-imap4-engine.h" -#include "camel-imap4-stream.h" -#include "camel-imap4-utils.h" - -#include "camel-imap4-search.h" - - -static void camel_imap4_search_class_init (CamelIMAP4SearchClass *klass); -static void camel_imap4_search_init (CamelIMAP4Search *search, CamelIMAP4SearchClass *klass); -static void camel_imap4_search_finalize (CamelObject *object); - -static ESExpResult *imap4_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search); - - -static CamelFolderSearchClass *parent_class = NULL; - - -CamelType -camel_imap4_search_get_type (void) -{ - static CamelType type = 0; - - if (!type) { - type = camel_type_register (camel_folder_search_get_type (), - "CamelIMAP4Search", - sizeof (CamelIMAP4Search), - sizeof (CamelIMAP4SearchClass), - (CamelObjectClassInitFunc) camel_imap4_search_class_init, - NULL, - (CamelObjectInitFunc) camel_imap4_search_init, - (CamelObjectFinalizeFunc) camel_imap4_search_finalize); - } - - return type; -} - -static void -camel_imap4_search_class_init (CamelIMAP4SearchClass *klass) -{ - CamelFolderSearchClass *search_class = (CamelFolderSearchClass *) klass; - - parent_class = (CamelFolderSearchClass *) camel_type_get_global_classfuncs (CAMEL_FOLDER_SEARCH_TYPE); - - search_class->body_contains = imap4_body_contains; -} - -static void -camel_imap4_search_init (CamelIMAP4Search *search, CamelIMAP4SearchClass *klass) -{ - search->engine = NULL; -} - -static void -camel_imap4_search_finalize (CamelObject *object) -{ - ; -} - - -CamelFolderSearch * -camel_imap4_search_new (CamelIMAP4Engine *engine, const char *cachedir) -{ - CamelIMAP4Search *search; - - search = (CamelIMAP4Search *) camel_object_new (camel_imap4_search_get_type ()); - camel_folder_search_construct ((CamelFolderSearch *) search); - search->engine = engine; - - return (CamelFolderSearch *) search; -} - - -static int -untagged_search (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, guint32 index, camel_imap4_token_t *token, CamelException *ex) -{ - CamelFolderSummary *summary = ((CamelFolder *) engine->folder)->summary; - GPtrArray *matches = ic->user_data; - CamelMessageInfo *info; - char uid[12]; - - while (1) { - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token == '\n') - break; - - if (token->token != CAMEL_IMAP4_TOKEN_NUMBER || token->v.number == 0) - goto unexpected; - - sprintf (uid, "%u", token->v.number); - if ((info = camel_folder_summary_uid (summary, uid))) { - g_ptr_array_add (matches, (char *) camel_message_info_uid (info)); - camel_message_info_free(info); - } - } - - return 0; - - unexpected: - - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - - return -1; -} - -static ESExpResult * -imap4_body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *search) -{ - CamelIMAP4Search *imap4_search = (CamelIMAP4Search *) search; - CamelIMAP4Engine *engine = imap4_search->engine; - GPtrArray *strings, *matches, *infos; - register const unsigned char *inptr; - gboolean utf8_search = FALSE; - GPtrArray *summary_set; - CamelMessageInfo *info; - CamelIMAP4Command *ic; - const char *expr; - ESExpResult *r; - int id, i, n; - size_t used; - char *set; - - summary_set = search->summary_set ? search->summary_set : search->summary; - - /* check the simple cases */ - if (argc == 0 || summary_set->len == 0) { - /* match nothing */ - if (search->current) { - r = e_sexp_result_new (f, ESEXP_RES_BOOL); - r->value.bool = FALSE; - } else { - r = e_sexp_result_new (f, ESEXP_RES_ARRAY_PTR); - r->value.ptrarray = g_ptr_array_new (); - } - - return r; - } else if (argc == 1 && argv[0]->type == ESEXP_RES_STRING && argv[0]->value.string[0] == '\0') { - /* match everything */ - if (search->current) { - r = e_sexp_result_new (f, ESEXP_RES_BOOL); - r->value.bool = TRUE; - } else { - r = e_sexp_result_new (f, ESEXP_RES_ARRAY_PTR); - r->value.ptrarray = g_ptr_array_new (); - g_ptr_array_set_size (r->value.ptrarray, summary_set->len); - r->value.ptrarray->len = summary_set->len; - for (i = 0; i < summary_set->len; i++) { - info = g_ptr_array_index (summary_set, i); - r->value.ptrarray->pdata[i] = (char *) camel_message_info_uid (info); - } - } - - return r; - } - - strings = g_ptr_array_new (); - for (i = 0; i < argc; i++) { - if (argv[i]->type == ESEXP_RES_STRING && argv[i]->value.string[0] != '\0') { - g_ptr_array_add (strings, argv[i]->value.string); - if (!utf8_search) { - inptr = (unsigned char *) argv[i]->value.string; - while (*inptr != '\0') { - if (!isascii ((int) *inptr)) { - utf8_search = TRUE; - break; - } - - inptr++; - } - } - } - } - - if (strings->len == 0) { - /* match everything */ - g_ptr_array_free (strings, TRUE); - - if (search->current) { - r = e_sexp_result_new (f, ESEXP_RES_BOOL); - r->value.bool = TRUE; - } else { - r = e_sexp_result_new (f, ESEXP_RES_ARRAY_PTR); - r->value.ptrarray = g_ptr_array_new (); - g_ptr_array_set_size (r->value.ptrarray, summary_set->len); - r->value.ptrarray->len = summary_set->len; - for (i = 0; i < summary_set->len; i++) { - info = g_ptr_array_index (summary_set, i); - r->value.ptrarray->pdata[i] = (char *) camel_message_info_uid (info); - } - } - - return r; - } - - g_ptr_array_add (strings, NULL); - matches = g_ptr_array_new (); - infos = g_ptr_array_new (); - - if (search->current) { - g_ptr_array_add (infos, search->current); - } else { - g_ptr_array_set_size (infos, summary_set->len); - infos->len = summary_set->len; - for (i = 0; i < summary_set->len; i++) - infos->pdata[i] = summary_set->pdata[i]; - } - - retry: - if (utf8_search && (engine->capa & CAMEL_IMAP4_CAPABILITY_utf8_search)) - expr = "UID SEARCH CHARSET UTF-8 UID %s BODY %V\r\n"; - else - expr = "UID SEARCH UID %s BODY %V\r\n"; - - used = strlen (expr) + (5 * (strings->len - 2)); - - for (i = 0; i < infos->len; i += n) { - n = camel_imap4_get_uid_set (engine, search->folder->summary, infos, i, used, &set); - - ic = camel_imap4_engine_queue (engine, search->folder, expr, set, strings->pdata); - camel_imap4_command_register_untagged (ic, "SEARCH", untagged_search); - ic->user_data = matches; - g_free (set); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_imap4_command_unref (ic); - goto done; - } - - - if (ic->result == CAMEL_IMAP4_RESULT_NO && utf8_search && (engine->capa & CAMEL_IMAP4_CAPABILITY_utf8_search)) { - int j; - - /* might be because the server is lame and doesn't support UTF-8 */ - for (j = 0; j < ic->resp_codes->len; j++) { - CamelIMAP4RespCode *resp = ic->resp_codes->pdata[j]; - - if (resp->code == CAMEL_IMAP4_RESP_CODE_BADCHARSET) { - engine->capa &= ~CAMEL_IMAP4_CAPABILITY_utf8_search; - camel_imap4_command_unref (ic); - goto retry; - } - } - } - - if (ic->result != CAMEL_IMAP4_RESULT_OK) { - camel_imap4_command_unref (ic); - break; - } - - camel_imap4_command_unref (ic); - } - - done: - - g_ptr_array_free (strings, TRUE); - g_ptr_array_free (infos, TRUE); - - if (search->current) { - const char *uid; - - uid = camel_message_info_uid (search->current); - r = e_sexp_result_new (f, ESEXP_RES_BOOL); - r->value.bool = FALSE; - for (i = 0; i < matches->len; i++) { - if (!strcmp (matches->pdata[i], uid)) { - r->value.bool = TRUE; - break; - } - } - - g_ptr_array_free (matches, TRUE); - } else { - r = e_sexp_result_new (f, ESEXP_RES_ARRAY_PTR); - r->value.ptrarray = matches; - } - - return r; -} diff --git a/camel/providers/imap4/camel-imap4-search.h b/camel/providers/imap4/camel-imap4-search.h deleted file mode 100644 index 5165367cfb..0000000000 --- a/camel/providers/imap4/camel-imap4-search.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast <fejj@novell.com> - * - * Copyright 2004 Novell, Inc. (www.novell.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef __CAMEL_IMAP4_SEARCH_H__ -#define __CAMEL_IMAP4_SEARCH_H__ - -#include <camel/camel-folder-search.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define CAMEL_IMAP4_SEARCH_TYPE (camel_imap4_search_get_type ()) -#define CAMEL_IMAP4_SEARCH(obj) CAMEL_CHECK_CAST (obj, camel_imap4_search_get_type (), CamelIMAP4Search) -#define CAMEL_IMAP4_SEARCH_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imap4_search_get_type (), CamelIMAP4SearchClass) -#define CAMEL_IS_IMAP4_SEARCH(obj) CAMEL_CHECK_TYPE (obj, camel_imap4_search_get_type ()) - -typedef struct _CamelIMAP4Search CamelIMAP4Search; -typedef struct _CamelIMAP4SearchClass CamelIMAP4SearchClass; - -struct _CamelIMAP4Engine; - -struct _CamelIMAP4Search { - CamelFolderSearch parent_object; - - struct _CamelIMAP4Engine *engine; -}; - -struct _CamelIMAP4SearchClass { - CamelFolderSearchClass parent_class; - -}; - - -CamelType camel_imap4_search_get_type (void); - -CamelFolderSearch *camel_imap4_search_new (struct _CamelIMAP4Engine *engine, const char *cachedir); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_IMAP4_SEARCH_H__ */ diff --git a/camel/providers/imap4/camel-imap4-specials.c b/camel/providers/imap4/camel-imap4-specials.c deleted file mode 100644 index 4682a403e4..0000000000 --- a/camel/providers/imap4/camel-imap4-specials.c +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> - -#include "camel-imap4-specials.h" - -#define CHARS_ATOM_SPECIALS "(){]" -#define CHARS_LWSP " \t\r\n" -#define CHARS_QUOTED_SPECIALS "\\\"" -#define CHARS_LIST_WILDCARDS "*%" - -unsigned char camel_imap4_specials[256] = { - 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 2, 2, 6, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 20, 0, 8, 0, 0, 32, 0, 0, 1, 1, 32, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -}; - - -static void -imap4_init_bits (unsigned short bit, unsigned short bitcopy, int remove, unsigned char *vals) -{ - int i, len = strlen (vals); - - if (!remove) { - for (i = 0; i < len; i++) - camel_imap4_specials[vals[i]] |= bit; - if (bitcopy) { - for (i = 0; i < 256; i++) { - if (camel_imap4_specials[i] & bitcopy) - camel_imap4_specials[i] |= bit; - } - } - } else { - for (i = 0; i < 256; i++) - camel_imap4_specials[i] |= bit; - for (i = 0; i < len; i++) - camel_imap4_specials[vals[i]] &= ~bit; - if (bitcopy) { - for (i = 0; i < 256; i++) { - if (camel_imap4_specials[i] & bitcopy) - camel_imap4_specials[i] &= ~bit; - } - } - } -} - - -void -camel_imap4_specials_init (void) -{ - int i; - - for (i = 0; i < 256; i++) { - camel_imap4_specials[i] = 0; - if (i <= 0x1f || i >= 0x7f) - camel_imap4_specials[i] |= IS_CTRL; - } - - camel_imap4_specials[' '] |= IS_SPACE; - - imap4_init_bits (IS_LWSP, 0, 0, CHARS_LWSP); - imap4_init_bits (IS_ASPECIAL, 0, 0, CHARS_ATOM_SPECIALS); - imap4_init_bits (IS_QSPECIAL, 0, 0, CHARS_QUOTED_SPECIALS); - imap4_init_bits (IS_WILDCARD, 0, 0, CHARS_LIST_WILDCARDS); -} diff --git a/camel/providers/imap4/camel-imap4-specials.h b/camel/providers/imap4/camel-imap4-specials.h deleted file mode 100644 index 36765cdc6b..0000000000 --- a/camel/providers/imap4/camel-imap4-specials.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifndef __CAMEL_IMAP4_SPECIALS_H__ -#define __CAMEL_IMAP4_SPECIALS_H__ - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -enum { - IS_ASPECIAL = (1 << 0), - IS_CTRL = (1 << 1), - IS_LWSP = (1 << 2), - IS_QSPECIAL = (1 << 3), - IS_SPACE = (1 << 4), - IS_WILDCARD = (1 << 5), -}; - -extern unsigned char camel_imap4_specials[256]; - -#define is_atom(x) ((camel_imap4_specials[(unsigned char)(x)] & (IS_ASPECIAL|IS_SPACE|IS_CTRL|IS_WILDCARD|IS_QSPECIAL)) == 0) -#define is_ctrl(x) ((camel_imap4_specials[(unsigned char)(x)] & IS_CTRL) != 0) -#define is_lwsp(x) ((camel_imap4_specials[(unsigned char)(x)] & IS_LWSP) != 0) -#define is_type(x, t) ((camel_imap4_specials[(unsigned char)(x)] & (t)) != 0) -#define is_qsafe(x) ((camel_imap4_specials[(unsigned char)(x)] & (IS_QSPECIAL|IS_CTRL)) == 0) -#define is_wild(x) ((camel_imap4_specials[(unsigned char)(x)] & IS_WILDCARD) != 0) - -void camel_imap4_specials_init (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_IMAP4_SPECIALS_H__ */ diff --git a/camel/providers/imap4/camel-imap4-store-summary.c b/camel/providers/imap4/camel-imap4-store-summary.c deleted file mode 100644 index ffa4bd05f1..0000000000 --- a/camel/providers/imap4/camel-imap4-store-summary.c +++ /dev/null @@ -1,402 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast <fejj@novell.com> - * - * Copyright 2004 Novell, Inc. (www.novell.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -#include <camel/camel-store.h> -#include <camel/camel-file-utils.h> - -#include "camel-imap4-utils.h" -#include "camel-imap4-store-summary.h" - - -#define CAMEL_IMAP4_STORE_SUMMARY_VERSION_0 (0) -#define CAMEL_IMAP4_STORE_SUMMARY_VERSION (0) - -static void camel_imap4_store_summary_class_init (CamelIMAP4StoreSummaryClass *klass); -static void camel_imap4_store_summary_init (CamelIMAP4StoreSummary *obj); -static void camel_imap4_store_summary_finalize (CamelObject *obj); - -static int summary_header_load (CamelStoreSummary *s, FILE *in); -static int summary_header_save (CamelStoreSummary *s, FILE *out); - -static CamelStoreInfo *store_info_load (CamelStoreSummary *s, FILE *in); -static int store_info_save (CamelStoreSummary *s, FILE *out, CamelStoreInfo *info); -static void store_info_free (CamelStoreSummary *s, CamelStoreInfo *info); - - -static CamelStoreSummaryClass *parent_class = NULL; - - -CamelType -camel_imap4_store_summary_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_store_summary_get_type (), - "CamelIMAP4StoreSummary", - sizeof (CamelIMAP4StoreSummary), - sizeof (CamelIMAP4StoreSummaryClass), - (CamelObjectClassInitFunc) camel_imap4_store_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_imap4_store_summary_init, - (CamelObjectFinalizeFunc) camel_imap4_store_summary_finalize); - } - - return type; -} - - -static void -camel_imap4_store_summary_class_init (CamelIMAP4StoreSummaryClass *klass) -{ - CamelStoreSummaryClass *ssklass = (CamelStoreSummaryClass *) klass; - - parent_class = (CamelStoreSummaryClass *) camel_store_summary_get_type (); - - ssklass->summary_header_load = summary_header_load; - ssklass->summary_header_save = summary_header_save; - - ssklass->store_info_load = store_info_load; - ssklass->store_info_save = store_info_save; - ssklass->store_info_free = store_info_free; -} - -static void -camel_imap4_store_summary_init (CamelIMAP4StoreSummary *s) -{ - ((CamelStoreSummary *) s)->store_info_size = sizeof (CamelIMAP4StoreInfo); - s->version = CAMEL_IMAP4_STORE_SUMMARY_VERSION; - s->namespaces = NULL; -} - -static void -camel_imap4_store_summary_finalize (CamelObject *obj) -{ - CamelIMAP4StoreSummary *s = (CamelIMAP4StoreSummary *) obj; - - if (s->namespaces) - camel_imap4_namespace_list_free (s->namespaces); -} - - -static CamelIMAP4NamespaceList * -load_namespaces (FILE *in) -{ - CamelIMAP4Namespace *ns, *tail; - CamelIMAP4NamespaceList *nsl; - guint32 i, j, n; - - nsl = g_malloc (sizeof (CamelIMAP4NamespaceList)); - nsl->personal = NULL; - nsl->shared = NULL; - nsl->other = NULL; - - for (j = 0; j < 3; j++) { - switch (j) { - case 0: - tail = (CamelIMAP4Namespace *) &nsl->personal; - break; - case 1: - tail = (CamelIMAP4Namespace *) &nsl->shared; - break; - case 2: - tail = (CamelIMAP4Namespace *) &nsl->other; - break; - } - - if (camel_file_util_decode_fixed_int32 (in, &n) == -1) - goto exception; - - for (i = 0; i < n; i++) { - guint32 sep; - char *path; - - if (camel_file_util_decode_string (in, &path) == -1) - goto exception; - - if (camel_file_util_decode_uint32 (in, &sep) == -1) { - g_free (path); - goto exception; - } - - tail->next = ns = g_malloc (sizeof (CamelIMAP4Namespace)); - ns->sep = sep & 0xff; - ns->path = path; - ns->next = NULL; - tail = ns; - } - } - - return nsl; - - exception: - - camel_imap4_namespace_list_free (nsl); - - return NULL; -} - -static int -summary_header_load (CamelStoreSummary *s, FILE *in) -{ - CamelIMAP4StoreSummary *is = (CamelIMAP4StoreSummary *) s; - guint32 version, capa; - - if (parent_class->summary_header_load (s, in) == -1) - return -1; - - if (camel_file_util_decode_fixed_int32 (in, &version) == -1) - return -1; - - is->version = version; - if (version < CAMEL_IMAP4_STORE_SUMMARY_VERSION_0) { - g_warning ("IMAP4 store summary header version too low"); - errno = EINVAL; - return -1; - } - - if (camel_file_util_decode_fixed_int32 (in, &capa) == -1) - return -1; - - is->capa = capa; - - if (!(is->namespaces = load_namespaces (in))) - return -1; - - return 0; -} - -static int -save_namespaces (FILE *out, CamelIMAP4NamespaceList *nsl) -{ - CamelIMAP4Namespace *cur, *ns; - guint32 i, n; - - for (i = 0; i < 3; i++) { - switch (i) { - case 0: - cur = nsl->personal; - break; - case 1: - cur = nsl->shared; - break; - case 2: - cur = nsl->other; - break; - } - - for (ns = cur, n = 0; ns; n++) - ns = ns->next; - - if (camel_file_util_encode_fixed_int32 (out, n) == -1) - return -1; - - ns = cur; - while (ns != NULL) { - if (camel_file_util_encode_string (out, ns->path) == -1) - return -1; - - if (camel_file_util_encode_uint32 (out, ns->sep) == -1) - return -1; - - ns = ns->next; - } - } - - return 0; -} - -static int -summary_header_save (CamelStoreSummary *s, FILE *out) -{ - CamelIMAP4StoreSummary *is = (CamelIMAP4StoreSummary *) s; - - if (parent_class->summary_header_save (s, out) == -1) - return -1; - - if (camel_file_util_encode_fixed_int32 (out, is->version) == -1) - return -1; - - if (camel_file_util_encode_fixed_int32 (out, is->capa) == -1) - return -1; - - if (save_namespaces (out, is->namespaces) == -1) - return -1; - - return 0; -} - -static CamelStoreInfo * -store_info_load (CamelStoreSummary *s, FILE *in) -{ - return parent_class->store_info_load (s, in); -} - -static int -store_info_save (CamelStoreSummary *s, FILE *out, CamelStoreInfo *info) -{ - return parent_class->store_info_save (s, out, info); -} - -static void -store_info_free (CamelStoreSummary *s, CamelStoreInfo *info) -{ - parent_class->store_info_free (s, info); -} - - -/** - * camel_imap4_store_summary_new: - * - * Create a new CamelIMAP4StoreSummary object. - * - * Returns a new CamelIMAP4StoreSummary object. - **/ -CamelIMAP4StoreSummary * -camel_imap4_store_summary_new (void) -{ - return (CamelIMAP4StoreSummary *) camel_object_new (camel_imap4_store_summary_get_type ()); -} - - -void -camel_imap4_store_summary_set_capabilities (CamelIMAP4StoreSummary *s, guint32 capa) -{ - s->capa = capa; -} - - -void -camel_imap4_store_summary_set_namespaces (CamelIMAP4StoreSummary *s, const CamelIMAP4NamespaceList *ns) -{ - if (s->namespaces) - camel_imap4_namespace_list_free (s->namespaces); - s->namespaces = camel_imap4_namespace_list_copy (ns); -} - - -void -camel_imap4_store_summary_note_info (CamelIMAP4StoreSummary *s, CamelFolderInfo *fi) -{ - CamelStoreSummary *ss = (CamelStoreSummary *) s; - CamelStoreInfo *si; - - if ((si = camel_store_summary_path (ss, fi->full_name))) { - if (fi->unread != -1) { - si->unread = fi->unread; - ss->flags |= CAMEL_STORE_SUMMARY_DIRTY; - } - - if (fi->total != -1) { - si->total = fi->total; - ss->flags |= CAMEL_STORE_SUMMARY_DIRTY; - } - - camel_store_summary_info_free (ss, si); - return; - } - - si = camel_store_summary_info_new (ss); - si->path = g_strdup (fi->full_name); - si->uri = g_strdup (fi->uri); - si->flags = fi->flags; - si->unread = fi->unread; - si->total = fi->total; - - camel_store_summary_add (ss, si); - - /* FIXME: should this be recursive? */ -} - - -void -camel_imap4_store_summary_unnote_info (CamelIMAP4StoreSummary *s, CamelFolderInfo *fi) -{ - CamelStoreSummary *ss = (CamelStoreSummary *) s; - - camel_store_summary_remove_path (ss, fi->full_name); -} - - -static CamelFolderInfo * -store_info_to_folder_info (CamelStoreSummary *s, CamelStoreInfo *si) -{ - CamelFolderInfo *fi; - - fi = g_malloc0 (sizeof (CamelFolderInfo)); - fi->full_name = g_strdup (camel_store_info_path (s, si)); - fi->name = g_strdup (camel_store_info_name (s, si)); - fi->uri = g_strdup (camel_store_info_uri (s, si)); - fi->flags = si->flags; - fi->unread = si->unread; - fi->total = si->total; - - return fi; -} - -CamelFolderInfo * -camel_imap4_store_summary_get_folder_info (CamelIMAP4StoreSummary *s, const char *top, guint32 flags) -{ - CamelStoreSummary *ss = (CamelStoreSummary *) s; - CamelFolderInfo *fi; - GPtrArray *folders; - CamelStoreInfo *si; - size_t toplen, len; - int i; - - toplen = strlen (top); - folders = g_ptr_array_new (); - - for (i = 0; i < ss->folders->len; i++) { - si = ss->folders->pdata[i]; - if (strncmp (si->path, top, toplen) != 0) - continue; - - if (toplen > 0 && (len = strlen (si->path)) > toplen && si->path[toplen] != '/') - continue; - - if (len == toplen) { - /* found toplevel folder */ - g_ptr_array_add (folders, store_info_to_folder_info (ss, si)); - continue; - } - - if ((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) || !strchr (si->path + toplen + 1, '/')) - g_ptr_array_add (folders, store_info_to_folder_info (ss, si)); - } - - fi = camel_folder_info_build (folders, top, '/', TRUE); - g_ptr_array_free (folders, TRUE); - - return fi; -} diff --git a/camel/providers/imap4/camel-imap4-store-summary.h b/camel/providers/imap4/camel-imap4-store-summary.h deleted file mode 100644 index 4a5af80d03..0000000000 --- a/camel/providers/imap4/camel-imap4-store-summary.h +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Jeffrey Stedfast <fejj@novell.com> - * - * Copyright 2004 Novell, Inc. (www.novell.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef __CAMEL_IMAP_STORE_SUMMARY_H__ -#define __CAMEL_IMAP_STORE_SUMMARY_H__ - -#include <camel/camel-store-summary.h> -#include "camel-imap4-engine.h" - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define CAMEL_IMAP4_STORE_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_imap4_store_summary_get_type (), CamelIMAP4StoreSummary) -#define CAMEL_IMAP4_STORE_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imap4_store_summary_get_type (), CamelIMAP4StoreSummaryClass) -#define CAMEL_IS_IMAP4_STORE_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_imap4_store_summary_get_type ()) - -typedef struct _CamelIMAP4StoreSummary CamelIMAP4StoreSummary; -typedef struct _CamelIMAP4StoreSummaryClass CamelIMAP4StoreSummaryClass; - -typedef struct _CamelIMAP4StoreInfo CamelIMAP4StoreInfo; - -enum { - CAMEL_IMAP4_STORE_INFO_FULL_NAME = CAMEL_STORE_INFO_LAST, - CAMEL_IMAP4_STORE_INFO_LAST, -}; - - -struct _CamelFolderInfo; - - -struct _CamelIMAP4StoreInfo { - CamelStoreInfo info; -}; - -struct _CamelIMAP4StoreSummary { - CamelStoreSummary summary; - - struct _CamelIMAP4StoreSummaryPrivate *priv; - - /* header info */ - guint32 version; - - CamelIMAP4NamespaceList *namespaces; - guint32 capa; -}; - -struct _CamelIMAP4StoreSummaryClass { - CamelStoreSummaryClass summary_class; -}; - - -CamelType camel_imap4_store_summary_get_type (void); - -CamelIMAP4StoreSummary *camel_imap4_store_summary_new (void); - -void camel_imap4_store_summary_set_capabilities (CamelIMAP4StoreSummary *s, guint32 capa); -void camel_imap4_store_summary_set_namespaces (CamelIMAP4StoreSummary *s, const CamelIMAP4NamespaceList *ns); - -/* add the info to the cache if we don't already have it, otherwise do nothing */ -void camel_imap4_store_summary_note_info (CamelIMAP4StoreSummary *s, struct _CamelFolderInfo *fi); - -void camel_imap4_store_summary_unnote_info (CamelIMAP4StoreSummary *s, struct _CamelFolderInfo *fi); - -struct _CamelFolderInfo *camel_imap4_store_summary_get_folder_info (CamelIMAP4StoreSummary *s, const char *top, guint32 flags); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_IMAP4_STORE_SUMMARY_H__ */ diff --git a/camel/providers/imap4/camel-imap4-store.c b/camel/providers/imap4/camel-imap4-store.c deleted file mode 100644 index 2e7308d75d..0000000000 --- a/camel/providers/imap4/camel-imap4-store.c +++ /dev/null @@ -1,1448 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> - -#include <camel/camel-sasl.h> -#include <camel/camel-utf8.h> -#include <camel/camel-tcp-stream-raw.h> -#include <camel/camel-tcp-stream-ssl.h> - -#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" -#include "camel-imap4-stream.h" -#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); -static void camel_imap4_store_finalize (CamelObject *object); - -/* service methods */ -static void imap4_construct (CamelService *service, CamelSession *session, - CamelProvider *provider, CamelURL *url, - CamelException *ex); -static char *imap4_get_name (CamelService *service, gboolean brief); -static gboolean imap4_connect (CamelService *service, CamelException *ex); -static gboolean imap4_reconnect (CamelIMAP4Engine *engine, CamelException *ex); -static gboolean imap4_disconnect (CamelService *service, gboolean clean, CamelException *ex); -static GList *imap4_query_auth_types (CamelService *service, CamelException *ex); - -/* store methods */ -static CamelFolder *imap4_get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex); -static CamelFolderInfo *imap4_create_folder (CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex); -static void imap4_delete_folder (CamelStore *store, const char *folder_name, CamelException *ex); -static void imap4_rename_folder (CamelStore *store, const char *old_name, const char *new_name, CamelException *ex); -static CamelFolderInfo *imap4_get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex); -static void imap4_subscribe_folder (CamelStore *store, const char *folder_name, CamelException *ex); -static void imap4_unsubscribe_folder (CamelStore *store, const char *folder_name, CamelException *ex); -static void imap4_noop (CamelStore *store, CamelException *ex); - - -static CamelStoreClass *parent_class = NULL; - - -CamelType -camel_imap4_store_get_type (void) -{ - static CamelType type = 0; - - if (!type) { - type = camel_type_register (CAMEL_STORE_TYPE, - "CamelIMAP4Store", - sizeof (CamelIMAP4Store), - sizeof (CamelIMAP4StoreClass), - (CamelObjectClassInitFunc) camel_imap4_store_class_init, - NULL, - (CamelObjectInitFunc) camel_imap4_store_init, - (CamelObjectFinalizeFunc) camel_imap4_store_finalize); - } - - return type; -} - -static guint -imap4_hash_folder_name (gconstpointer key) -{ - if (g_ascii_strcasecmp (key, "INBOX") == 0) - return g_str_hash ("INBOX"); - else - return g_str_hash (key); -} - -static int -imap4_compare_folder_name (gconstpointer a, gconstpointer b) -{ - gconstpointer aname = a, bname = b; - - if (g_ascii_strcasecmp (a, "INBOX") == 0) - aname = "INBOX"; - if (g_ascii_strcasecmp (b, "INBOX") == 0) - bname = "INBOX"; - - return g_str_equal (aname, bname); -} - -static void -camel_imap4_store_class_init (CamelIMAP4StoreClass *klass) -{ - CamelServiceClass *service_class = (CamelServiceClass *) klass; - CamelStoreClass *store_class = (CamelStoreClass *) klass; - - parent_class = (CamelStoreClass *) camel_type_get_global_classfuncs (CAMEL_STORE_TYPE); - - service_class->construct = imap4_construct; - service_class->get_name = imap4_get_name; - service_class->connect = imap4_connect; - service_class->disconnect = imap4_disconnect; - service_class->query_auth_types = imap4_query_auth_types; - - store_class->hash_folder_name = imap4_hash_folder_name; - store_class->compare_folder_name = imap4_compare_folder_name; - - store_class->get_folder = imap4_get_folder; - store_class->create_folder = imap4_create_folder; - store_class->delete_folder = imap4_delete_folder; - store_class->rename_folder = imap4_rename_folder; - store_class->get_folder_info = imap4_get_folder_info; - store_class->subscribe_folder = imap4_subscribe_folder; - store_class->unsubscribe_folder = imap4_unsubscribe_folder; - store_class->noop = imap4_noop; -} - -static void -camel_imap4_store_init (CamelIMAP4Store *store, CamelIMAP4StoreClass *klass) -{ - store->engine = NULL; - store->summary = NULL; -} - -static void -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); - - g_free (store->storage_path); -} - - -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)) - return; - - 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 * -imap4_get_name (CamelService *service, gboolean brief) -{ - if (brief) - return g_strdup_printf (_("IMAP server %s"), service->url->host); - else - return g_strdup_printf (_("IMAP service for %s on %s"), - service->url->user, service->url->host); -} - -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 (CamelIMAP4Engine *engine, struct addrinfo *ai, int ssl_mode, CamelException *ex) -{ - CamelService *service = engine->service; - CamelStream *tcp_stream; - CamelIMAP4Command *ic; - int id, ret; - - 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); - } else { - 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")); - - return FALSE; -#endif /* HAVE_SSL */ - } else { - tcp_stream = camel_tcp_stream_raw_new (); - } - - 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)); - - camel_object_unref (tcp_stream); - - return FALSE; - } - - if (camel_imap4_engine_take_stream (engine, tcp_stream, ex) == -1) - return FALSE; - - 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; - } - - if (!(engine->capa & CAMEL_IMAP4_CAPABILITY_STARTTLS)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to IMAP server %s in secure mode: %s"), - service->url->host, _("SSL negotiations failed")); - - return FALSE; - } - - ic = camel_imap4_engine_prequeue (engine, NULL, "STARTTLS\r\n"); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->result != CAMEL_IMAP4_RESULT_OK) { - if (ic->result != CAMEL_IMAP4_RESULT_OK) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to IMAP server %s in secure mode: %s"), - service->url->host, _("Unknown error")); - } else { - camel_exception_xfer (ex, &ic->ex); - } - - camel_imap4_command_unref (ic); - - return FALSE; - } - - camel_imap4_command_unref (ic); - - return TRUE; -} - -static struct { - char *value; - char *serv; - char *port; - int mode; -} ssl_options[] = { - { "", "imaps", "993", MODE_SSL }, /* really old (1.x) */ - { "always", "imaps", "993", MODE_SSL }, - { "when-possible", "imap", "143", MODE_TLS }, - { "never", "imap", "143", MODE_CLEAR }, - { NULL, "imap", "143", MODE_CLEAR }, -}; - -static gboolean -connect_to_server_wrapper (CamelIMAP4Engine *engine, CamelException *ex) -{ - CamelService *service = engine->service; - struct addrinfo *ai, hints; - const char *ssl_mode; - int mode, ret, i; - const char *port; - char *serv; - - 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 = "imap"; - port = "143"; - } - - 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 (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); - } - - camel_freeaddrinfo (ai); - - return ret; -} - -static int -sasl_auth (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, const unsigned char *linebuf, size_t linelen, CamelException *ex) -{ - /* Perform a single challenge iteration */ - CamelSasl *sasl = ic->user_data; - char *challenge; - - if (camel_sasl_authenticated (sasl)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Cannot authenticate to IMAP server %s using the %s authentication mechanism"), - engine->url->host, engine->url->authmech); - return -1; - } - - while (isspace (*linebuf)) - linebuf++; - - if (*linebuf == '\0') - linebuf = NULL; - - if (!(challenge = camel_sasl_challenge_base64 (sasl, (const char *) linebuf, ex))) - return -1; - - d(fprintf (stderr, "sending : %s\r\n", challenge)); - - if (camel_stream_printf (engine->ostream, "%s\r\n", challenge) == -1) { - g_free (challenge); - return -1; - } - - g_free (challenge); - - if (camel_stream_flush (engine->ostream) == -1) - return -1; - - return 0; -} - -static int -imap4_try_authenticate (CamelIMAP4Engine *engine, gboolean reprompt, const char *errmsg, CamelException *ex) -{ - CamelService *service = engine->service; - CamelSession *session = service->session; - CamelSasl *sasl = NULL; - CamelIMAP4Command *ic; - int id; - - if (!service->url->passwd) { - guint32 flags = CAMEL_SESSION_PASSWORD_SECRET; - char *prompt; - - if (reprompt) - flags |= CAMEL_SESSION_PASSWORD_REPROMPT; - - prompt = g_strdup_printf (_("%sPlease enter the IMAP password for %s on host %s"), - errmsg ? errmsg : "", - service->url->user, - service->url->host); - - service->url->passwd = camel_session_get_password (session, service, NULL, prompt, "password", flags, ex); - - g_free (prompt); - - if (!service->url->passwd) - return FALSE; - } - - if (service->url->authmech) { - CamelServiceAuthType *mech; - - mech = g_hash_table_lookup (engine->authtypes, service->url->authmech); - sasl = camel_sasl_new ("imap", mech->authproto, service); - - ic = camel_imap4_engine_prequeue (engine, NULL, "AUTHENTICATE %s\r\n", service->url->authmech); - ic->plus = sasl_auth; - ic->user_data = sasl; - } else { - ic = camel_imap4_engine_prequeue (engine, NULL, "LOGIN %S %S\r\n", - service->url->user, service->url->passwd); - } - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (sasl != NULL) - camel_object_unref (sasl); - - if (id == -1 || ic->status == CAMEL_IMAP4_COMMAND_ERROR) { - /* unrecoverable error */ - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - - return FALSE; - } - - if (ic->result != CAMEL_IMAP4_RESULT_OK) { - camel_imap4_command_unref (ic); - - /* try again */ - - return TRUE; - } - - camel_imap4_command_unref (ic); - - return FALSE; -} - -static gboolean -imap4_reconnect (CamelIMAP4Engine *engine, CamelException *ex) -{ - CamelService *service = engine->service; - CamelServiceAuthType *mech; - gboolean reprompt = FALSE; - char *errmsg = NULL; - CamelException lex; - - if (!connect_to_server_wrapper (engine, ex)) - return FALSE; - -#define CANT_USE_AUTHMECH (!(mech = g_hash_table_lookup (engine->authtypes, service->url->authmech))) - if (service->url->authmech && CANT_USE_AUTHMECH) { - /* Oops. We can't AUTH using the requested mechanism */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Cannot authenticate to IMAP server %s using %s"), - service->url->host, service->url->authmech); - - return FALSE; - } - - camel_exception_init (&lex); - while (imap4_try_authenticate (engine, reprompt, errmsg, &lex)) { - 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); - - if (camel_exception_is_set (&lex)) { - camel_exception_xfer (ex, &lex); - return FALSE; - } - - 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; - CAMEL_SERVICE_UNLOCK (service, connect_lock); - - return retval; -} - -static gboolean -imap4_disconnect (CamelService *service, gboolean clean, CamelException *ex) -{ - CamelIMAP4Store *store = (CamelIMAP4Store *) service; - 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) { - 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; -} - -extern CamelServiceAuthType camel_imap4_password_authtype; - -static GList * -imap4_query_auth_types (CamelService *service, CamelException *ex) -{ - CamelIMAP4Store *store = (CamelIMAP4Store *) service; - CamelServiceAuthType *authtype; - 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); - if (!connected) - return NULL; - - sasl_types = camel_sasl_authtype_list (FALSE); - for (t = sasl_types; t; t = next) { - authtype = t->data; - next = t->next; - - if (!g_hash_table_lookup (store->engine->authtypes, authtype->authproto)) { - sasl_types = g_list_remove_link (sasl_types, t); - g_list_free_1 (t); - } - } - - return g_list_prepend (sasl_types, &camel_imap4_password_authtype); -} - -static char * -imap4_folder_utf7_name (CamelStore *store, const char *folder_name, char wildcard) -{ - char *real_name, *p; - char sep = '\0'; - 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; - } - - real_name = camel_utf8_utf7 (folder_name); - } else - real_name = g_strdup (""); - - if (wildcard) { - len = strlen (real_name); - real_name = g_realloc (real_name, len + 3); - - if (len > 0) - real_name[len++] = sep; - - real_name[len++] = wildcard; - real_name[len] = '\0'; - } - - return real_name; -} - -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; - CamelFolderInfo *fi; - GPtrArray *array; - char *utf7_name; - int create; - int id, i; - - 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); - camel_imap4_command_register_untagged (ic, "LIST", camel_imap4_untagged_list); - ic->user_data = array = g_ptr_array_new (); - g_free (utf7_name); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - g_ptr_array_free (array, TRUE); - goto done; - } - - create = array->len == 0; - - for (i = 0; i < array->len; i++) { - list = array->pdata[i]; - g_free (list->name); - g_free (list); - } - - g_ptr_array_free (array, TRUE); - - if (ic->result != CAMEL_IMAP4_RESULT_OK) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get folder `%s' on IMAP server %s: Unknown"), - folder_name, ((CamelService *) store)->url->host); - camel_imap4_command_unref (ic); - goto done; - } - - camel_imap4_command_unref (ic); - - if (create) { - const char *basename; - char *parent; - int len; - - if (!(flags & CAMEL_STORE_FOLDER_CREATE)) - goto done; - - if (!(basename = strrchr (folder_name, '/'))) - basename = folder_name; - else - basename++; - - len = basename > folder_name ? (basename - folder_name) - 1 : 0; - parent = g_alloca (len + 1); - memcpy (parent, folder_name, len); - parent[len] = '\0'; - - if (!(fi = imap4_create_folder (store, parent, basename, ex))) - goto done; - - camel_store_free_folder_info (store, fi); - } - - folder = camel_imap4_folder_new (store, folder_name, ex); - - done: - - CAMEL_SERVICE_UNLOCK (store, connect_lock); - - return folder; -} - -static CamelFolderInfo * -imap4_create_folder (CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex) -{ - /* FIXME: also need to deal with parent folders that can't - * 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; - CamelURL *url; - const char *c; - char *name; - char sep; - int id; - - sep = camel_imap4_get_path_delim (((CamelIMAP4Store *) store)->summary, parent_name); - - c = folder_name; - while (*c != '\0') { - if (*c == sep || strchr ("/#%*", *c)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_PATH, - _("The folder name \"%s\" is invalid because " - "it contains the character \"%c\""), - folder_name, *c); - return NULL; - } - - 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 - name = g_strdup (folder_name); - - CAMEL_SERVICE_LOCK (store, connect_lock); - - utf7_name = imap4_folder_utf7_name (store, name, '\0'); - ic = camel_imap4_engine_queue (engine, NULL, "CREATE %S\r\n", utf7_name); - g_free (utf7_name); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - g_free (name); - goto done; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - url = camel_url_copy (engine->url); - camel_url_set_fragment (url, name); - - c = strrchr (name, '/'); - - fi = g_malloc0 (sizeof (CamelFolderInfo)); - fi->full_name = name; - fi->name = g_strdup (c ? c + 1: name); - fi->uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - camel_url_free (url); - fi->flags = 0; - 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: - /* FIXME: would be good to save the NO reason into the err message */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create folder `%s': Invalid mailbox name"), - name); - g_free (name); - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create folder `%s': Bad command"), - name); - g_free (name); - break; - default: - g_assert_not_reached (); - } - - camel_imap4_command_unref (ic); - - done: - - CAMEL_SERVICE_UNLOCK (store, connect_lock); - - return fi; -} - -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; - char *utf7_name; - CamelURL *url; - const char *p; - int id; - - if (!g_ascii_strcasecmp (folder_name, "INBOX")) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot delete folder `%s': Special folder"), - folder_name); - - 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)) - ic0 = camel_imap4_engine_queue (engine, NULL, "CLOSE\r\n"); - - utf7_name = imap4_folder_utf7_name (store, folder_name, '\0'); - ic = camel_imap4_engine_queue (engine, NULL, "DELETE %S\r\n", utf7_name); - g_free (utf7_name); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - if (ic0 && ic0->status != CAMEL_IMAP4_COMMAND_COMPLETE) - camel_exception_xfer (ex, &ic0->ex); - else - camel_exception_xfer (ex, &ic->ex); - - if (ic0 != NULL) - camel_imap4_command_unref (ic0); - - camel_imap4_command_unref (ic); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return; - } - - if (ic0 != NULL) - camel_imap4_command_unref (ic0); - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - /* deleted */ - url = camel_url_copy (engine->url); - camel_url_set_fragment (url, folder_name); - - p = strrchr (folder_name, '/'); - - fi = g_malloc0 (sizeof (CamelFolderInfo)); - fi->full_name = g_strdup (folder_name); - fi->name = g_strdup (p ? p + 1: folder_name); - fi->uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - camel_url_free (url); - fi->flags = 0; - 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); - break; - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot delete folder `%s': Invalid mailbox name"), - folder_name); - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot delete folder `%s': Bad command"), - folder_name); - break; - } - - camel_imap4_command_unref (ic); - - CAMEL_SERVICE_UNLOCK (store, connect_lock); -} - -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; - - if (!g_ascii_strcasecmp (old_name, "INBOX")) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot rename folder `%s' to `%s': Special folder"), - old_name, new_name); - - 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'); - new_uname = imap4_folder_utf7_name (store, new_name, '\0'); - - ic = camel_imap4_engine_queue (engine, NULL, "RENAME %S %S\r\n", old_uname, new_uname); - g_free (old_uname); - g_free (new_uname); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return; - } - - 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 */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot rename folder `%s' to `%s': Invalid mailbox name"), - old_name, new_name); - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot rename folder `%s' to `%s': Bad command"), - old_name, new_name); - break; - } - - camel_imap4_command_unref (ic); - - CAMEL_SERVICE_UNLOCK (store, connect_lock); -} - -static int -list_sort (const camel_imap4_list_t **list0, const camel_imap4_list_t **list1) -{ - return strcmp ((*list0)->name, (*list1)->name); -} - -static void -list_remove_duplicates (GPtrArray *array) -{ - camel_imap4_list_t *list, *last; - int i; - - last = array->pdata[0]; - for (i = 1; i < array->len; i++) { - list = array->pdata[i]; - if (!strcmp (list->name, last->name)) { - g_ptr_array_remove_index (array, i--); - last->flags |= list->flags; - g_free (list->name); - g_free (list); - } - } -} - -static void -imap4_status (CamelStore *store, CamelFolderInfo *fi) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - camel_imap4_status_attr_t *attr, *next; - camel_imap4_status_t *status; - CamelIMAP4Command *ic; - GPtrArray *array; - char *mailbox; - int id, i; - - mailbox = imap4_folder_utf7_name (store, fi->full_name, '\0'); - ic = camel_imap4_engine_queue (engine, NULL, "STATUS %S (MESSAGES UNSEEN)\r\n", mailbox); - g_free (mailbox); - - camel_imap4_command_register_untagged (ic, "STATUS", camel_imap4_untagged_status); - ic->user_data = array = g_ptr_array_new (); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_imap4_command_unref (ic); - g_ptr_array_free (array, TRUE); - return; - } - - for (i = 0; i < array->len; i++) { - status = array->pdata[i]; - attr = status->attr_list; - while (attr != NULL) { - next = attr->next; - if (attr->type == CAMEL_IMAP4_STATUS_MESSAGES) - fi->total = attr->value; - else if (attr->type == CAMEL_IMAP4_STATUS_UNSEEN) - fi->unread = attr->value; - g_free (attr); - attr = next; - } - - g_free (status->mailbox); - g_free (status); - } - - camel_imap4_command_unref (ic); - g_ptr_array_free (array, TRUE); -} - -static CamelFolderInfo * -imap4_build_folder_info (CamelStore *store, const char *top, guint32 flags, GPtrArray *array) -{ - CamelIMAP4Engine *engine = ((CamelIMAP4Store *) store)->engine; - CamelFolder *folder = (CamelFolder *) engine->folder; - camel_imap4_list_t *list; - CamelFolderInfo *fi; - char *name, *p; - CamelURL *url; - int i; - - if (array->len == 0) { - g_ptr_array_free (array, TRUE); - return NULL; - } - - g_ptr_array_sort (array, (GCompareFunc) list_sort); - - list_remove_duplicates (array); - - 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)); - - p = name = camel_utf7_utf8 (list->name); - while (*p != '\0') { - if (*p == list->delim) - *p = '/'; - p++; - } - - p = strrchr (name, '/'); - camel_url_set_fragment (url, name); - - fi->full_name = name; - fi->name = g_strdup (p ? p + 1: name); - fi->uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - 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); - } - - 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); - - camel_url_free (url); - - g_ptr_array_free (array, TRUE); - - camel_store_summary_save ((CamelStoreSummary *) ((CamelIMAP4Store *) store)->summary); - - return fi; -} - -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; - GPtrArray *array; - const char *cmd; - char *pattern; - 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; - } - - check_online: - - if (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) - cmd = "LSUB"; - else - cmd = "LIST"; - - wildcard = (flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) ? '*' : '%'; - pattern = imap4_folder_utf7_name (store, top, wildcard); - array = g_ptr_array_new (); - - if (*top != '\0') { - size_t len; - char sep; - - len = strlen (pattern); - sep = pattern[len - 2]; - pattern[len - 2] = '\0'; - - ic0 = camel_imap4_engine_queue (engine, NULL, "%s \"\" %S\r\n", cmd, pattern); - camel_imap4_command_register_untagged (ic0, cmd, camel_imap4_untagged_list); - ic0->user_data = array; - - pattern[len - 2] = sep; - } - - ic = camel_imap4_engine_queue (engine, NULL, "%s \"\" %S\r\n", cmd, pattern); - camel_imap4_command_register_untagged (ic, cmd, camel_imap4_untagged_list); - ic->user_data = array; - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - if (ic0 && ic0->status != CAMEL_IMAP4_COMMAND_COMPLETE) - camel_exception_xfer (ex, &ic0->ex); - else - camel_exception_xfer (ex, &ic->ex); - - if (ic0 != NULL) - camel_imap4_command_unref (ic0); - camel_imap4_command_unref (ic); - - for (i = 0; i < array->len; i++) { - list = array->pdata[i]; - g_free (list->name); - g_free (list); - } - - g_ptr_array_free (array, TRUE); - g_free (pattern); - - goto done; - } - - if (ic0 != NULL) - camel_imap4_command_unref (ic0); - - if (ic->result != CAMEL_IMAP4_RESULT_OK) { - camel_imap4_command_unref (ic); - - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get %s information for pattern `%s' on IMAP server %s: %s"), - cmd, pattern, engine->url->host, ic->result == CAMEL_IMAP4_RESULT_BAD ? - _("Bad command") : _("Unknown")); - - for (i = 0; i < array->len; i++) { - list = array->pdata[i]; - g_free (list->name); - g_free (list); - } - - g_ptr_array_free (array, TRUE); - - g_free (pattern); - - goto done; - } - - g_free (pattern); - - fi = imap4_build_folder_info (store, top, flags, array); - - done: - - CAMEL_SERVICE_UNLOCK (store, connect_lock); - - return fi; -} - -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; - CamelURL *url; - 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'); - ic = camel_imap4_engine_queue (engine, NULL, "SUBSCRIBE %S\r\n", utf7_name); - g_free (utf7_name); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - /* subscribed */ - url = camel_url_copy (engine->url); - camel_url_set_fragment (url, folder_name); - - p = strrchr (folder_name, '/'); - - fi = g_malloc0 (sizeof (CamelFolderInfo)); - fi->full_name = g_strdup (folder_name); - fi->name = g_strdup (p ? p + 1: folder_name); - fi->uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - camel_url_free (url); - fi->flags = CAMEL_FOLDER_NOCHILDREN; - 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; - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot subscribe to folder `%s': Invalid mailbox name"), - folder_name); - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot subscribe to folder `%s': Bad command"), - folder_name); - break; - } - - camel_imap4_command_unref (ic); - - CAMEL_SERVICE_UNLOCK (store, connect_lock); -} - -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; - CamelURL *url; - 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'); - ic = camel_imap4_engine_queue (engine, NULL, "UNSUBSCRIBE %S\r\n", utf7_name); - g_free (utf7_name); - - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return; - } - - switch (ic->result) { - case CAMEL_IMAP4_RESULT_OK: - /* unsubscribed */ - url = camel_url_copy (engine->url); - camel_url_set_fragment (url, folder_name); - - p = strrchr (folder_name, '/'); - - fi = g_malloc0 (sizeof (CamelFolderInfo)); - fi->full_name = g_strdup (folder_name); - fi->name = g_strdup (p ? p + 1: folder_name); - fi->uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - camel_url_free (url); - fi->flags = 0; - 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; - case CAMEL_IMAP4_RESULT_NO: - /* FIXME: would be good to save the NO reason into the err message */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot unsubscribe from folder `%s': Invalid mailbox name"), - folder_name); - break; - case CAMEL_IMAP4_RESULT_BAD: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot unsubscribe from folder `%s': Bad command"), - folder_name); - break; - } - - camel_imap4_command_unref (ic); - - CAMEL_SERVICE_UNLOCK (store, connect_lock); -} - -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) { - camel_folder_sync (folder, FALSE, ex); - if (camel_exception_is_set (ex)) { - CAMEL_SERVICE_UNLOCK (store, connect_lock); - return; - } - } - - ic = camel_imap4_engine_queue (engine, NULL, "NOOP\r\n"); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) - camel_exception_xfer (ex, &ic->ex); - - camel_imap4_command_unref (ic); - - if (folder && !camel_exception_is_set (ex)) - camel_imap4_summary_flush_updates (folder->summary, ex); - - CAMEL_SERVICE_UNLOCK (store, connect_lock); -} diff --git a/camel/providers/imap4/camel-imap4-store.h b/camel/providers/imap4/camel-imap4-store.h deleted file mode 100644 index aef3c6c6a4..0000000000 --- a/camel/providers/imap4/camel-imap4-store.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifndef __CAMEL_IMAP4_STORE_H__ -#define __CAMEL_IMAP4_STORE_H__ - -#include <camel/camel-store.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define CAMEL_TYPE_IMAP4_STORE (camel_imap4_store_get_type ()) -#define CAMEL_IMAP4_STORE(obj) (CAMEL_CHECK_CAST ((obj), CAMEL_TYPE_IMAP4_STORE, CamelIMAP4Store)) -#define CAMEL_IMAP4_STORE_CLASS(klass) (CAMEL_CHECK_CLASS_CAST ((klass), CAMEL_TYPE_IMAP4_STORE, CamelIMAP4StoreClass)) -#define CAMEL_IS_IMAP4_STORE(obj) (CAMEL_CHECK_TYPE ((obj), CAMEL_TYPE_IMAP4_STORE)) -#define CAMEL_IS_IMAP4_STORE_CLASS(klass) (CAMEL_CHECK_CLASS_TYPE ((klass), CAMEL_TYPE_IMAP4_STORE)) -#define CAMEL_IMAP4_STORE_GET_CLASS(obj) (CAMEL_CHECK_GET_CLASS ((obj), CAMEL_TYPE_IMAP4_STORE, CamelIMAP4StoreClass)) - -typedef struct _CamelIMAP4Store CamelIMAP4Store; -typedef struct _CamelIMAP4StoreClass CamelIMAP4StoreClass; - -struct _CamelIMAP4Engine; - -struct _CamelIMAP4Store { - CamelStore parent_object; - - struct _CamelIMAP4StoreSummary *summary; - struct _CamelIMAP4Engine *engine; - char *storage_path; -}; - -struct _CamelIMAP4StoreClass { - CamelStoreClass parent_class; - -}; - - -CamelType camel_imap4_store_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_IMAP4_STORE_H__ */ diff --git a/camel/providers/imap4/camel-imap4-stream.c b/camel/providers/imap4/camel-imap4-stream.c deleted file mode 100644 index 4a48fe5cf2..0000000000 --- a/camel/providers/imap4/camel-imap4-stream.c +++ /dev/null @@ -1,725 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <ctype.h> - -#include "camel-imap4-specials.h" - -#include "camel-imap4-stream.h" - -#define d(x) x - -#define IMAP4_TOKEN_LEN 128 - -static void camel_imap4_stream_class_init (CamelIMAP4StreamClass *klass); -static void camel_imap4_stream_init (CamelIMAP4Stream *stream, CamelIMAP4StreamClass *klass); -static void camel_imap4_stream_finalize (CamelObject *object); - -static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n); -static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n); -static int stream_flush (CamelStream *stream); -static int stream_close (CamelStream *stream); -static gboolean stream_eos (CamelStream *stream); - - -static CamelStreamClass *parent_class = NULL; - - -CamelType -camel_imap4_stream_get_type (void) -{ - static CamelType type = 0; - - if (!type) { - type = camel_type_register (CAMEL_STREAM_TYPE, - "CamelIMAP4Stream", - sizeof (CamelIMAP4Stream), - sizeof (CamelIMAP4StreamClass), - (CamelObjectClassInitFunc) camel_imap4_stream_class_init, - NULL, - (CamelObjectInitFunc) camel_imap4_stream_init, - (CamelObjectFinalizeFunc) camel_imap4_stream_finalize); - } - - return type; -} - -static void -camel_imap4_stream_class_init (CamelIMAP4StreamClass *klass) -{ - CamelStreamClass *stream_class = (CamelStreamClass *) klass; - - parent_class = (CamelStreamClass *) camel_type_get_global_classfuncs (CAMEL_STREAM_TYPE); - - /* virtual method overload */ - stream_class->read = stream_read; - stream_class->write = stream_write; - stream_class->flush = stream_flush; - stream_class->close = stream_close; - stream_class->eos = stream_eos; -} - -static void -camel_imap4_stream_init (CamelIMAP4Stream *imap4, CamelIMAP4StreamClass *klass) -{ - imap4->stream = NULL; - - imap4->mode = CAMEL_IMAP4_STREAM_MODE_TOKEN; - imap4->disconnected = FALSE; - imap4->have_unget = FALSE; - imap4->eol = FALSE; - - imap4->literal = 0; - - imap4->inbuf = imap4->realbuf + IMAP4_READ_PRELEN; - imap4->inptr = imap4->inbuf; - imap4->inend = imap4->inbuf; - - imap4->tokenbuf = g_malloc (IMAP4_TOKEN_LEN); - imap4->tokenptr = imap4->tokenbuf; - imap4->tokenleft = IMAP4_TOKEN_LEN; -} - -static void -camel_imap4_stream_finalize (CamelObject *object) -{ - CamelIMAP4Stream *imap4 = (CamelIMAP4Stream *) object; - - if (imap4->stream) - camel_object_unref (imap4->stream); - - g_free (imap4->tokenbuf); -} - - -static ssize_t -imap4_fill (CamelIMAP4Stream *imap4) -{ - unsigned char *inbuf, *inptr, *inend; - ssize_t nread; - size_t inlen; - - if (imap4->disconnected) { - errno = EINVAL; - return -1; - } - - inbuf = imap4->inbuf; - inptr = imap4->inptr; - inend = imap4->inend; - inlen = inend - inptr; - - g_assert (inptr <= inend); - - /* attempt to align 'inend' with realbuf + SCAN_HEAD */ - if (inptr >= inbuf) { - inbuf -= inlen < IMAP4_READ_PRELEN ? inlen : IMAP4_READ_PRELEN; - memmove (inbuf, inptr, inlen); - inptr = inbuf; - inbuf += inlen; - } else if (inptr > imap4->realbuf) { - size_t shift; - - shift = MIN (inptr - imap4->realbuf, inend - inbuf); - memmove (inptr - shift, inptr, inlen); - inptr -= shift; - inbuf = inptr + inlen; - } else { - /* we can't shift... */ - inbuf = inend; - } - - imap4->inptr = inptr; - imap4->inend = inbuf; - inend = imap4->realbuf + IMAP4_READ_PRELEN + IMAP4_READ_BUFLEN - 1; - - if ((nread = camel_stream_read (imap4->stream, inbuf, inend - inbuf)) == -1) - return -1; - else if (nread == 0) - imap4->disconnected = TRUE; - - imap4->inend += nread; - - return imap4->inend - imap4->inptr; -} - -static ssize_t -stream_read (CamelStream *stream, char *buffer, size_t n) -{ - CamelIMAP4Stream *imap4 = (CamelIMAP4Stream *) stream; - ssize_t len, nread = 0; - - if (imap4->mode == CAMEL_IMAP4_STREAM_MODE_LITERAL) { - /* don't let our caller read past the end of the literal */ - n = MIN (n, imap4->literal); - } - - if (imap4->inptr < imap4->inend) { - len = MIN (n, imap4->inend - imap4->inptr); - memcpy (buffer, imap4->inptr, len); - imap4->inptr += len; - nread = len; - } - - if (nread < n) { - if ((len = camel_stream_read (imap4->stream, buffer + nread, n - nread)) == 0) - imap4->disconnected = TRUE; - else if (len == -1) - return -1; - - nread += len; - } - - if (imap4->mode == CAMEL_IMAP4_STREAM_MODE_LITERAL) { - imap4->literal -= nread; - - if (imap4->literal == 0) { - imap4->mode = CAMEL_IMAP4_STREAM_MODE_TOKEN; - imap4->eol = TRUE; - } - } - - return nread; -} - -static ssize_t -stream_write (CamelStream *stream, const char *buffer, size_t n) -{ - CamelIMAP4Stream *imap4 = (CamelIMAP4Stream *) stream; - ssize_t nwritten; - - if (imap4->disconnected) { - errno = EINVAL; - return -1; - } - - if ((nwritten = camel_stream_write (imap4->stream, buffer, n)) == 0) - imap4->disconnected = TRUE; - - return nwritten; -} - -static int -stream_flush (CamelStream *stream) -{ - CamelIMAP4Stream *imap4 = (CamelIMAP4Stream *) stream; - - return camel_stream_flush (imap4->stream); -} - -static int -stream_close (CamelStream *stream) -{ - CamelIMAP4Stream *imap4 = (CamelIMAP4Stream *) stream; - - if (camel_stream_close (imap4->stream) == -1) - return -1; - - camel_object_unref (imap4->stream); - imap4->stream = NULL; - - imap4->disconnected = TRUE; - - return 0; -} - -static gboolean -stream_eos (CamelStream *stream) -{ - CamelIMAP4Stream *imap4 = (CamelIMAP4Stream *) stream; - - if (imap4->eol) - return TRUE; - - if (imap4->disconnected && imap4->inptr == imap4->inend) - return TRUE; - - if (camel_stream_eos (imap4->stream)) - return TRUE; - - return FALSE; -} - - -/** - * camel_imap4_stream_new: - * @stream: tcp stream - * - * Returns a new imap4 stream - **/ -CamelStream * -camel_imap4_stream_new (CamelStream *stream) -{ - CamelIMAP4Stream *imap4; - - g_return_val_if_fail (CAMEL_IS_STREAM (stream), NULL); - - imap4 = (CamelIMAP4Stream *) camel_object_new (CAMEL_TYPE_IMAP4_STREAM); - camel_object_ref (stream); - imap4->stream = stream; - - return (CamelStream *) imap4; -} - - - -#define token_save(imap4, start, len) G_STMT_START { \ - if (imap4->tokenleft <= len) { \ - unsigned int tlen, toff; \ - \ - tlen = toff = imap4->tokenptr - imap4->tokenbuf; \ - tlen = tlen ? tlen : 1; \ - \ - while (tlen < toff + len) \ - tlen <<= 1; \ - \ - imap4->tokenbuf = g_realloc (imap4->tokenbuf, tlen + 1); \ - imap4->tokenptr = imap4->tokenbuf + toff; \ - imap4->tokenleft = tlen - toff; \ - } \ - \ - memcpy (imap4->tokenptr, start, len); \ - imap4->tokenptr += len; \ - imap4->tokenleft -= len; \ -} G_STMT_END - -#define token_clear(imap4) G_STMT_START { \ - imap4->tokenleft += imap4->tokenptr - imap4->tokenbuf; \ - imap4->tokenptr = imap4->tokenbuf; \ - imap4->literal = 0; \ -} G_STMT_END - - -/** - * camel_imap4_stream_next_token: - * @stream: imap4 stream - * @token: imap4 token - * - * Reads the next token from the imap4 stream and saves it in @token. - * - * Returns 0 on success or -1 on fail. - **/ -int -camel_imap4_stream_next_token (CamelIMAP4Stream *stream, camel_imap4_token_t *token) -{ - register unsigned char *inptr; - unsigned char *inend, *start, *p; - gboolean escaped = FALSE; - size_t literal = 0; - guint32 nz_number; - int ret; - - g_return_val_if_fail (CAMEL_IS_IMAP4_STREAM (stream), -1); - g_return_val_if_fail (stream->mode != CAMEL_IMAP4_STREAM_MODE_LITERAL, -1); - g_return_val_if_fail (token != NULL, -1); - - if (stream->have_unget) { - memcpy (token, &stream->unget, sizeof (camel_imap4_token_t)); - stream->have_unget = FALSE; - return 0; - } - - token_clear (stream); - - inptr = stream->inptr; - inend = stream->inend; - *inend = '\0'; - - do { - if (inptr == inend) { - if ((ret = imap4_fill (stream)) < 0) { - token->token = CAMEL_IMAP4_TOKEN_ERROR; - return -1; - } else if (ret == 0) { - token->token = CAMEL_IMAP4_TOKEN_NO_DATA; - return 0; - } - - inptr = stream->inptr; - inend = stream->inend; - *inend = '\0'; - } - - while (*inptr == ' ' || *inptr == '\r') - inptr++; - } while (inptr == inend); - - do { - if (inptr < inend) { - if (*inptr == '"') { - /* qstring token */ - escaped = FALSE; - start = inptr; - - /* eat the beginning " */ - inptr++; - - p = inptr; - while (inptr < inend) { - if (*inptr == '"' && !escaped) - break; - - if (*inptr == '\\' && !escaped) { - token_save (stream, p, inptr - p); - escaped = TRUE; - inptr++; - p = inptr; - } else { - inptr++; - escaped = FALSE; - } - } - - token_save (stream, p, inptr - p); - - if (inptr == inend) { - stream->inptr = start; - goto refill; - } - - /* eat the ending " */ - inptr++; - - /* nul-terminate the atom token */ - token_save (stream, "", 1); - - token->token = CAMEL_IMAP4_TOKEN_QSTRING; - token->v.qstring = stream->tokenbuf; - - d(fprintf (stderr, "token: \"%s\"\n", token->v.qstring)); - - break; - } else if (strchr ("+*()[]\n", *inptr)) { - /* special character token */ - token->token = *inptr++; -#if d(!)0 - if (token->token != '\n') - fprintf (stderr, "token: %c\n", token->token); - else - fprintf (stderr, "token: \\n\n"); -#endif - break; - } else if (*inptr == '{') { - /* literal identifier token */ - if ((p = strchr (inptr, '}')) && strchr (p, '\n')) { - inptr++; - - while (isdigit ((int) *inptr) && literal < UINT_MAX / 10) - literal = (literal * 10) + (*inptr++ - '0'); - - if (*inptr != '}') { - if (isdigit ((int) *inptr)) - g_warning ("illegal literal identifier: literal too large"); - else if (*inptr != '+') - g_warning ("illegal literal identifier: garbage following size"); - - while (*inptr != '}') - inptr++; - } - - /* skip over '}' */ - inptr++; - - /* skip over any trailing whitespace */ - while (*inptr == ' ' || *inptr == '\r') - inptr++; - - if (*inptr != '\n') { - g_warning ("illegal token following literal identifier: %s", inptr); - - /* skip ahead to the eoln */ - inptr = strchr (inptr, '\n'); - } - - /* skip over '\n' */ - inptr++; - - token->token = CAMEL_IMAP4_TOKEN_LITERAL; - token->v.literal = literal; - - d(fprintf (stderr, "token: {%u}\n", literal)); - - stream->mode = CAMEL_IMAP4_STREAM_MODE_LITERAL; - stream->literal = literal; - stream->eol = FALSE; - - break; - } else { - stream->inptr = inptr; - goto refill; - } - } else if (*inptr >= '0' && *inptr <= '9') { - /* number token */ - *inend = '\0'; - nz_number = strtoul ((char *) inptr, (char **) &start, 10); - if (start == inend) - goto refill; - - if (*start == ':' || *start == ',') { - /* workaround for 'set' tokens (APPENDUID / COPYUID) */ - goto atom_token; - } - - inptr = start; - token->token = CAMEL_IMAP4_TOKEN_NUMBER; - token->v.number = nz_number; - - d(fprintf (stderr, "token: %u\n", nz_number)); - - break; - } else if (is_atom (*inptr)) { - atom_token: - /* simple atom token */ - start = inptr; - - while (inptr < inend && is_atom (*inptr)) - inptr++; - - if (inptr == inend) { - stream->inptr = start; - goto refill; - } - - token_save (stream, start, inptr - start); - - /* nul-terminate the atom token */ - token_save (stream, "", 1); - - if (!strcmp (stream->tokenbuf, "NIL")) { - /* special atom token */ - token->token = CAMEL_IMAP4_TOKEN_NIL; - d(fprintf (stderr, "token: NIL\n")); - } else { - token->token = CAMEL_IMAP4_TOKEN_ATOM; - token->v.atom = stream->tokenbuf; - d(fprintf (stderr, "token: %s\n", token->v.atom)); - } - - break; - } else if (*inptr == '\\') { - /* possible flag token ("\" atom) */ - start = inptr++; - - while (inptr < inend && is_atom (*inptr)) - inptr++; - - if (inptr == inend) { - stream->inptr = start; - goto refill; - } - - /* handle the \* case */ - if ((inptr - start) == 1 && *inptr == '*') - inptr++; - - if ((inptr - start) > 1) { - token_save (stream, start, inptr - start); - - /* nul-terminate the flag token */ - token_save (stream, "", 1); - - token->token = CAMEL_IMAP4_TOKEN_FLAG; - token->v.atom = stream->tokenbuf; - d(fprintf (stderr, "token: %s\n", token->v.atom)); - } else { - token->token = '\\'; - d(fprintf (stderr, "token: %c\n", token->token)); - } - break; - } else if (is_lwsp (*inptr)) { - inptr++; - } else { - /* unknown character token? */ - token->token = *inptr++; - d(fprintf (stderr, "token: %c\n", token->token)); - break; - } - } else { - refill: - token_clear (stream); - - if (imap4_fill (stream) <= 0) { - token->token = CAMEL_IMAP4_TOKEN_ERROR; - return -1; - } - - inptr = stream->inptr; - inend = stream->inend; - *inend = '\0'; - } - } while (inptr < inend); - - stream->inptr = inptr; - - return 0; -} - - -/** - * camel_imap4_stream_unget_token: - * @stream: imap4 stream - * @token: token to 'unget' - * - * Ungets an imap4 token (as in ungetc()). - * - * Note: you may *ONLY* unget a single token. Trying to unget another - * token will fail. - * - * Returns 0 on success or -1 on fail. - **/ -int -camel_imap4_stream_unget_token (CamelIMAP4Stream *stream, camel_imap4_token_t *token) -{ - if (stream->have_unget) - return -1; - - if (token->token != CAMEL_IMAP4_TOKEN_NO_DATA) { - memcpy (&stream->unget, token, sizeof (camel_imap4_token_t)); - stream->have_unget = TRUE; - } - - return 0; -} - - -/** - * camel_imap4_stream_line: - * @stream: imap4 stream - * @line: line pointer - * @len: line length - * - * Reads a single line from the imap4 stream and points @line at an - * internal buffer containing the line read and sets @len to the - * length of the line buffer. - * - * Returns -1 on error, 0 if the line read is complete, or 1 if the - * read is incomplete. - **/ -int -camel_imap4_stream_line (CamelIMAP4Stream *stream, unsigned char **line, size_t *len) -{ - register unsigned char *inptr; - unsigned char *inend; - - g_return_val_if_fail (CAMEL_IS_IMAP4_STREAM (stream), -1); - g_return_val_if_fail (stream->mode != CAMEL_IMAP4_STREAM_MODE_LITERAL, -1); - g_return_val_if_fail (line != NULL, -1); - g_return_val_if_fail (len != NULL, -1); - - inptr = stream->inptr; - inend = stream->inend; - - if (inptr == inend || ((inend - inptr) < 2 && *inptr != '\n')) { - if (imap4_fill (stream) == -1 && stream->inptr == stream->inend) - return -1; - } - - *line = stream->inptr; - inptr = stream->inptr; - inend = stream->inend; - *inend = '\n'; - - while (*inptr != '\n') - inptr++; - - *len = (inptr - stream->inptr); - - if (inptr > stream->inptr && inptr[-1] == '\r') - inptr[-1] = '\0'; - - if (inptr < inend) { - /* got the eoln */ - inptr[0] = '\0'; - *len += 1; - - stream->inptr = inptr + 1; - - return 0; - } - - stream->inptr = inptr; - - return 1; -} - - -/** - * camel_imap4_stream_literal: - * @stream: IMAP stream - * @literal: literal pointer - * @len: literal length - * - * Sets @literal to the beginning of the next chunk of the literal - * buffer from the IMAP stream and sets @len to the length of the - * @literal buffer. - * - * Returns >0 if more literal data exists, 0 if the end of the literal - * has been reached or -1 on fail. - **/ -int -camel_imap4_stream_literal (CamelIMAP4Stream *stream, unsigned char **literal, size_t *len) -{ - unsigned char *inptr, *inend; - size_t nread; - - g_return_val_if_fail (CAMEL_IS_IMAP4_STREAM (stream), -1); - g_return_val_if_fail (stream->mode == CAMEL_IMAP4_STREAM_MODE_LITERAL, -1); - g_return_val_if_fail (literal != NULL, -1); - g_return_val_if_fail (len != NULL, -1); - - if (stream->eol) { - *len = 0; - return 0; - } - - if ((stream->inend - stream->inptr) < 1) { - /* keep our buffer full to the optimal size */ - if (imap4_fill (stream) == -1 && stream->inptr == stream->inend) - return -1; - } - - *literal = inptr = stream->inptr; - inend = stream->inend; - if ((inend - inptr) > stream->literal) - inend = inptr + stream->literal; - else - inend = stream->inend; - - *len = nread = inend - inptr; - - stream->literal -= nread; - stream->inptr += nread; - - if (stream->literal == 0) { - stream->mode = CAMEL_IMAP4_STREAM_MODE_TOKEN; - stream->eol = TRUE; - return 0; - } - - return 1; -} diff --git a/camel/providers/imap4/camel-imap4-stream.h b/camel/providers/imap4/camel-imap4-stream.h deleted file mode 100644 index c0f870a0bd..0000000000 --- a/camel/providers/imap4/camel-imap4-stream.h +++ /dev/null @@ -1,125 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifndef __CAMEL_IMAP4_STREAM_H__ -#define __CAMEL_IMAP4_STREAM_H__ - -#include <camel/camel-stream.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define CAMEL_TYPE_IMAP4_STREAM (camel_imap4_stream_get_type ()) -#define CAMEL_IMAP4_STREAM(obj) (CAMEL_CHECK_CAST ((obj), CAMEL_TYPE_IMAP4_STREAM, CamelIMAP4Stream)) -#define CAMEL_IMAP4_STREAM_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_TYPE_IMAP4_STREAM, CamelIMAP4StreamClass)) -#define CAMEL_IS_IMAP4_STREAM(o) (CAMEL_CHECK_TYPE((o), CAMEL_TYPE_IMAP4_STREAM)) - -typedef struct _CamelIMAP4Stream CamelIMAP4Stream; -typedef struct _CamelIMAP4StreamClass CamelIMAP4StreamClass; - -#define IMAP4_READ_PRELEN 128 -#define IMAP4_READ_BUFLEN 4096 - -enum { - CAMEL_IMAP4_TOKEN_NO_DATA = -8, - CAMEL_IMAP4_TOKEN_ERROR = -7, - CAMEL_IMAP4_TOKEN_NIL = -6, - CAMEL_IMAP4_TOKEN_ATOM = -5, - CAMEL_IMAP4_TOKEN_FLAG = -4, - CAMEL_IMAP4_TOKEN_NUMBER = -3, - CAMEL_IMAP4_TOKEN_QSTRING = -2, - CAMEL_IMAP4_TOKEN_LITERAL = -1, - /* CAMEL_IMAP4_TOKEN_CHAR would just be the char we got */ - CAMEL_IMAP4_TOKEN_EOLN = '\n', - CAMEL_IMAP4_TOKEN_LPAREN = '(', - CAMEL_IMAP4_TOKEN_RPAREN = ')', - CAMEL_IMAP4_TOKEN_ASTERISK = '*', - CAMEL_IMAP4_TOKEN_PLUS = '+', - CAMEL_IMAP4_TOKEN_LBRACKET = '[', - CAMEL_IMAP4_TOKEN_RBRACKET = ']', -}; - -typedef struct _camel_imap4_token_t { - int token; - union { - char *atom; - char *flag; - char *qstring; - size_t literal; - guint32 number; - } v; -} camel_imap4_token_t; - -enum { - CAMEL_IMAP4_STREAM_MODE_TOKEN = 0, - CAMEL_IMAP4_STREAM_MODE_LITERAL = 1, -}; - -struct _CamelIMAP4Stream { - CamelStream parent_object; - - CamelStream *stream; - - guint disconnected:1; /* disconnected state */ - guint have_unget:1; /* have an unget token */ - guint mode:1; /* TOKEN vs LITERAL */ - guint eol:1; /* end-of-literal */ - - size_t literal; - - /* i/o buffers */ - unsigned char realbuf[IMAP4_READ_PRELEN + IMAP4_READ_BUFLEN + 1]; - unsigned char *inbuf; - unsigned char *inptr; - unsigned char *inend; - - /* token buffers */ - unsigned char *tokenbuf; - unsigned char *tokenptr; - unsigned int tokenleft; - - camel_imap4_token_t unget; -}; - -struct _CamelIMAP4StreamClass { - CamelStreamClass parent_class; - - /* Virtual methods */ -}; - - -/* Standard Camel function */ -CamelType camel_imap4_stream_get_type (void); - -CamelStream *camel_imap4_stream_new (CamelStream *stream); - -int camel_imap4_stream_next_token (CamelIMAP4Stream *stream, camel_imap4_token_t *token); -int camel_imap4_stream_unget_token (CamelIMAP4Stream *stream, camel_imap4_token_t *token); - -int camel_imap4_stream_line (CamelIMAP4Stream *stream, unsigned char **line, size_t *len); -int camel_imap4_stream_literal (CamelIMAP4Stream *stream, unsigned char **literal, size_t *len); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_IMAP4_STREAM_H__ */ diff --git a/camel/providers/imap4/camel-imap4-summary.c b/camel/providers/imap4/camel-imap4-summary.c deleted file mode 100644 index e38928ef43..0000000000 --- a/camel/providers/imap4/camel-imap4-summary.c +++ /dev/null @@ -1,1319 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <limits.h> -#include <utime.h> -#include <fcntl.h> -#include <ctype.h> -#include <errno.h> - -#include <libedataserver/md5-utils.h> - -#include <camel/camel-file-utils.h> -#include <camel/camel-string-utils.h> -#include <camel/camel-i18n.h> - -#include "camel-imap4-store.h" -#include "camel-imap4-engine.h" -#include "camel-imap4-folder.h" -#include "camel-imap4-stream.h" -#include "camel-imap4-command.h" -#include "camel-imap4-utils.h" - -#include "camel-imap4-summary.h" - -#define d(x) x - -#define IMAP4_SUMMARY_VERSION 1 - -static void camel_imap4_summary_class_init (CamelIMAP4SummaryClass *klass); -static void camel_imap4_summary_init (CamelIMAP4Summary *summary, CamelIMAP4SummaryClass *klass); -static void camel_imap4_summary_finalize (CamelObject *object); - -static int imap4_header_load (CamelFolderSummary *summary, FILE *fin); -static int imap4_header_save (CamelFolderSummary *summary, FILE *fout); -static CamelMessageInfo *imap4_message_info_new_from_header (CamelFolderSummary *summary, struct _camel_header_raw *header); -static CamelMessageInfo *imap4_message_info_load (CamelFolderSummary *summary, FILE *fin); -static int imap4_message_info_save (CamelFolderSummary *summary, FILE *fout, CamelMessageInfo *info); - - -static CamelFolderSummaryClass *parent_class = NULL; - - -CamelType -camel_imap4_summary_get_type (void) -{ - static CamelType type = 0; - - if (!type) { - type = camel_type_register (CAMEL_FOLDER_SUMMARY_TYPE, - "CamelIMAP4Summary", - sizeof (CamelIMAP4Summary), - sizeof (CamelIMAP4SummaryClass), - (CamelObjectClassInitFunc) camel_imap4_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_imap4_summary_init, - (CamelObjectFinalizeFunc) camel_imap4_summary_finalize); - } - - return type; -} - - -static void -camel_imap4_summary_class_init (CamelIMAP4SummaryClass *klass) -{ - CamelFolderSummaryClass *summary_class = (CamelFolderSummaryClass *) klass; - - parent_class = (CamelFolderSummaryClass *) camel_type_get_global_classfuncs (camel_folder_summary_get_type ()); - - summary_class->summary_header_load = imap4_header_load; - summary_class->summary_header_save = imap4_header_save; - summary_class->message_info_new_from_header = imap4_message_info_new_from_header; - summary_class->message_info_load = imap4_message_info_load; - summary_class->message_info_save = imap4_message_info_save; -} - -static void -camel_imap4_summary_init (CamelIMAP4Summary *summary, CamelIMAP4SummaryClass *klass) -{ - CamelFolderSummary *folder_summary = (CamelFolderSummary *) summary; - - folder_summary->version += IMAP4_SUMMARY_VERSION; - folder_summary->flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_DELETED | - CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN; - - folder_summary->message_info_size = sizeof (CamelIMAP4MessageInfo); - - summary->update_flags = TRUE; - summary->uidvalidity_changed = FALSE; -} - -static void -camel_imap4_summary_finalize (CamelObject *object) -{ - ; -} - - -CamelFolderSummary * -camel_imap4_summary_new (CamelFolder *folder) -{ - CamelFolderSummary *summary; - - summary = (CamelFolderSummary *) camel_object_new (CAMEL_TYPE_IMAP4_SUMMARY); - summary->folder = folder; - - return summary; -} - -static int -imap4_header_load (CamelFolderSummary *summary, FILE *fin) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - - if (CAMEL_FOLDER_SUMMARY_CLASS (parent_class)->summary_header_load (summary, fin) == -1) - return -1; - - if (camel_file_util_decode_uint32 (fin, &imap4_summary->uidvalidity) == -1) - return -1; - - return 0; -} - -static int -imap4_header_save (CamelFolderSummary *summary, FILE *fout) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - - if (CAMEL_FOLDER_SUMMARY_CLASS (parent_class)->summary_header_save (summary, fout) == -1) - return -1; - - if (camel_file_util_encode_uint32 (fout, imap4_summary->uidvalidity) == -1) - return -1; - - return 0; -} - -static int -envelope_decode_address (CamelIMAP4Engine *engine, GString *addrs, CamelException *ex) -{ - char *addr, *name = NULL, *user = NULL; - struct _camel_header_address *cia; - unsigned char *literal = NULL; - camel_imap4_token_t token; - const char *domain = NULL; - int part = 0; - size_t n; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token == CAMEL_IMAP4_TOKEN_NIL) { - return 0; - } else if (token.token != '(') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - if (addrs->len > 0) - g_string_append (addrs, ", "); - - do { - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - goto exception; - - literal = NULL; - switch (token.token) { - case CAMEL_IMAP4_TOKEN_NIL: - break; - case CAMEL_IMAP4_TOKEN_ATOM: - case CAMEL_IMAP4_TOKEN_QSTRING: - switch (part) { - case 0: - name = camel_header_decode_string (token.v.qstring, NULL); - break; - case 2: - user = g_strdup (token.v.qstring); - break; - case 3: - domain = token.v.qstring; - break; - } - break; - case CAMEL_IMAP4_TOKEN_LITERAL: - if (camel_imap4_engine_literal (engine, &literal, &n, ex) == -1) - goto exception; - - switch (part) { - case 0: - name = camel_header_decode_string (literal, NULL); - g_free (literal); - break; - case 2: - user = literal; - break; - case 3: - domain = literal; - break; - } - break; - default: - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - goto exception; - } - - part++; - } while (part < 4); - - addr = g_strdup_printf ("%s@%s", user, domain); - g_free (literal); - g_free (user); - - cia = camel_header_address_new_name (name, addr); - g_free (name); - g_free (addr); - - addr = camel_header_address_list_format (cia); - camel_header_address_unref (cia); - - g_string_append (addrs, addr); - g_free (addr); - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != ')') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - return 0; - - exception: - - g_free (name); - g_free (user); - - return -1; -} - -static int -envelope_decode_addresses (CamelIMAP4Engine *engine, char **addrlist, CamelException *ex) -{ - camel_imap4_token_t token; - GString *addrs; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token == CAMEL_IMAP4_TOKEN_NIL) { - *addrlist = NULL; - return 0; - } else if (token.token != '(') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - addrs = g_string_new (""); - - do { - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) { - g_string_free (addrs, TRUE); - return -1; - } - - if (token.token == '(') { - camel_imap4_stream_unget_token (engine->istream, &token); - - if (envelope_decode_address (engine, addrs, ex) == -1) { - g_string_free (addrs, TRUE); - return -1; - } - } else if (token.token == ')') { - break; - } else { - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - } while (1); - - *addrlist = addrs->str; - g_string_free (addrs, FALSE); - - return 0; -} - -static int -envelope_decode_date (CamelIMAP4Engine *engine, time_t *date, CamelException *ex) -{ - unsigned char *literal = NULL; - camel_imap4_token_t token; - const char *nstring; - size_t n; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - switch (token.token) { - case CAMEL_IMAP4_TOKEN_NIL: - *date = (time_t) -1; - return 0; - case CAMEL_IMAP4_TOKEN_ATOM: - nstring = token.v.atom; - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - nstring = token.v.qstring; - break; - case CAMEL_IMAP4_TOKEN_LITERAL: - if (camel_imap4_engine_literal (engine, &literal, &n, ex) == -1) - return -1; - - nstring = literal; - break; - default: - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - *date = camel_header_decode_date (nstring, NULL); - - g_free (literal); - - return 0; -} - -static int -envelope_decode_nstring (CamelIMAP4Engine *engine, char **nstring, gboolean rfc2047, CamelException *ex) -{ - camel_imap4_token_t token; - unsigned char *literal; - 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: - if (rfc2047) - *nstring = camel_header_decode_string (token.v.atom, NULL); - else - *nstring = g_strdup (token.v.atom); - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - if (rfc2047) - *nstring = camel_header_decode_string (token.v.qstring, NULL); - else - *nstring = g_strdup (token.v.qstring); - break; - case CAMEL_IMAP4_TOKEN_LITERAL: - if (camel_imap4_engine_literal (engine, &literal, &n, ex) == -1) - return -1; - - if (rfc2047) { - *nstring = camel_header_decode_string (literal, NULL); - g_free (literal); - } else - *nstring = literal; - - break; - default: - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - return 0; -} - -static CamelSummaryReferences * -decode_references (const char *string) -{ - struct _camel_header_references *refs, *r; - CamelSummaryReferences *references; - unsigned char md5sum[16]; - guint32 i, n = 0; - MD5Context md5; - - if (!(r = refs = camel_header_references_inreplyto_decode (string))) - return NULL; - - while (r != NULL) { - r = r->next; - n++; - } - - references = g_malloc (sizeof (CamelSummaryReferences) + (sizeof (CamelSummaryMessageID) * (n - 1))); - references->size = n; - - for (i = 0, r = refs; i < n; i++, r = r->next) { - md5_init (&md5); - md5_update (&md5, r->id, strlen (r->id)); - md5_final (&md5, md5sum); - memcpy (references->references[i].id.hash, md5sum, sizeof (references->references[i].id.hash)); - } - - camel_header_references_list_clear (&refs); - - return references; -} - -static int -decode_envelope (CamelIMAP4Engine *engine, CamelMessageInfo *info, camel_imap4_token_t *token, CamelException *ex) -{ - unsigned char md5sum[16]; - char *nstring; - CamelIMAP4MessageInfo *iinfo = (CamelIMAP4MessageInfo *)info; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token != '(') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - return -1; - } - - if (envelope_decode_date (engine, &iinfo->info.date_sent, ex) == -1) - goto exception; - - /* subject */ - if (envelope_decode_nstring (engine, &nstring, TRUE, ex) == -1) - goto exception; - iinfo->info.subject = camel_pstring_strdup(nstring); - g_free(nstring); - - /* from */ - if (envelope_decode_addresses (engine, &nstring, ex) == -1) - goto exception; - iinfo->info.from = camel_pstring_strdup(nstring); - g_free(nstring); - - /* sender */ - if (envelope_decode_addresses (engine, &nstring, ex) == -1) - goto exception; - g_free (nstring); - - /* reply-to */ - if (envelope_decode_addresses (engine, &nstring, ex) == -1) - goto exception; - g_free (nstring); - - /* to */ - if (envelope_decode_addresses (engine, &nstring, ex) == -1) - goto exception; - iinfo->info.to = camel_pstring_strdup(nstring); - g_free(nstring); - - /* cc */ - if (envelope_decode_addresses (engine, &nstring, ex) == -1) - goto exception; - iinfo->info.cc = camel_pstring_strdup(nstring); - g_free(nstring); - - /* bcc */ - if (envelope_decode_addresses (engine, &nstring, ex) == -1) - goto exception; - g_free (nstring); - - /* in-reply-to */ - if (envelope_decode_nstring (engine, &nstring, FALSE, ex) == -1) - goto exception; - - if (nstring != NULL) { - iinfo->info.references = decode_references (nstring); - g_free (nstring); - } - - /* message-id */ - if (envelope_decode_nstring (engine, &nstring, FALSE, ex) == -1) - goto exception; - - if (nstring != NULL) { - md5_get_digest (nstring, strlen (nstring), md5sum); - memcpy (iinfo->info.message_id.id.hash, md5sum, sizeof (iinfo->info.message_id.id.hash)); - g_free (nstring); - } - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token != ')') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - goto exception; - } - - return 0; - - exception: - - return -1; -} - -static char *tm_months[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -static gboolean -decode_time (const char **in, int *hour, int *min, int *sec) -{ - register const unsigned char *inptr = (const unsigned char *) *in; - int *val, colons = 0; - - *hour = *min = *sec = 0; - - val = hour; - for ( ; *inptr && !isspace ((int) *inptr); inptr++) { - if (*inptr == ':') { - colons++; - switch (colons) { - case 1: - val = min; - break; - case 2: - val = sec; - break; - default: - return FALSE; - } - } else if (!isdigit ((int) *inptr)) - return FALSE; - else - *val = (*val * 10) + (*inptr - '0'); - } - - *in = inptr; - - return TRUE; -} - -static time_t -mktime_utc (struct tm *tm) -{ - time_t tt; - - tm->tm_isdst = -1; - tt = mktime (tm); - -#if defined (HAVE_TM_GMTOFF) - tt += tm->tm_gmtoff; -#elif defined (HAVE_TIMEZONE) - if (tm->tm_isdst > 0) { -#if defined (HAVE_ALTZONE) - tt -= altzone; -#else /* !defined (HAVE_ALTZONE) */ - tt -= (timezone - 3600); -#endif - } else - tt -= timezone; -#endif - - return tt; -} - -static time_t -decode_internaldate (const char *in) -{ - const char *inptr = in; - int hour, min, sec, n; - struct tm tm; - time_t date; - char *buf; - - memset ((void *) &tm, 0, sizeof (struct tm)); - - tm.tm_mday = strtoul (inptr, &buf, 10); - if (buf == inptr || *buf != '-') - return (time_t) -1; - - inptr = buf + 1; - if (inptr[3] != '-') - return (time_t) -1; - - for (n = 0; n < 12; n++) { - if (!strncasecmp (inptr, tm_months[n], 3)) - break; - } - - if (n >= 12) - return (time_t) -1; - - tm.tm_mon = n; - - inptr += 4; - - n = strtoul (inptr, &buf, 10); - if (buf == inptr || *buf != ' ') - return (time_t) -1; - - tm.tm_year = n - 1900; - - inptr = buf + 1; - if (!decode_time (&inptr, &hour, &min, &sec)) - return (time_t) -1; - - tm.tm_hour = hour; - tm.tm_min = min; - tm.tm_sec = sec; - - n = strtol (inptr, NULL, 10); - - date = mktime_utc (&tm); - - /* date is now GMT of the time we want, but not offset by the timezone ... */ - - /* this should convert the time to the GMT equiv time */ - date -= ((n / 100) * 60 * 60) + (n % 100) * 60; - - return date; -} - -enum { - IMAP4_FETCH_ENVELOPE = (1 << 1), - IMAP4_FETCH_FLAGS = (1 << 2), - IMAP4_FETCH_INTERNALDATE = (1 << 3), - IMAP4_FETCH_RFC822SIZE = (1 << 4), - IMAP4_FETCH_UID = (1 << 5), -}; - -#define IMAP4_FETCH_ALL (IMAP4_FETCH_ENVELOPE | IMAP4_FETCH_FLAGS | IMAP4_FETCH_INTERNALDATE | IMAP4_FETCH_RFC822SIZE | IMAP4_FETCH_UID) - -struct imap4_envelope_t { - CamelMessageInfo *info; - guint changed; -}; - -struct imap4_fetch_all_t { - CamelFolderChangeInfo *changes; - CamelFolderSummary *summary; - GHashTable *uid_hash; - GPtrArray *added; - guint32 first; - guint32 need; - int count; - int total; -}; - -static void -imap4_fetch_all_free (struct imap4_fetch_all_t *fetch) -{ - struct imap4_envelope_t *envelope; - int i; - - for (i = 0; i < fetch->added->len; i++) { - if (!(envelope = fetch->added->pdata[i])) - continue; - - camel_message_info_free(envelope->info); - g_free (envelope); - } - - g_ptr_array_free (fetch->added, TRUE); - g_hash_table_destroy (fetch->uid_hash); - camel_folder_change_info_free (fetch->changes); - g_free (fetch); -} - -static void -courier_imap_is_a_piece_of_shit (CamelFolderSummary *summary, guint32 msg) -{ - CamelSession *session = ((CamelService *) summary->folder->parent_store)->session; - char *warning; - - warning = g_strdup_printf ("IMAP server did not respond with an untagged FETCH response " - "for message #%u. This is illegal according to rfc3501 (and " - "the older rfc2060). You will need to contact your\n" - "Administrator(s) (or ISP) and have them resolve this issue.\n\n" - "Hint: If your IMAP server is Courier-IMAP, it is likely that this " - "message is simply unreadable by the IMAP server and will need " - "to be given read permissions.", msg); - - camel_session_alert_user (session, CAMEL_SESSION_ALERT_WARNING, warning, FALSE); - g_free (warning); -} - -static void -imap4_fetch_all_add (struct imap4_fetch_all_t *fetch) -{ - CamelFolderChangeInfo *changes = NULL; - struct imap4_envelope_t *envelope; - CamelMessageInfo *info; - int i; - - changes = fetch->changes; - - for (i = 0; i < fetch->added->len; i++) { - if (!(envelope = fetch->added->pdata[i])) { - courier_imap_is_a_piece_of_shit (fetch->summary, i + fetch->first); - break; - } - - if (envelope->changed != IMAP4_FETCH_ALL) { - d(fprintf (stderr, "Hmmm, IMAP4 server didn't give us everything for message %d\n", i + 1)); - camel_message_info_free(envelope->info); - g_free (envelope); - continue; - } - - if ((info = camel_folder_summary_uid (fetch->summary, camel_message_info_uid (envelope->info)))) { - camel_message_info_free(envelope->info); - g_free (envelope); - continue; - } - - camel_folder_change_info_add_uid (changes, camel_message_info_uid (envelope->info)); - - camel_folder_summary_add (fetch->summary, envelope->info); - g_free (envelope); - } - - g_ptr_array_free (fetch->added, TRUE); - g_hash_table_destroy (fetch->uid_hash); - - if (camel_folder_change_info_changed (changes)) - camel_object_trigger_event (fetch->summary->folder, "folder_changed", changes); - camel_folder_change_info_free (changes); - - g_free (fetch); -} - -static guint32 -imap4_fetch_all_update (struct imap4_fetch_all_t *fetch) -{ - CamelIMAP4MessageInfo *iinfo, *new_iinfo; - CamelFolderChangeInfo *changes = NULL; - struct imap4_envelope_t *envelope; - CamelMessageInfo *info; - guint32 first = 0; - guint32 flags; - int scount, i; - - changes = fetch->changes; - - scount = camel_folder_summary_count (fetch->summary); - for (i = fetch->first - 1; i < scount; i++) { - info = camel_folder_summary_index (fetch->summary, i); - if (!(envelope = g_hash_table_lookup (fetch->uid_hash, camel_message_info_uid (info)))) { - /* remove it */ - camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info)); - camel_folder_summary_remove (fetch->summary, info); - scount--; - i--; - } else if (envelope->changed & IMAP4_FETCH_FLAGS) { - /* update it with the new flags */ - new_iinfo = (CamelIMAP4MessageInfo *) envelope->info; - iinfo = (CamelIMAP4MessageInfo *) info; - - flags = iinfo->info.flags; - iinfo->info.flags = camel_imap4_merge_flags (iinfo->server_flags, iinfo->info.flags, new_iinfo->server_flags); - iinfo->server_flags = new_iinfo->server_flags; - if (iinfo->info.flags != flags) - camel_folder_change_info_change_uid (changes, camel_message_info_uid (info)); - } - - camel_message_info_free(info); - } - - for (i = 0; i < fetch->added->len; i++) { - if (!(envelope = fetch->added->pdata[i])) { - courier_imap_is_a_piece_of_shit (fetch->summary, i + fetch->first); - break; - } - - info = envelope->info; - if (!first && camel_message_info_uid (info)) { - if ((info = camel_folder_summary_uid (fetch->summary, camel_message_info_uid (info)))) { - camel_message_info_free(info); - } else { - first = i + fetch->first; - } - } - - camel_message_info_free(envelope->info); - g_free (envelope); - } - - g_ptr_array_free (fetch->added, TRUE); - g_hash_table_destroy (fetch->uid_hash); - - if (camel_folder_change_info_changed (changes)) - camel_object_trigger_event (fetch->summary->folder, "folder_changed", changes); - camel_folder_change_info_free (changes); - - g_free (fetch); - - return first; -} - -static int -untagged_fetch_all (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, guint32 index, camel_imap4_token_t *token, CamelException *ex) -{ - struct imap4_fetch_all_t *fetch = ic->user_data; - CamelFolderSummary *summary = fetch->summary; - struct imap4_envelope_t *envelope = NULL; - GPtrArray *added = fetch->added; - CamelIMAP4MessageInfo *iinfo; - CamelMessageInfo *info; - guint32 changed = 0; - const char *iuid; - char uid[12]; - - if (index < fetch->first) { - /* we already have this message envelope cached - - * server is probably notifying us of a FLAGS change - * by another client? */ - g_assert (index < summary->messages->len); - iinfo = (CamelIMAP4MessageInfo *)(info = summary->messages->pdata[index - 1]); - g_assert (info != NULL); - } else { - if (index > (added->len + fetch->first - 1)) - g_ptr_array_set_size (added, index - fetch->first + 1); - - if (!(envelope = added->pdata[index - fetch->first])) { - iinfo = (CamelIMAP4MessageInfo *) (info = camel_message_info_new (summary)); - envelope = g_new (struct imap4_envelope_t, 1); - added->pdata[index - fetch->first] = envelope; - envelope->info = info; - envelope->changed = 0; - } else { - iinfo = (CamelIMAP4MessageInfo *) (info = envelope->info); - } - } - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - /* parse the FETCH response list */ - if (token->token != '(') { - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - return -1; - } - - do { - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token == ')' || token->token == '\n') - break; - - if (token->token != CAMEL_IMAP4_TOKEN_ATOM) - goto unexpected; - - if (!strcmp (token->v.atom, "ENVELOPE")) { - if (envelope) { - if (decode_envelope (engine, info, token, ex) == -1) - goto exception; - - changed |= IMAP4_FETCH_ENVELOPE; - } else { - CamelMessageInfo *tmp; - int rv; - - g_warning ("Hmmm, server is sending us ENVELOPE data for a message we didn't ask for (message %u)\n", - index); - tmp = camel_message_info_new (summary); - rv = decode_envelope (engine, tmp, token, ex); - camel_message_info_free(tmp); - - if (rv == -1) - goto exception; - } - } else if (!strcmp (token->v.atom, "FLAGS")) { - guint32 server_flags = 0; - - if (camel_imap4_parse_flags_list (engine, &server_flags, ex) == -1) - return -1; - - iinfo->info.flags = camel_imap4_merge_flags (iinfo->server_flags, iinfo->info.flags, server_flags); - iinfo->server_flags = server_flags; - - changed |= IMAP4_FETCH_FLAGS; - } else if (!strcmp (token->v.atom, "INTERNALDATE")) { - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - switch (token->token) { - case CAMEL_IMAP4_TOKEN_NIL: - iinfo->info.date_received = (time_t) -1; - break; - case CAMEL_IMAP4_TOKEN_ATOM: - case CAMEL_IMAP4_TOKEN_QSTRING: - iinfo->info.date_received = decode_internaldate (token->v.qstring); - break; - default: - goto unexpected; - } - - changed |= IMAP4_FETCH_INTERNALDATE; - } else if (!strcmp (token->v.atom, "RFC822.SIZE")) { - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token != CAMEL_IMAP4_TOKEN_NUMBER) - goto unexpected; - - iinfo->info.size = token->v.number; - - changed |= IMAP4_FETCH_RFC822SIZE; - } else if (!strcmp (token->v.atom, "UID")) { - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token != CAMEL_IMAP4_TOKEN_NUMBER || token->v.number == 0) - goto unexpected; - - sprintf (uid, "%u", token->v.number); - iuid = camel_message_info_uid (info); - if (iuid != NULL && iuid[0] != '\0') { - if (strcmp (iuid, uid) != 0) { - d(fprintf (stderr, "Hmmm, UID mismatch for message %u\n", index)); - g_assert_not_reached (); - } - } else { - g_free(info->uid); - info->uid = g_strdup (uid); - g_hash_table_insert (fetch->uid_hash, (void *) camel_message_info_uid (info), envelope); - changed |= IMAP4_FETCH_UID; - } - } else { - /* wtf? */ - d(fprintf (stderr, "huh? %s?...\n", token->v.atom)); - } - } while (1); - - if (envelope) { - envelope->changed |= changed; - if ((envelope->changed & fetch->need) == fetch->need) - camel_operation_progress (NULL, (++fetch->count * 100.0f) / fetch->total); - } else if (changed & IMAP4_FETCH_FLAGS) { - camel_folder_change_info_change_uid (fetch->changes, camel_message_info_uid (info)); - } - - if (token->token != ')') - goto unexpected; - - return 0; - - unexpected: - - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - - exception: - - return -1; -} - -#define IMAP4_ALL "FLAGS INTERNALDATE RFC822.SIZE ENVELOPE" - -static CamelIMAP4Command * -imap4_summary_fetch_all (CamelFolderSummary *summary, guint32 first, guint32 last) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - CamelFolder *folder = summary->folder; - struct imap4_fetch_all_t *fetch; - CamelIMAP4Engine *engine; - CamelIMAP4Command *ic; - int total; - - engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - - total = last ? (last - first) + 1 : (imap4_summary->exists - first) + 1; - fetch = g_new (struct imap4_fetch_all_t, 1); - fetch->uid_hash = g_hash_table_new (g_str_hash, g_str_equal); - fetch->changes = camel_folder_change_info_new (); - fetch->added = g_ptr_array_sized_new (total); - fetch->summary = summary; - fetch->first = first; - fetch->need = IMAP4_FETCH_ALL; - fetch->total = total; - fetch->count = 0; - - if (last != 0) - ic = camel_imap4_engine_queue (engine, folder, "FETCH %u:%u (UID " IMAP4_ALL ")\r\n", first, last); - else - ic = camel_imap4_engine_queue (engine, folder, "FETCH %u:* (UID " IMAP4_ALL ")\r\n", first); - - camel_imap4_command_register_untagged (ic, "FETCH", untagged_fetch_all); - ic->user_data = fetch; - - return ic; -} - -static CamelIMAP4Command * -imap4_summary_fetch_flags (CamelFolderSummary *summary, guint32 first, guint32 last) -{ - CamelFolder *folder = summary->folder; - struct imap4_fetch_all_t *fetch; - CamelIMAP4Engine *engine; - CamelIMAP4Command *ic; - int total; - - engine = ((CamelIMAP4Store *) folder->parent_store)->engine; - - total = (last - first) + 1; - fetch = g_new (struct imap4_fetch_all_t, 1); - fetch->uid_hash = g_hash_table_new (g_str_hash, g_str_equal); - fetch->changes = camel_folder_change_info_new (); - fetch->added = g_ptr_array_sized_new (total); - fetch->summary = summary; - fetch->first = first; - fetch->need = IMAP4_FETCH_UID | IMAP4_FETCH_FLAGS; - fetch->total = total; - fetch->count = 0; - - if (last != 0) - ic = camel_imap4_engine_queue (engine, folder, "FETCH %u:%u (UID FLAGS)\r\n", first, last); - else - ic = camel_imap4_engine_queue (engine, folder, "FETCH %u:* (UID FLAGS)\r\n", first); - - camel_imap4_command_register_untagged (ic, "FETCH", untagged_fetch_all); - ic->user_data = fetch; - - return ic; -} - -#if 0 -static int -imap4_build_summary (CamelFolderSummary *summary, guint32 first, guint32 last) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - CamelFolder *folder = summary->folder; - struct imap4_fetch_all_t *fetch; - CamelIMAP4Engine *engine; - CamelIMAP4Command *ic; - int id; - - engine = ((CamelIMAP4Store *) folder->store)->engine; - - ic = imap4_summary_fetch_all (summary, first, last); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - fetch = ic->user_data; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - camel_imap4_command_unref (ic); - imap4_fetch_all_free (fetch); - return -1; - } - - imap4_fetch_all_add (fetch); - - camel_imap4_command_unref (ic); - - return 0; -} -#endif - -static CamelMessageInfo * -imap4_message_info_new_from_header (CamelFolderSummary *summary, struct _camel_header_raw *header) -{ - CamelMessageInfo *info; - - info = CAMEL_FOLDER_SUMMARY_CLASS (parent_class)->message_info_new_from_header (summary, header); - - ((CamelIMAP4MessageInfo *) info)->server_flags = 0; - - return info; -} - -static CamelMessageInfo * -imap4_message_info_load (CamelFolderSummary *summary, FILE *fin) -{ - CamelIMAP4MessageInfo *minfo; - CamelMessageInfo *info; - - if (!(info = CAMEL_FOLDER_SUMMARY_CLASS (parent_class)->message_info_load (summary, fin))) - return NULL; - - minfo = (CamelIMAP4MessageInfo *) info; - - if (camel_file_util_decode_uint32 (fin, &minfo->server_flags) == -1) - goto exception; - - return info; - - exception: - - camel_message_info_free(info); - - return NULL; -} - -static int -imap4_message_info_save (CamelFolderSummary *summary, FILE *fout, CamelMessageInfo *info) -{ - CamelIMAP4MessageInfo *minfo = (CamelIMAP4MessageInfo *) info; - - if (CAMEL_FOLDER_SUMMARY_CLASS (parent_class)->message_info_save (summary, fout, info) == -1) - return -1; - - if (camel_file_util_encode_uint32 (fout, minfo->server_flags) == -1) - return -1; - - return 0; -} - - -void -camel_imap4_summary_set_exists (CamelFolderSummary *summary, guint32 exists) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - - g_return_if_fail (CAMEL_IS_IMAP4_SUMMARY (summary)); - - imap4_summary->exists = exists; -} - -void -camel_imap4_summary_set_recent (CamelFolderSummary *summary, guint32 recent) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - - g_return_if_fail (CAMEL_IS_IMAP4_SUMMARY (summary)); - - imap4_summary->recent = recent; -} - -void -camel_imap4_summary_set_unseen (CamelFolderSummary *summary, guint32 unseen) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - - g_return_if_fail (CAMEL_IS_IMAP4_SUMMARY (summary)); - - imap4_summary->unseen = unseen; -} - -void -camel_imap4_summary_set_uidnext (CamelFolderSummary *summary, guint32 uidnext) -{ - g_return_if_fail (CAMEL_IS_IMAP4_SUMMARY (summary)); - - summary->nextuid = uidnext; -} - -void -camel_imap4_summary_set_uidvalidity (CamelFolderSummary *summary, guint32 uidvalidity) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - CamelFolderChangeInfo *changes; - CamelMessageInfo *info; - int i, count; - - g_return_if_fail (CAMEL_IS_IMAP4_SUMMARY (summary)); - - if (imap4_summary->uidvalidity == uidvalidity) - return; - - changes = camel_folder_change_info_new (); - count = camel_folder_summary_count (summary); - for (i = 0; i < count; i++) { - if (!(info = camel_folder_summary_index (summary, i))) - continue; - - camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info)); - camel_message_info_free(info); - } - - camel_folder_summary_clear (summary); - camel_data_cache_clear (((CamelIMAP4Folder *) summary->folder)->cache, "cache", NULL); - - if (camel_folder_change_info_changed (changes)) - camel_object_trigger_event (summary->folder, "folder_changed", changes); - camel_folder_change_info_free (changes); - - imap4_summary->uidvalidity = uidvalidity; - - imap4_summary->uidvalidity_changed = TRUE; -} - -void -camel_imap4_summary_expunge (CamelFolderSummary *summary, int seqid) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - CamelFolderChangeInfo *changes; - CamelMessageInfo *info; - const char *uid; - - g_return_if_fail (CAMEL_IS_IMAP4_SUMMARY (summary)); - - seqid--; - if (!(info = camel_folder_summary_index (summary, seqid))) - return; - - imap4_summary->exists--; - - uid = camel_message_info_uid (info); - camel_data_cache_remove (((CamelIMAP4Folder *) summary->folder)->cache, "cache", uid, NULL); - - changes = camel_folder_change_info_new (); - camel_folder_change_info_remove_uid (changes, uid); - - camel_message_info_free(info); - camel_folder_summary_remove_index (summary, seqid); - - camel_object_trigger_event (summary->folder, "folder_changed", changes); - camel_folder_change_info_free (changes); -} - -#if 0 -static int -info_uid_sort (const CamelMessageInfo **info0, const CamelMessageInfo **info1) -{ - guint32 uid0, uid1; - - uid0 = strtoul (camel_message_info_uid (*info0), NULL, 10); - uid1 = strtoul (camel_message_info_uid (*info1), NULL, 10); - - if (uid0 == uid1) - return 0; - - return uid0 < uid1 ? -1 : 1; -} -#endif - -int -camel_imap4_summary_flush_updates (CamelFolderSummary *summary, CamelException *ex) -{ - CamelIMAP4Summary *imap4_summary = (CamelIMAP4Summary *) summary; - CamelIMAP4Engine *engine; - CamelIMAP4Command *ic; - guint32 first = 0; - int scount, id; - - g_return_val_if_fail (CAMEL_IS_IMAP4_SUMMARY (summary), -1); - - engine = ((CamelIMAP4Store *) summary->folder->parent_store)->engine; - scount = camel_folder_summary_count (summary); - - if (imap4_summary->uidvalidity_changed) { - first = 1; - } else if (imap4_summary->update_flags || imap4_summary->exists < scount) { - /* this both updates flags and removes messages which - * have since been expunged from the server by another - * client */ - ic = imap4_summary_fetch_flags (summary, 1, scount); - - camel_operation_start (NULL, _("Scanning for changed messages")); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - imap4_fetch_all_free (ic->user_data); - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - camel_operation_end (NULL); - return -1; - } - - if (!(first = imap4_fetch_all_update (ic->user_data)) && imap4_summary->exists > scount) - first = scount + 1; - - camel_imap4_command_unref (ic); - camel_operation_end (NULL); - } else { - first = scount + 1; - } - - if (first != 0 && first <= imap4_summary->exists) { - ic = imap4_summary_fetch_all (summary, first, 0); - - camel_operation_start (NULL, _("Fetching envelopes for new messages")); - while ((id = camel_imap4_engine_iterate (engine)) < ic->id && id != -1) - ; - - if (id == -1 || ic->status != CAMEL_IMAP4_COMMAND_COMPLETE) { - imap4_fetch_all_free (ic->user_data); - camel_exception_xfer (ex, &ic->ex); - camel_imap4_command_unref (ic); - camel_operation_end (NULL); - return -1; - } - - imap4_fetch_all_add (ic->user_data); - camel_imap4_command_unref (ic); - camel_operation_end (NULL); - -#if 0 - /* Note: this should not be needed - the code that adds envelopes to the summary - * adds them in proper order */ - - /* it's important for these to be sorted sequentially for EXPUNGE events to work */ - g_ptr_array_sort (summary->messages, (GCompareFunc) info_uid_sort); -#endif - } - - imap4_summary->update_flags = FALSE; - imap4_summary->uidvalidity_changed = FALSE; - - return 0; -} diff --git a/camel/providers/imap4/camel-imap4-summary.h b/camel/providers/imap4/camel-imap4-summary.h deleted file mode 100644 index 0145e4ac52..0000000000 --- a/camel/providers/imap4/camel-imap4-summary.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifndef __CAMEL_IMAP4_SUMMARY_H__ -#define __CAMEL_IMAP4_SUMMARY_H__ - -#include <sys/types.h> - -#include <camel/camel-folder.h> -#include <camel/camel-folder-summary.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#define CAMEL_TYPE_IMAP4_SUMMARY (camel_imap4_summary_get_type ()) -#define CAMEL_IMAP4_SUMMARY(obj) (CAMEL_CHECK_CAST ((obj), CAMEL_TYPE_IMAP4_SUMMARY, CamelIMAP4Summary)) -#define CAMEL_IMAP4_SUMMARY_CLASS(klass) (CAMEL_CHECK_CLASS_CAST ((klass), CAMEL_TYPE_IMAP4_SUMMARY, CamelIMAP4SummaryClass)) -#define CAMEL_IS_IMAP4_SUMMARY(obj) (CAMEL_CHECK_TYPE ((obj), CAMEL_TYPE_IMAP4_SUMMARY)) -#define CAMEL_IS_IMAP4_SUMMARY_CLASS(klass) (CAMEL_CHECK_CLASS_TYPE ((klass), CAMEL_TYPE_IMAP4_SUMMARY)) -#define CAMEL_IMAP4_SUMMARY_GET_CLASS(obj) (CAMEL_CHECK_GET_CLASS ((obj), CAMEL_TYPE_FOLDER_SUMMARY, CamelIMAP4SummaryClass)) - -typedef struct _CamelIMAP4MessageInfo CamelIMAP4MessageInfo; -typedef struct _CamelIMAP4Summary CamelIMAP4Summary; -typedef struct _CamelIMAP4SummaryClass CamelIMAP4SummaryClass; - -#define CAMEL_IMAP4_MESSAGE_RECENT (1 << 17) - -struct _CamelIMAP4MessageInfo { - CamelMessageInfoBase info; - - guint32 server_flags; -}; - -struct _CamelIMAP4Summary { - CamelFolderSummary parent_object; - - guint32 exists; - guint32 recent; - guint32 unseen; - - guint32 uidvalidity; - - guint uidvalidity_changed:1; - guint update_flags:1; -}; - -struct _CamelIMAP4SummaryClass { - CamelFolderSummaryClass parent_class; - -}; - - -CamelType camel_imap4_summary_get_type (void); - -CamelFolderSummary *camel_imap4_summary_new (CamelFolder *folder); - -void camel_imap4_summary_set_exists (CamelFolderSummary *summary, guint32 exists); -void camel_imap4_summary_set_recent (CamelFolderSummary *summary, guint32 recent); -void camel_imap4_summary_set_unseen (CamelFolderSummary *summary, guint32 unseen); -void camel_imap4_summary_set_uidnext (CamelFolderSummary *summary, guint32 uidnext); - -void camel_imap4_summary_set_uidvalidity (CamelFolderSummary *summary, guint32 uidvalidity); - -void camel_imap4_summary_expunge (CamelFolderSummary *summary, int seqid); - -int camel_imap4_summary_flush_updates (CamelFolderSummary *summary, CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_IMAP4_SUMMARY_H__ */ diff --git a/camel/providers/imap4/camel-imap4-utils.c b/camel/providers/imap4/camel-imap4-utils.c deleted file mode 100644 index 8a0e92f502..0000000000 --- a/camel/providers/imap4/camel-imap4-utils.c +++ /dev/null @@ -1,749 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> - -#include <camel/camel-store.h> -#include <camel/camel-i18n.h> -#include <camel/camel-net-utils.h> - -#include "camel-imap4-engine.h" -#include "camel-imap4-stream.h" -#include "camel-imap4-command.h" -#include "camel-imap4-summary.h" -#include "camel-imap4-store-summary.h" - -#include "camel-imap4-utils.h" - -#define d(x) x - - -void -camel_imap4_flags_diff (flags_diff_t *diff, guint32 old, guint32 new) -{ - diff->changed = old ^ new; - diff->bits = new & diff->changed; -} - - -guint32 -camel_imap4_flags_merge (flags_diff_t *diff, guint32 flags) -{ - return (flags & ~diff->changed) | diff->bits; -} - - -/** - * camel_imap4_merge_flags: - * @original: original server flags - * @local: local flags (after changes) - * @server: new server flags (another client updated the server flags) - * - * Merge the local flag changes into the new server flags. - * - * Returns the merged flags. - **/ -guint32 -camel_imap4_merge_flags (guint32 original, guint32 local, guint32 server) -{ - flags_diff_t diff; - - camel_imap4_flags_diff (&diff, original, local); - - return camel_imap4_flags_merge (&diff, server); -} - - -void -camel_imap4_namespace_clear (CamelIMAP4Namespace **ns) -{ - CamelIMAP4Namespace *node, *next; - - node = *ns; - while (node != NULL) { - next = node->next; - g_free (node->path); - g_free (node); - node = next; - } - - *ns = NULL; -} - -static CamelIMAP4Namespace * -imap4_namespace_copy (const CamelIMAP4Namespace *ns) -{ - CamelIMAP4Namespace *list, *node, *tail; - - list = NULL; - tail = (CamelIMAP4Namespace *) &list; - - while (ns != NULL) { - tail->next = node = g_malloc (sizeof (CamelIMAP4Namespace)); - node->path = g_strdup (ns->path); - node->sep = ns->sep; - ns = ns->next; - tail = node; - } - - tail->next = NULL; - - return list; -} - -CamelIMAP4NamespaceList * -camel_imap4_namespace_list_copy (const CamelIMAP4NamespaceList *nsl) -{ - CamelIMAP4NamespaceList *new; - - new = g_malloc (sizeof (CamelIMAP4NamespaceList)); - new->personal = imap4_namespace_copy (nsl->personal); - new->other = imap4_namespace_copy (nsl->other); - new->shared = imap4_namespace_copy (nsl->shared); - - return new; -} - -void -camel_imap4_namespace_list_free (CamelIMAP4NamespaceList *nsl) -{ - camel_imap4_namespace_clear (&nsl->personal); - camel_imap4_namespace_clear (&nsl->shared); - camel_imap4_namespace_clear (&nsl->other); - g_free (nsl); -} - - -char -camel_imap4_get_path_delim (CamelIMAP4StoreSummary *s, const char *full_name) -{ - CamelIMAP4Namespace *namespace; - const char *slash; - size_t len; - char *top; - - g_return_val_if_fail (s->namespaces != NULL, '/'); - - 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")) - strcpy (top, "INBOX"); - - retry: - namespace = s->namespaces->personal; - while (namespace != NULL) { - if (!strcmp (namespace->path, top)) - return namespace->sep; - namespace = namespace->next; - } - - namespace = s->namespaces->other; - while (namespace != NULL) { - if (!strcmp (namespace->path, top)) - return namespace->sep; - namespace = namespace->next; - } - - namespace = s->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 '/'; -} - - -struct _uidset_range { - struct _uidset_range *next; - guint32 first, last; - uint8_t buflen; - char buf[24]; -}; - -struct _uidset { - CamelFolderSummary *summary; - struct _uidset_range *ranges; - struct _uidset_range *tail; - size_t maxlen, setlen; -}; - -static void -uidset_range_free (struct _uidset_range *range) -{ - struct _uidset_range *next; - - while (range != NULL) { - next = range->next; - g_free (range); - range = next; - } -} - -static void -uidset_init (struct _uidset *uidset, CamelFolderSummary *summary, size_t maxlen) -{ - uidset->ranges = g_new (struct _uidset_range, 1); - uidset->ranges->first = (guint32) -1; - uidset->ranges->last = (guint32) -1; - uidset->ranges->next = NULL; - uidset->ranges->buflen = 0; - - uidset->tail = uidset->ranges; - uidset->summary = summary; - uidset->maxlen = maxlen; - uidset->setlen = 0; -} - -/* returns: -1 on full-and-not-added, 0 on added-and-not-full or 1 on added-and-full */ -static int -uidset_add (struct _uidset *uidset, CamelMessageInfo *info) -{ - GPtrArray *messages = uidset->summary->messages; - struct _uidset_range *node, *tail = uidset->tail; - const char *iuid = camel_message_info_uid (info); - size_t uidlen, len; - const char *colon; - guint32 index; - - /* Note: depends on integer overflow for initial 'add' */ - for (index = tail->last + 1; index < messages->len; index++) { - if (info == messages->pdata[index]) - break; - } - - g_assert (index < messages->len); - - uidlen = strlen (iuid); - - if (tail->buflen == 0) { - /* first add */ - tail->first = tail->last = index; - strcpy (tail->buf, iuid); - uidset->setlen = uidlen; - tail->buflen = uidlen; - } else if (index == (tail->last + 1)) { - /* add to last range */ - if (tail->last == tail->first) { - /* make sure we've got enough room to add this one... */ - if ((uidset->setlen + uidlen + 1) > uidset->maxlen) - return -1; - - tail->buf[tail->buflen++] = ':'; - uidset->setlen++; - } else { - colon = strchr (tail->buf, ':') + 1; - - len = strlen (colon); - uidset->setlen -= len; - tail->buflen -= len; - } - - strcpy (tail->buf + tail->buflen, iuid); - uidset->setlen += uidlen; - tail->buflen += uidlen; - - tail->last = index; - } else if ((uidset->setlen + uidlen + 1) < uidset->maxlen) { - /* the beginning of a new range */ - tail->next = node = g_new (struct _uidset_range, 1); - node->first = node->last = index; - strcpy (node->buf, iuid); - uidset->setlen += uidlen + 1; - node->buflen = uidlen; - uidset->tail = node; - node->next = NULL; - } else { - /* can't add this one... */ - return -1; - } - - fprintf (stderr, "added uid %s to uidset (summary index = %u)\n", iuid, index); - - if (uidset->setlen < uidset->maxlen) - return 0; - - return 1; -} - -static char * -uidset_to_string (struct _uidset *uidset) -{ - struct _uidset_range *range; - GString *string; - char *str; - - string = g_string_new (""); - - range = uidset->ranges; - while (range != NULL) { - g_string_append (string, range->buf); - range = range->next; - if (range) - g_string_append_c (string, ','); - } - - str = string->str; - g_string_free (string, FALSE); - - return str; -} - -int -camel_imap4_get_uid_set (CamelIMAP4Engine *engine, CamelFolderSummary *summary, GPtrArray *infos, int cur, size_t linelen, char **set) -{ - struct _uidset uidset; - size_t maxlen; - int rv = 0; - int i; - - if (engine->maxlentype == CAMEL_IMAP4_ENGINE_MAXLEN_LINE) - maxlen = engine->maxlen - linelen; - else - maxlen = engine->maxlen; - - uidset_init (&uidset, summary, maxlen); - - for (i = cur; i < infos->len && rv != 1; i++) { - if ((rv = uidset_add (&uidset, infos->pdata[i])) == -1) - break; - } - - if (i > cur) - *set = uidset_to_string (&uidset); - - uidset_range_free (uidset.ranges); - - return (i - cur); -} - - -void -camel_imap4_utils_set_unexpected_token_error (CamelException *ex, CamelIMAP4Engine *engine, camel_imap4_token_t *token) -{ - GString *errmsg; - - if (ex == NULL) - return; - - errmsg = g_string_new (""); - g_string_append_printf (errmsg, _("Unexpected token in response from IMAP server %s: "), - engine->url->host); - - switch (token->token) { - case CAMEL_IMAP4_TOKEN_NIL: - g_string_append (errmsg, "NIL"); - break; - case CAMEL_IMAP4_TOKEN_ATOM: - g_string_append (errmsg, token->v.atom); - break; - case CAMEL_IMAP4_TOKEN_FLAG: - g_string_append (errmsg, token->v.flag); - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - g_string_append (errmsg, token->v.qstring); - break; - case CAMEL_IMAP4_TOKEN_LITERAL: - g_string_append_printf (errmsg, "{%u}", token->v.literal); - break; - case CAMEL_IMAP4_TOKEN_NUMBER: - g_string_append_printf (errmsg, "%u", token->v.number); - break; - case CAMEL_IMAP4_TOKEN_NO_DATA: - g_string_append (errmsg, _("No data")); - break; - default: - g_string_append_c (errmsg, (unsigned char) (token->token & 0xff)); - break; - } - - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, errmsg->str); - - g_string_free (errmsg, TRUE); -} - - -static struct { - const char *name; - guint32 flag; -} imap4_flags[] = { - { "\\Answered", CAMEL_MESSAGE_ANSWERED }, - { "\\Deleted", CAMEL_MESSAGE_DELETED }, - { "\\Draft", CAMEL_MESSAGE_DRAFT }, - { "\\Flagged", CAMEL_MESSAGE_FLAGGED }, - { "\\Seen", CAMEL_MESSAGE_SEEN }, - { "\\Recent", CAMEL_IMAP4_MESSAGE_RECENT }, - { "\\*", CAMEL_MESSAGE_USER }, -}; - -#if 0 -static struct { - const char *name; - guint32 flag; -} imap4_user_flags[] = { - { "$Forwarded", CAMEL_MESSAGE_FORWARDED }, -}; -#endif - - -int -camel_imap4_parse_flags_list (CamelIMAP4Engine *engine, guint32 *flags, CamelException *ex) -{ - camel_imap4_token_t token; - guint32 new = 0; - int i; - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - if (token.token != '(') { - d(fprintf (stderr, "Expected to find a '(' token starting the flags list\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - - while (token.token == CAMEL_IMAP4_TOKEN_ATOM || token.token == CAMEL_IMAP4_TOKEN_FLAG) { - /* parse the flags list */ - for (i = 0; i < G_N_ELEMENTS (imap4_flags); i++) { - if (!g_ascii_strcasecmp (imap4_flags[i].name, token.v.atom)) { - new |= imap4_flags[i].flag; - break; - } - } - -#if 0 - if (i == G_N_ELEMENTS (imap4_flags)) { - for (i = 0; i < G_N_ELEMENTS (imap4_user_flags); i++) { - if (!g_ascii_strcasecmp (imap4_user_flags[i].name, token.v.atom)) { - new |= imap4_user_flags[i].flag; - break; - } - } - - if (i == G_N_ELEMENTS (imap4_user_flags)) - fprintf (stderr, "Encountered unknown flag: %s\n", token.v.atom); - } -#else - if (i == G_N_ELEMENTS (imap4_flags)) - fprintf (stderr, "Encountered unknown flag: %s\n", token.v.atom); -#endif - - if (camel_imap4_engine_next_token (engine, &token, ex) == -1) - return -1; - } - - if (token.token != ')') { - d(fprintf (stderr, "Expected to find a ')' token terminating the flags list\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, &token); - return -1; - } - - *flags = new; - - return 0; -} - - -struct { - const char *name; - guint32 flag; -} list_flags[] = { - { "\\Marked", CAMEL_IMAP4_FOLDER_MARKED }, - { "\\Unmarked", CAMEL_IMAP4_FOLDER_UNMARKED }, - { "\\Noselect", CAMEL_FOLDER_NOSELECT }, - { "\\Noinferiors", CAMEL_FOLDER_NOINFERIORS }, - { "\\HasChildren", CAMEL_FOLDER_CHILDREN }, - { "\\HasNoChildren", CAMEL_FOLDER_NOCHILDREN }, -}; - -int -camel_imap4_untagged_list (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, guint32 index, camel_imap4_token_t *token, CamelException *ex) -{ - GPtrArray *array = ic->user_data; - camel_imap4_list_t *list; - unsigned char *buf; - guint32 flags = 0; - GString *literal; - char delim; - size_t n; - int i; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - /* parse the flag list */ - if (token->token != '(') - goto unexpected; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - while (token->token == CAMEL_IMAP4_TOKEN_FLAG || token->token == CAMEL_IMAP4_TOKEN_ATOM) { - for (i = 0; i < G_N_ELEMENTS (list_flags); i++) { - if (!g_ascii_strcasecmp (list_flags[i].name, token->v.atom)) { - flags |= list_flags[i].flag; - break; - } - } - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - } - - if (token->token != ')') - goto unexpected; - - /* parse the path delimiter */ - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - switch (token->token) { - case CAMEL_IMAP4_TOKEN_NIL: - delim = '\0'; - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - delim = *token->v.qstring; - break; - default: - goto unexpected; - } - - /* parse the folder name */ - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - list = g_new (camel_imap4_list_t, 1); - list->flags = flags; - list->delim = delim; - - switch (token->token) { - case CAMEL_IMAP4_TOKEN_ATOM: - list->name = g_strdup (token->v.atom); - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - list->name = g_strdup (token->v.qstring); - break; - case CAMEL_IMAP4_TOKEN_LITERAL: - literal = g_string_new (""); - while ((i = camel_imap4_stream_literal (engine->istream, &buf, &n)) == 1) - g_string_append_len (literal, buf, n); - - if (i == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("IMAP server %s unexpectedly disconnected: %s"), - engine->url->host, errno ? g_strerror (errno) : _("Unknown")); - g_string_free (literal, TRUE); - return -1; - } - - g_string_append_len (literal, buf, n); - list->name = literal->str; - g_string_free (literal, FALSE); - break; - default: - g_free (list); - goto unexpected; - } - - g_ptr_array_add (array, list); - - return camel_imap4_engine_eat_line (engine, ex); - - unexpected: - - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - - return -1; -} - - -static struct { - const char *name; - int type; -} imap4_status[] = { - { "MESSAGES", CAMEL_IMAP4_STATUS_MESSAGES }, - { "RECENT", CAMEL_IMAP4_STATUS_RECENT }, - { "UIDNEXT", CAMEL_IMAP4_STATUS_UIDNEXT }, - { "UIDVALIDITY", CAMEL_IMAP4_STATUS_UIDVALIDITY }, - { "UNSEEN", CAMEL_IMAP4_STATUS_UNSEEN }, -}; - - -void -camel_imap4_status_free (camel_imap4_status_t *status) -{ - camel_imap4_status_attr_t *attr, *next; - - attr = status->attr_list; - while (attr != NULL) { - next = attr->next; - g_free (attr); - attr = next; - } - - g_free (status->mailbox); - g_free (status); -} - - -int -camel_imap4_untagged_status (CamelIMAP4Engine *engine, CamelIMAP4Command *ic, guint32 index, camel_imap4_token_t *token, CamelException *ex) -{ - camel_imap4_status_attr_t *attr, *tail, *list = NULL; - GPtrArray *array = ic->user_data; - camel_imap4_status_t *status; - char *mailbox; - size_t len; - int type; - int i; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - switch (token->token) { - case CAMEL_IMAP4_TOKEN_ATOM: - mailbox = g_strdup (token->v.atom); - break; - case CAMEL_IMAP4_TOKEN_QSTRING: - mailbox = g_strdup (token->v.qstring); - break; - case CAMEL_IMAP4_TOKEN_LITERAL: - if (camel_imap4_engine_literal (engine, (unsigned char **) &mailbox, &len, ex) == -1) - return -1; - break; - default: - fprintf (stderr, "Unexpected token in IMAP4 untagged STATUS response: %s%c\n", - token->token == CAMEL_IMAP4_TOKEN_NIL ? "NIL" : "", - (unsigned char) (token->token & 0xff)); - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - return -1; - } - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) { - g_free (mailbox); - return -1; - } - - if (token->token != '(') { - d(fprintf (stderr, "Expected to find a '(' token after the mailbox token in the STATUS response\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - g_free (mailbox); - return -1; - } - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) { - g_free (mailbox); - return -1; - } - - tail = (camel_imap4_status_attr_t *) &list; - - while (token->token == CAMEL_IMAP4_TOKEN_ATOM) { - /* parse the status messages list */ - type = CAMEL_IMAP4_STATUS_UNKNOWN; - for (i = 0; i < G_N_ELEMENTS (imap4_status); i++) { - if (!g_ascii_strcasecmp (imap4_status[i].name, token->v.atom)) { - type = imap4_status[i].type; - break; - } - } - - if (type == CAMEL_IMAP4_STATUS_UNKNOWN) - fprintf (stderr, "unrecognized token in STATUS list: %s\n", token->v.atom); - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - - if (token->token != CAMEL_IMAP4_TOKEN_NUMBER) - break; - - attr = g_new (camel_imap4_status_attr_t, 1); - attr->next = NULL; - attr->type = type; - attr->value = token->v.number; - - tail->next = attr; - tail = attr; - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - goto exception; - } - - status = g_new (camel_imap4_status_t, 1); - status->mailbox = mailbox; - status->attr_list = list; - list = NULL; - - g_ptr_array_add (array, status); - - if (token->token != ')') { - d(fprintf (stderr, "Expected to find a ')' token terminating the untagged STATUS response\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - return -1; - } - - if (camel_imap4_engine_next_token (engine, token, ex) == -1) - return -1; - - if (token->token != '\n') { - d(fprintf (stderr, "Expected to find a '\\n' token after the STATUS response\n")); - camel_imap4_utils_set_unexpected_token_error (ex, engine, token); - return -1; - } - - return 0; - - exception: - - g_free (mailbox); - - attr = list; - while (attr != NULL) { - list = attr->next; - g_free (attr); - attr = list; - } - - return -1; -} diff --git a/camel/providers/imap4/camel-imap4-utils.h b/camel/providers/imap4/camel-imap4-utils.h deleted file mode 100644 index 1bb8b00962..0000000000 --- a/camel/providers/imap4/camel-imap4-utils.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Camel - * Copyright (C) 1999-2004 Jeffrey Stedfast - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - */ - - -#ifndef __CAMEL_IMAP4_UTILS_H__ -#define __CAMEL_IMAP4_UTILS_H__ - -#include <glib.h> - -#include <camel/camel-exception.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -/* IMAP4 flag merging */ -typedef struct { - guint32 changed; - guint32 bits; -} flags_diff_t; - -void camel_imap4_flags_diff (flags_diff_t *diff, guint32 old, guint32 new); -guint32 camel_imap4_flags_merge (flags_diff_t *diff, guint32 flags); -guint32 camel_imap4_merge_flags (guint32 original, guint32 local, guint32 server); - - -struct _CamelIMAP4Engine; -struct _CamelIMAP4Command; -struct _CamelFolderSummary; -struct _camel_imap4_token_t; -struct _CamelIMAP4StoreSummary; -struct _CamelIMAP4NamespaceList; -struct _CamelIMAP4Namespace; - -void camel_imap4_namespace_clear (struct _CamelIMAP4Namespace **ns); -struct _CamelIMAP4NamespaceList *camel_imap4_namespace_list_copy (const struct _CamelIMAP4NamespaceList *nsl); -void camel_imap4_namespace_list_free (struct _CamelIMAP4NamespaceList *nsl); - -char camel_imap4_get_path_delim (struct _CamelIMAP4StoreSummary *s, const char *full_name); - -int camel_imap4_get_uid_set (struct _CamelIMAP4Engine *engine, struct _CamelFolderSummary *summary, GPtrArray *infos, int cur, size_t linelen, char **set); - -void camel_imap4_utils_set_unexpected_token_error (CamelException *ex, struct _CamelIMAP4Engine *engine, struct _camel_imap4_token_t *token); - -int camel_imap4_parse_flags_list (struct _CamelIMAP4Engine *engine, guint32 *flags, CamelException *ex); - -/* Note: make sure these don't clash with any bit flags in camel-store.h */ -#define CAMEL_IMAP4_FOLDER_MARKED (1 << 17) -#define CAMEL_IMAP4_FOLDER_UNMARKED (1 << 18) - -typedef struct { - guint32 flags; - char delim; - char *name; -} camel_imap4_list_t; - -int camel_imap4_untagged_list (struct _CamelIMAP4Engine *engine, struct _CamelIMAP4Command *ic, - guint32 index, struct _camel_imap4_token_t *token, CamelException *ex); - - -enum { - CAMEL_IMAP4_STATUS_UNKNOWN, - CAMEL_IMAP4_STATUS_MESSAGES, - CAMEL_IMAP4_STATUS_RECENT, - CAMEL_IMAP4_STATUS_UIDNEXT, - CAMEL_IMAP4_STATUS_UIDVALIDITY, - CAMEL_IMAP4_STATUS_UNSEEN, -}; - -typedef struct _camel_imap4_status_attr { - struct _camel_imap4_status_attr *next; - guint32 type; - guint32 value; -} camel_imap4_status_attr_t; - -typedef struct { - camel_imap4_status_attr_t *attr_list; - char *mailbox; -} camel_imap4_status_t; - -void camel_imap4_status_free (camel_imap4_status_t *status); - -int camel_imap4_untagged_status (struct _CamelIMAP4Engine *engine, struct _CamelIMAP4Command *ic, - guint32 index, struct _camel_imap4_token_t *token, CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __CAMEL_IMAP4_UTILS_H__ */ diff --git a/camel/providers/imap4/libcamelimap4.urls b/camel/providers/imap4/libcamelimap4.urls deleted file mode 100644 index 7ccb0b0414..0000000000 --- a/camel/providers/imap4/libcamelimap4.urls +++ /dev/null @@ -1 +0,0 @@ -imap4 diff --git a/camel/providers/imapp/.cvsignore b/camel/providers/imapp/.cvsignore deleted file mode 100644 index 3fa8afaa38..0000000000 --- a/camel/providers/imapp/.cvsignore +++ /dev/null @@ -1,11 +0,0 @@ -.deps -Makefile -Makefile.in -.libs -.deps -*.lo -*.la -*.bb -*.bbg -*.da -*.gcov diff --git a/camel/providers/imapp/ChangeLog b/camel/providers/imapp/ChangeLog deleted file mode 100644 index 63b46ae57a..0000000000 --- a/camel/providers/imapp/ChangeLog +++ /dev/null @@ -1,22 +0,0 @@ -2004-11-11 Not Zed <NotZed@Ximian.com> - - * updates for camel folder summary api changes. - -2004-09-30 Not Zed <NotZed@Ximian.com> - - * camel-imapp-engine.c: make the build again, warnings, doesn't - work. - -2004-09-28 Not Zed <NotZed@Ximian.com> - - * camel-imapp-engine.c (camel_imapp_engine_command_free): assume - the command isn't in a list now. - (cie_worker): worker thread code. - - * camel-imapp-engine.h: make the imappcommand a - message. - -2004-09-28 Not Zed <NotZed@Ximian.com> - - * added new changelog. - diff --git a/camel/providers/imapp/Makefile.am b/camel/providers/imapp/Makefile.am deleted file mode 100644 index 8260c58670..0000000000 --- a/camel/providers/imapp/Makefile.am +++ /dev/null @@ -1,40 +0,0 @@ -## Process this file with automake to produce Makefile.in - -camel_provider_LTLIBRARIES = libcamelimapp.la -camel_provider_DATA = libcamelimapp.urls - -INCLUDES = -I.. \ - -I$(srcdir)/.. \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/e-util \ - -I$(top_srcdir) \ - $(CAMEL_CFLAGS) \ - $(GNOME_INCLUDEDIR) \ - $(GTK_INCLUDEDIR) \ - -DG_LOG_DOMAIN=\"camel-imapp-provider\" - -libcamelimapp_la_SOURCES = \ - camel-imapp-utils.c \ - camel-imapp-engine.c \ - camel-imapp-stream.c \ - camel-imapp-store.c \ - camel-imapp-folder.c \ - camel-imapp-provider.c \ - camel-imapp-store-summary.c \ - camel-imapp-driver.c \ - camel-imapp-summary.c - -noinst_HEADERS = \ - camel-imapp-utils.h \ - camel-imapp-engine.h \ - camel-imapp-stream.h \ - camel-imapp-store.h \ - camel-imapp-folder.h \ - camel-imapp-store-summary.h \ - camel-imapp-driver.h \ - camel-imapp-summary.h - -libcamelimapp_la_LDFLAGS = -avoid-version -module - -EXTRA_DIST = libcamelimapp.urls diff --git a/camel/providers/imapp/camel-imapp-driver.c b/camel/providers/imapp/camel-imapp-driver.c deleted file mode 100644 index c9a9e45042..0000000000 --- a/camel/providers/imapp/camel-imapp-driver.c +++ /dev/null @@ -1,953 +0,0 @@ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <ctype.h> - -#include "camel-imapp-driver.h" -#include "camel-imapp-utils.h" -#include "camel-imapp-folder.h" -#include "camel-imapp-engine.h" -#include "camel-imapp-summary.h" -#include "camel-imapp-exception.h" - -#include <camel/camel-stream-mem.h> -#include <camel/camel-stream-null.h> - -#include <camel/camel-folder-summary.h> -#include <camel/camel-store.h> -#include <camel/camel-mime-utils.h> -#include <camel/camel-sasl.h> - -#define d(x) x - -static int driver_resp_fetch(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata); -static int driver_resp_expunge(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata); -static int driver_resp_exists(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata); -static int driver_resp_list(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata); - -static void driver_status(CamelIMAPPEngine *ie, struct _status_info *sinfo, CamelIMAPPDriver *sdata); - -static void -class_init(CamelIMAPPDriverClass *ieclass) -{ -} - -static void -object_init(CamelIMAPPDriver *ie, CamelIMAPPDriverClass *ieclass) -{ - ie->summary = g_ptr_array_new(); - e_dlist_init(&ie->body_fetch); - e_dlist_init(&ie->body_fetch_done); -} - -static void -object_finalise(CamelIMAPPDriver *ie, CamelIMAPPDriverClass *ieclass) -{ - if (ie->folder) - camel_object_unref((CamelObject *)ie->folder); - if (ie->engine) - camel_object_unref((CamelObject *)ie->engine); - if (ie->summary) - g_ptr_array_free(ie->summary, TRUE); -} - -CamelType -camel_imapp_driver_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register ( - camel_object_get_type (), - "CamelIMAPPDriver", - sizeof (CamelIMAPPDriver), - sizeof (CamelIMAPPDriverClass), - (CamelObjectClassInitFunc) class_init, - NULL, - (CamelObjectInitFunc) object_init, - (CamelObjectFinalizeFunc) object_finalise); - } - - return type; -} - -CamelIMAPPDriver * -camel_imapp_driver_new(CamelIMAPPStream *stream) -{ - CamelIMAPPDriver *driver; - CamelIMAPPEngine *ie; - - driver = CAMEL_IMAPP_DRIVER (camel_object_new (CAMEL_IMAPP_DRIVER_TYPE)); - ie = driver->engine = camel_imapp_engine_new(stream); - - camel_imapp_engine_add_handler(ie, "FETCH", (CamelIMAPPEngineFunc)driver_resp_fetch, driver); - camel_imapp_engine_add_handler(ie, "EXPUNGE", (CamelIMAPPEngineFunc)driver_resp_expunge, driver); - camel_imapp_engine_add_handler(ie, "EXISTS", (CamelIMAPPEngineFunc)driver_resp_exists, driver); - camel_imapp_engine_add_handler(ie, "LIST", (CamelIMAPPEngineFunc)driver_resp_list, driver); - camel_object_hook_event(ie, "status", (CamelObjectEventHookFunc)driver_status, driver); - - return driver; -} - -void -camel_imapp_driver_set_sasl_factory(CamelIMAPPDriver *id, CamelIMAPPSASLFunc get_sasl, void *sasl_data) -{ - id->get_sasl = get_sasl; - id->get_sasl_data = sasl_data; -} - -void -camel_imapp_driver_set_login_query(CamelIMAPPDriver *id, CamelIMAPPLoginFunc get_login, void *login_data) -{ - id->get_login = get_login; - id->get_login_data = login_data; -} - -void -camel_imapp_driver_login(CamelIMAPPDriver *id) -/* throws SERVICE_CANT_AUTHENTICATE, SYSTEM_IO */ -{ - CamelIMAPPCommand * volatile ic = NULL; - - /* connect? */ - /* camel_imapp_engine_connect() */ - /* or above? */ - - CAMEL_TRY { - CamelSasl *sasl; - - if (id->get_sasl - && (sasl = id->get_sasl(id, id->get_sasl_data))) { - ic = camel_imapp_engine_command_new(id->engine, "AUTHENTICATE", NULL, "AUTHENTICATE %A", sasl); - camel_object_unref(sasl); - } else { - char *user, *pass; - - g_assert(id->get_login); - id->get_login(id, &user, &pass, id->get_login_data); - ic = camel_imapp_engine_command_new(id->engine, "LOGIN", NULL, "LOGIN %s %s", user, pass); - g_free(user); - g_free(pass); - } - - camel_imapp_engine_command_queue(id->engine, ic); - while (camel_imapp_engine_iterate(id->engine, ic) > 0) - ; - - if (ic->status->result != IMAP_OK) - camel_exception_throw(CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, "Login failed: %s", ic->status->text); - camel_imapp_engine_command_free(id->engine, ic); - } CAMEL_CATCH(ex) { - if (ic) - camel_imapp_engine_command_free(id->engine, ic); - camel_exception_throw_ex(ex); - } CAMEL_DONE; -} - -void -camel_imapp_driver_select(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder) -{ - CamelIMAPPCommand * volatile ic = NULL; - CamelIMAPPCommand * volatile ic2 = NULL; - guint32 count; - CamelFolderSummary *summary; - - if (id->folder) { - if (folder == id->folder) - return; - camel_imapp_driver_sync(id, FALSE, id->folder); - if (camel_folder_change_info_changed(id->folder->changes)) { - camel_object_trigger_event(id->folder, "folder_changed", id->folder->changes); - camel_folder_change_info_clear(id->folder->changes); - } - camel_object_unref(id->folder); - id->folder = NULL; - } - - summary = ((CamelFolder *)folder)->summary; - - ic = camel_imapp_engine_command_new(id->engine, "SELECT", NULL, "SELECT %t", folder->raw_name); - camel_imapp_engine_command_queue(id->engine, ic); - while (camel_imapp_engine_iterate(id->engine, ic)>0) - ; - camel_imapp_engine_command_free(id->engine, ic); - - id->folder = folder; - camel_object_ref(folder); - - count = camel_folder_summary_count(summary); - if (count > 0 && count <= id->exists) { - ic = camel_imapp_engine_command_new(id->engine, "FETCH", NULL, - "FETCH 1:%u (UID FLAGS)", count); - camel_imapp_engine_command_queue(id->engine, ic); - if (count < id->exists) { - ic2 = camel_imapp_engine_command_new(id->engine, "FETCH", NULL, - "FETCH %u:* (UID FLAGS ENVELOPE)", count+1); - camel_imapp_engine_command_queue(id->engine, ic2); - } else { - ic2 = NULL; - } - - while (camel_imapp_engine_iterate(id->engine, ic2?ic2:ic)>0) - ; - - camel_imapp_engine_command_free(id->engine, ic); - if (ic2) - camel_imapp_engine_command_free(id->engine, ic2); - } else { - ic = camel_imapp_engine_command_new(id->engine, "FETCH", NULL, - "FETCH 1:* (UID FLAGS ENVELOPE)"); - camel_imapp_engine_command_queue(id->engine, ic); - while (camel_imapp_engine_iterate(id->engine, ic)>0) - ; - camel_imapp_engine_command_free(id->engine, ic); - } - - /* TODO: need to set exists/etc in summary */ - folder->exists = id->exists; - folder->uidvalidity = id->uidvalidity; - - printf("saving summary '%s'\n", summary->summary_path); - camel_folder_summary_save(summary); - - if (camel_folder_change_info_changed(id->folder->changes)) { - camel_object_trigger_event(id->folder, "folder_changed", id->folder->changes); - camel_folder_change_info_clear(id->folder->changes); - } -} - -static void -imapp_driver_check(CamelIMAPPDriver *id) -{ - guint32 count; - CamelIMAPPCommand *ic; - - /* FIXME: exception handling */ - - if (id->folder->exists != id->exists) { - count = camel_folder_summary_count(((CamelFolder *)id->folder)->summary); - if (count < id->exists) { - printf("fetching new messages\n"); - ic = camel_imapp_engine_command_new(id->engine, "FETCH", NULL, - "FETCH %u:* (UID FLAGS ENVELOPE)", count+1); - camel_imapp_engine_command_queue(id->engine, ic); - while (camel_imapp_engine_iterate(id->engine, ic)>0) - ; - camel_imapp_engine_command_free(id->engine, ic); - } else if (count > id->exists) { - printf("folder shrank with no expunge notificaitons!? uh, dunno what to do\n"); - } - } - - printf("checking for change info changes\n"); - if (camel_folder_change_info_changed(id->folder->changes)) { - printf("got somechanges! added=%d changed=%d removed=%d\n", - id->folder->changes->uid_added->len, - id->folder->changes->uid_changed->len, - id->folder->changes->uid_removed->len); - camel_object_trigger_event(id->folder, "folder_changed", id->folder->changes); - camel_folder_change_info_clear(id->folder->changes); - } -} - -void -camel_imapp_driver_update(CamelIMAPPDriver *id, CamelIMAPPFolder *folder) -{ - if (id->folder == folder) { - CamelIMAPPCommand *ic; - - /* this will automagically update flags & expunge items */ - ic = camel_imapp_engine_command_new(id->engine, "NOOP", NULL, "NOOP"); - camel_imapp_engine_command_queue(id->engine, ic); - while (camel_imapp_engine_iterate(id->engine, ic)>0) - ; - camel_imapp_engine_command_free(id->engine, ic); - - imapp_driver_check(id); - } else { - camel_imapp_driver_select(id, folder); - } -} - -/* FIXME: this is basically a copy of the same in camel-imapp-utils.c */ -static struct { - char *name; - guint32 flag; -} flag_table[] = { - { "\\ANSWERED", CAMEL_MESSAGE_ANSWERED }, - { "\\DELETED", CAMEL_MESSAGE_DELETED }, - { "\\DRAFT", CAMEL_MESSAGE_DRAFT }, - { "\\FLAGGED", CAMEL_MESSAGE_FLAGGED }, - { "\\SEEN", CAMEL_MESSAGE_SEEN }, - /* { "\\RECENT", CAMEL_IMAPP_MESSAGE_RECENT }, */ -}; - -/* - flags 00101000 - sflags 01001000 - ^ 01100000 -~flags 11010111 -& 01000000 - -&flags 00100000 -*/ - -static void -imapp_write_flags(CamelIMAPPDriver *id, guint32 orset, gboolean on, CamelFolderSummary *summary) -{ - guint32 i, j, count; - CamelIMAPPMessageInfo *info; - CamelIMAPPCommand *ic = NULL; - struct _uidset_state ss; - GSList *commands = NULL; - - /* FIXME: exception handling */ - - count = camel_folder_summary_count(summary); - for (j=0;j<sizeof(flag_table)/sizeof(flag_table[0]);j++) { - int flush; - - if ((orset & flag_table[j].flag) == 0) - continue; - - printf("checking/storing %s flags '%s'\n", on?"on":"off", flag_table[j].name); - - flush = 0; - imapp_uidset_init(&ss, id->engine); - for (i=0;i<count;i++) { - info = (CamelIMAPPMessageInfo *)camel_folder_summary_index(summary, i); - if (info) { - guint32 flags = info->info.flags & CAMEL_IMAPP_SERVER_FLAGS; - guint32 sflags = info->server_flags & CAMEL_IMAPP_SERVER_FLAGS; - - if ( (on && (((flags ^ sflags) & flags) & flag_table[j].flag)) - || (!on && (((flags ^ sflags) & ~flags) & flag_table[j].flag))) { - if (ic == NULL) - ic = camel_imapp_engine_command_new(id->engine, "STORE", NULL, "UID STORE "); - flush = imapp_uidset_add(&ss, ic, camel_message_info_uid(info)); - } - camel_message_info_free((CamelMessageInfo *)info); - } - - if (i == count-1 && ic != NULL) - flush |= imapp_uidset_done(&ss, ic); - - if (flush) { - flush = 0; - camel_imapp_engine_command_add(id->engine, ic, " %tFLAGS.SILENT (%t)", on?"+":"-", flag_table[j].name); - camel_imapp_engine_command_queue(id->engine, ic); - commands = g_slist_prepend(commands, ic); - ic = NULL; - } - } - } - - /* flush off any requests we may have outstanding */ - /* TODO: for max benefit, should have this routine do both on and off flags in one go */ - while (commands) { - GSList *next = commands->next; - - ic = commands->data; - g_slist_free_1(commands); - commands = next; - - while (camel_imapp_engine_iterate(id->engine, ic)>0) - ; - camel_imapp_engine_command_free(id->engine, ic); - } -} - -void -camel_imapp_driver_sync(CamelIMAPPDriver *id, gboolean expunge, CamelIMAPPFolder *folder) -{ - CamelFolderSummary *summary; - guint i, count, on_orset, off_orset; - CamelIMAPPMessageInfo *info; - CamelIMAPPCommand *ic; - - /* FIXME: exception handling */ - - camel_imapp_driver_update(id, folder); - - summary = ((CamelFolder *)folder)->summary; - count = camel_folder_summary_count(summary); - /* find out which flags have turned on, which have tunred off */ - off_orset = on_orset = 0; - for (i=0;i<count;i++) { - guint32 flags, sflags; - - info = (CamelIMAPPMessageInfo *)camel_folder_summary_index(summary, i); - if (info == NULL) - continue; - flags = info->info.flags & CAMEL_IMAPP_SERVER_FLAGS; - sflags = info->server_flags & CAMEL_IMAPP_SERVER_FLAGS; - if (flags != sflags) { - off_orset |= ( flags ^ sflags ) & ~flags; - on_orset |= (flags ^ sflags) & flags; - } - camel_message_info_free((CamelMessageInfo *)info); - } - - if (on_orset || off_orset) { - /* turn on or off all messages matching */ - if (on_orset) - imapp_write_flags(id, on_orset, TRUE, summary); - if (off_orset) - imapp_write_flags(id, off_orset, FALSE, summary); - - /* success (no exception), make sure we match what we're supposed to */ - for (i=0;i<count;i++) { - info = (CamelIMAPPMessageInfo *)camel_folder_summary_index(summary, i); - if (info == NULL) - continue; - info->server_flags = info->info.flags & CAMEL_IMAPP_SERVER_FLAGS; - camel_message_info_free((CamelMessageInfo *)info); - } - camel_folder_summary_touch(summary); - /* could save summary here, incase of failure? */ - } - - if (expunge) { - ic = camel_imapp_engine_command_new(id->engine, "EXPUNGE", NULL, "EXPUNGE"); - camel_imapp_engine_command_queue(id->engine, ic); - while (camel_imapp_engine_iterate(id->engine, ic)>0) - ; - camel_imapp_engine_command_free(id->engine, ic); - } - - printf("saving summary '%s'\n", summary->summary_path); - camel_folder_summary_save(summary); - - if (camel_folder_change_info_changed(id->folder->changes)) { - camel_object_trigger_event(id->folder, "folder_changed", id->folder->changes); - camel_folder_change_info_clear(id->folder->changes); - } -} - -#if 0 -static void -fetch_data_free(CamelIMAPPFetch *fd) -{ - if (fd->body) - camel_object_unref(fd->body); - camel_object_unref(fd->folder); - g_free(fd->uid); - g_free(fd->section); - g_free(fd); -} -#endif - -struct _CamelStream * camel_imapp_driver_fetch(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder, const char *uid, const char *body) -{ - return NULL; -} - -#if 0 -void -camel_imapp_driver_fetch(CamelIMAPPDriver *id, CamelIMAPPFolder *folder, const char *uid, const char *section, CamelIMAPPFetchFunc done, void *data) -{ - struct _fetch_data *fd; - CamelIMAPPCommand *ic; - - fd = g_malloc0(sizeof(*fd)); - fd->folder = folder; - camel_object_ref(folder); - fd->uid = g_strdup(uid); - fd->section = g_strdup(fd->section); - fd->done = done; - fd->data = data; - - e_dlist_addtail(&id->body_fetch, (EDListNode *)&fd); - - CAMEL_TRY { - camel_imapp_driver_select(id, folder); - - ic = camel_imapp_engine_command_new(id->engine, "FETCH", NULL, "UID FETCH %t (BODY.PEEK[%t])", uid, section); - camel_imapp_engine_command_queue(id->engine, ic); - while (camel_imapp_engine_iterate(id->engine, ic)>0) - ; - camel_imapp_engine_command_free(id->engine, ic); - imapp_driver_check(id); - } CAMEL_CATCH(e) { - /* FIXME: do exception properly */ - } CAMEL_DONE; - - e_dlist_remove((EDListNode *)&fd); - - return fd.data; -} -#endif - -GPtrArray * -camel_imapp_driver_list(CamelIMAPPDriver *id, const char *name, guint32 flags) -{ - CamelIMAPPCommand * volatile ic; - GPtrArray *res; - - g_assert(id->list_commands == NULL); - g_assert(id->list_result == NULL); - - /* FIXME: make sure we only have a single list running at a time */ - /* sem_wait(id->list_sem); */ - - /* FIXME: namespace stuff (done in store code?) */ - - /* FIXME: if name != "", we need to also do list "name.%" (. == sep) */ - - id->list_result = g_ptr_array_new(); - id->list_flags = flags; - CAMEL_TRY { - ic = camel_imapp_engine_command_new(id->engine, "LIST", NULL, "LIST \"\" %f", name[0]?name:"%"); - camel_imapp_engine_command_queue(id->engine, ic); - while (ic) { - while (camel_imapp_engine_iterate(id->engine, ic)>0) - ; - camel_imapp_engine_command_free(id->engine, ic); - - if (id->list_commands) { - GSList *top = id->list_commands; - - id->list_commands = top->next; - ic = top->data; - g_slist_free_1(top); - } else { - ic = NULL; - } - } - } CAMEL_CATCH(e) { - GSList *top = id->list_commands; - int i; - - camel_imapp_engine_command_free(id->engine, ic); - - while (top) { - GSList *topn = top->next; - - camel_imapp_engine_command_free(id->engine, ic); - g_slist_free_1(top); - top = topn; - } - id->list_commands = NULL; - - res = id->list_result; - for (i=0;i<res->len;i++) - imap_free_list(res->pdata[i]); - g_ptr_array_free(res, TRUE); - id->list_result = NULL; - - camel_exception_throw_ex(e); - } CAMEL_DONE; - - res = id->list_result; - id->list_result = NULL; - - /* sem_post(id->list_sem); */ - - return res; -} - -static int -driver_resp_list(CamelIMAPPEngine *ie, guint32 idx, CamelIMAPPDriver *id) -{ - struct _list_info *linfo; - - /* FIXME: exceptions */ - - linfo = imap_parse_list(ie->stream); - printf("store list: '%s' ('%c')\n", linfo->name, linfo->separator); - if (id->list_result) { - if ((linfo->flags & CAMEL_FOLDER_NOINFERIORS) == 0 - && (id->list_flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) - && linfo->separator) { - int depth = 0; - char *p = linfo->name; - char c = linfo->separator; - - /* this is expensive ... but if we've listed this deep we're going slow anyway */ - while (*p && depth < 10) { - if (*p == c) - depth++; - p++; - } - - if (depth < 10 - && (linfo->name[0] == 0 || linfo->name[strlen(linfo->name)-1] != c)) { - CamelIMAPPCommand *ic; - - ic = camel_imapp_engine_command_new(id->engine, "LIST", NULL, "LIST \"\" %t%c%%", linfo->name, c); - id->list_commands = g_slist_prepend(id->list_commands, ic); - camel_imapp_engine_command_queue(id->engine, ic); - } - } - /* FIXME: dont add to list if name ends in separator */ - g_ptr_array_add(id->list_result, linfo); - } else { - g_warning("unexpected list response\n"); - imap_free_list(linfo); - } - - return camel_imapp_engine_skip(ie); -} - -/* ********************************************************************** */ - -static void -driver_status(CamelIMAPPEngine *ie, struct _status_info *sinfo, CamelIMAPPDriver *sdata) -{ - printf("got status response ...\n"); - switch(sinfo->condition) { - case IMAP_READ_WRITE: - printf("folder is read-write\n"); - break; - case IMAP_READ_ONLY: - printf("folder is read-only\n"); - break; - case IMAP_UIDVALIDITY: - sdata->uidvalidity = sinfo->u.uidvalidity; - break; -#if 0 - /* not defined yet ... */ - case IMAP_UIDNEXT: - printf("got uidnext for folder: %d\n", sinfo->u.uidnext); - break; -#endif - case IMAP_UNSEEN: - sdata->unseen = sinfo->u.unseen; - break; - case IMAP_PERMANENTFLAGS: - sdata->permanentflags = sinfo->u.permanentflags; - break; - case IMAP_ALERT: - printf("ALERT!: %s\n", sinfo->text); - break; - case IMAP_PARSE: - printf("PARSE: %s\n", sinfo->text); - break; - default: - break; - } -} - -static int -driver_resp_exists(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata) -{ - /* should this be an event instead? */ - - sdata->exists = id; - - return camel_imapp_engine_skip(ie); -} - -static int -driver_resp_expunge(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata) -{ - printf("got expunge response %u\n", id); - if (sdata->folder != NULL) { - CamelMessageInfo *info; - CamelFolderSummary *summary = ((CamelFolder *)sdata->folder)->summary; - - info = camel_folder_summary_index(summary, id-1); - if (info) { - printf("expunging msg %d\n", id); - camel_folder_summary_remove(summary, info); - camel_message_info_free(info); - camel_folder_change_info_remove_uid(sdata->folder->changes, camel_message_info_uid(info)); - } else { - printf("can not find msg %u from expunge\n", id); - } - } - - return camel_imapp_engine_skip(ie); -} - -static int -driver_resp_fetch(CamelIMAPPEngine *ie, guint32 id, CamelIMAPPDriver *sdata) -{ - struct _fetch_info *finfo = NULL; - CamelIMAPPMessageInfo *info, *uinfo; - unsigned int i; - CamelFolderSummary *summary; - - printf("got fetch response %d\n", id); - - if (sdata->folder == NULL) - goto done; - - summary = ((CamelFolder *)sdata->folder)->summary; - - finfo = imap_parse_fetch(ie->stream); - imap_dump_fetch(finfo); - - info = (CamelIMAPPMessageInfo *)camel_folder_summary_index(summary, id-1); - if (info == NULL) { - if (finfo->uid == NULL) { - printf("got fetch response for currently unknown message %u\n", id); - goto done; - } - uinfo = (CamelIMAPPMessageInfo *)camel_folder_summary_uid(summary, finfo->uid); - if (uinfo) { - /* we have a problem ... index mismatch */ - printf("index mismatch, uid '%s' not at index '%u'\n", - finfo->uid, id); - camel_message_info_free(uinfo); - } - /* pad out the summary till we have enough indexes */ - for (i=camel_folder_summary_count(summary);i<id;i++) { - info = camel_message_info_new(summary); - if (i == id-1) { - printf("inserting new info @ %u\n", i); - info->info.uid = g_strdup(finfo->uid); - } else { - char uidtmp[32]; - - sprintf(uidtmp, "blank-%u", i); - info->info.uid = g_strdup(uidtmp); - printf("inserting empty uid %s\n", uidtmp); - } - - camel_folder_summary_add(summary, (CamelMessageInfo *)info); - } - info = (CamelIMAPPMessageInfo *)camel_folder_summary_index(summary, id-1); - g_assert(info != NULL); - } else { - if (finfo->uid) { - /* FIXME: need to handle blank-* uids, somehow */ - while (info && strcmp(camel_message_info_uid(info), finfo->uid) != 0) { - printf("index mismatch, uid '%s' not at index '%u', got '%s' instead (removing)\n", - finfo->uid, id, camel_message_info_uid(info)); - - camel_folder_change_info_remove_uid(sdata->folder->changes, camel_message_info_uid(info)); - camel_folder_summary_remove(summary, (CamelMessageInfo *)info); - camel_message_info_free(info); - info = (CamelIMAPPMessageInfo *)camel_folder_summary_index(summary, id-1); - } - } else { - printf("got info for unknown message %u\n", id); - } - } - - if (info) { - if (finfo->got & FETCH_MINFO) { - /* if we only use ENVELOPE? */ - info->info.subject = g_strdup(camel_message_info_subject(finfo->minfo)); - info->info.from = g_strdup(camel_message_info_from(finfo->minfo)); - info->info.to = g_strdup(camel_message_info_to(finfo->minfo)); - info->info.cc = g_strdup(camel_message_info_cc(finfo->minfo)); - info->info.date_sent = camel_message_info_date_sent(finfo->minfo); - camel_folder_change_info_add_uid(sdata->folder->changes, camel_message_info_uid(info)); - printf("adding change info uid '%s'\n", camel_message_info_uid(info)); - } - - if (finfo->got & FETCH_FLAGS) { - if ((info->info.flags & CAMEL_IMAPP_SERVER_FLAGS) != (camel_message_info_flags(finfo) & CAMEL_IMAPP_SERVER_FLAGS)) { - camel_folder_change_info_change_uid(sdata->folder->changes, camel_message_info_uid(info)); - info->info.flags = (info->info.flags & ~(CAMEL_IMAPP_SERVER_FLAGS)) | (camel_message_info_flags(finfo) & CAMEL_IMAPP_SERVER_FLAGS); - camel_folder_summary_touch(summary); - } - ((CamelIMAPPMessageInfo *)info)->server_flags = finfo->flags & CAMEL_IMAPP_SERVER_FLAGS; - } - - if ((finfo->got & (FETCH_BODY|FETCH_UID)) == (FETCH_BODY|FETCH_UID)) { - CamelIMAPPFetch *fd, *fn; - - fd = (CamelIMAPPFetch *)sdata->body_fetch.head; - fn = fd->next; - while (fn) { - if (!strcmp(finfo->uid, fd->uid) && !strcmp(finfo->section, fd->section)) { - fd->done(sdata, fd); - e_dlist_remove((EDListNode *)fd); - e_dlist_addtail(&sdata->body_fetch_done, (EDListNode *)fd); - break; - } - fd = fn; - fn = fn->next; - } - } - - camel_message_info_free(info); - } else { - printf("dont know what to do with message\n"); - } - done: - imap_free_fetch(finfo); - - return camel_imapp_engine_skip(ie); -} - - -/* This code is for the separate thread per server idea */ - -typedef enum { - CAMEL_IMAPP_MSG_FETCH, - CAMEL_IMAPP_MSG_LIST, - CAMEL_IMAPP_MSG_QUIT, - CAMEL_IMAPP_MSG_SEARCH, - CAMEL_IMAPP_MSG_SYNC, - CAMEL_IMAPP_MSG_UPDATE, -} camel_imapp_msg_t; - -typedef struct _CamelIMAPPMsg CamelIMAPPMsg; - -struct _CamelIMAPPMsg { - EMsg msg; - CamelOperation *cancel; - CamelException *ex; - camel_imapp_msg_t type; - union { - struct { - struct _CamelIMAPPFolder *folder; - char *uid; - char *section; - struct _CamelStream *body; - struct _CamelIMAPPCommand *ic; - } fetch; - struct { - char *name; - guint32 flags; - GPtrArray *result; - GSList *ics; - } list; - struct { - guint32 flags; - } quit; - struct { - struct _CamelIMAPPFolder *folder; - char *search; - GPtrArray *results; - } search; - struct { - struct _CamelIMAPPFolder *folder; - guint32 flags; - } sync; - struct { - struct _CamelIMAPPFolder *folder; - } update; - } data; -}; - -CamelIMAPPMsg *camel_imapp_msg_new(camel_imapp_msg_t type, struct _CamelException *ex, struct _CamelOperation *cancel, ...); -void camel_imapp_msg_free(CamelIMAPPMsg *m); -void camel_imapp_driver_worker(CamelIMAPPDriver *id); - -CamelIMAPPMsg * -camel_imapp_msg_new(camel_imapp_msg_t type, struct _CamelException *ex, struct _CamelOperation *cancel, ...) -{ - CamelIMAPPMsg *m; - va_list ap; - - m = g_malloc0(sizeof(*m)); - m->type = type; - m->cancel = cancel; - camel_operation_ref(cancel); - m->ex = ex; - - va_start(ap, cancel); - switch (type) { - case CAMEL_IMAPP_MSG_FETCH: - m->data.fetch.folder = va_arg(ap, struct _CamelIMAPPFolder *); - camel_object_ref(m->data.fetch.folder); - m->data.fetch.uid = g_strdup(va_arg(ap, char *)); - m->data.fetch.section = g_strdup(va_arg(ap, char *)); - break; - case CAMEL_IMAPP_MSG_LIST: - m->data.list.name = g_strdup(va_arg(ap, char *)); - m->data.list.flags = va_arg(ap, guint32); - break; - case CAMEL_IMAPP_MSG_QUIT: - m->data.quit.flags = va_arg(ap, guint32); - break; - case CAMEL_IMAPP_MSG_SEARCH: - m->data.search.folder = va_arg(ap, struct _CamelIMAPPFolder *); - camel_object_ref(m->data.search.folder); - m->data.search.search = g_strdup(va_arg(ap, char *)); - break; - case CAMEL_IMAPP_MSG_SYNC: - m->data.sync.folder = va_arg(ap, struct _CamelIMAPPFolder *); - camel_object_ref(m->data.sync.folder); - m->data.sync.flags = va_arg(ap, guint32); - break; - case CAMEL_IMAPP_MSG_UPDATE: - m->data.update.folder = va_arg(ap, struct _CamelIMAPPFolder *); - camel_object_ref(m->data.update.folder); - break; - } - va_end(ap); - - return m; -} - -void -camel_imapp_msg_free(CamelIMAPPMsg *m) -{ - switch (m->type) { - case CAMEL_IMAPP_MSG_FETCH: - camel_object_unref(m->data.fetch.folder); - g_free(m->data.fetch.uid); - g_free(m->data.fetch.section); - - if (m->data.fetch.body) - camel_object_unref(m->data.fetch.body); - break; - case CAMEL_IMAPP_MSG_LIST: - g_free(m->data.list.name); - if (m->data.list.result) - /* FIXME: free list data ... */ - g_ptr_array_free(m->data.list.result, TRUE); - break; - case CAMEL_IMAPP_MSG_QUIT: - break; - case CAMEL_IMAPP_MSG_SEARCH: - camel_object_unref(m->data.search.folder); - g_free(m->data.search.search); - if (m->data.search.results) - /* FIXME: free search data */ - g_ptr_array_free(m->data.search.results, TRUE); - break; - case CAMEL_IMAPP_MSG_SYNC: - camel_object_unref(m->data.sync.folder); - break; - case CAMEL_IMAPP_MSG_UPDATE: - camel_object_unref(m->data.update.folder); - break; - } - - camel_operation_unref(m->cancel); - g_free(m); -} - -void -camel_imapp_driver_worker(CamelIMAPPDriver *id) -{ - CamelIMAPPMsg *m; - int go = TRUE; - - do { - /*m = (CamelIMAPPMsg *)e_msgport_get(id->queue);*/ - switch (m->type) { - case CAMEL_IMAPP_MSG_FETCH: - /*e_dlist_addtail(&id->fetch_queue, (EDListNode *)m);*/ - camel_imapp_driver_select(id, m->data.fetch.folder); - break; - case CAMEL_IMAPP_MSG_LIST: - m->data.list.result = camel_imapp_driver_list(id, m->data.list.name, m->data.list.flags); - break; - case CAMEL_IMAPP_MSG_QUIT: - camel_imapp_msg_free(m); - go = FALSE; - break; - case CAMEL_IMAPP_MSG_SEARCH: - break; - case CAMEL_IMAPP_MSG_SYNC: - break; - case CAMEL_IMAPP_MSG_UPDATE: - break; - } - } while (go); -} - diff --git a/camel/providers/imapp/camel-imapp-driver.h b/camel/providers/imapp/camel-imapp-driver.h deleted file mode 100644 index 2ecdfe634b..0000000000 --- a/camel/providers/imapp/camel-imapp-driver.h +++ /dev/null @@ -1,100 +0,0 @@ - -#ifndef _CAMEL_IMAPP_DRIVER_H -#define _CAMEL_IMAPP_DRIVER_H - -#include <camel/camel-object.h> -#include "camel-imapp-stream.h" -#include <libedataserver/e-msgport.h> - -#define CAMEL_IMAPP_DRIVER_TYPE (camel_imapp_driver_get_type ()) -#define CAMEL_IMAPP_DRIVER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAPP_DRIVER_TYPE, CamelIMAPPDriver)) -#define CAMEL_IMAPP_DRIVER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAPP_DRIVER_TYPE, CamelIMAPPDriverClass)) -#define CAMEL_IS_IMAP_DRIVER(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAPP_DRIVER_TYPE)) - -typedef struct _CamelIMAPPDriver CamelIMAPPDriver; -typedef struct _CamelIMAPPDriverClass CamelIMAPPDriverClass; - -typedef struct _CamelIMAPPFetch CamelIMAPPFetch; - -typedef int (*CamelIMAPPDriverFunc)(struct _CamelIMAPPDriver *driver, void *data); -typedef struct _CamelSasl * (*CamelIMAPPSASLFunc)(struct _CamelIMAPPDriver *driver, void *data); -typedef void (*CamelIMAPPLoginFunc)(struct _CamelIMAPPDriver *driver, char **login, char **pass, void *data); - -typedef void (*CamelIMAPPFetchFunc)(struct _CamelIMAPPDriver *driver, CamelIMAPPFetch *); - -struct _CamelIMAPPFetch { - struct _CamelIMAPPFetch *next; - struct _CamelIMAPPFetch *prev; - - CamelStream *body; /* the content fetched */ - - struct _CamelIMAPPFolder *folder; - char *uid; - char *section; - - CamelIMAPPFetchFunc done; - void *data; -}; - -struct _CamelMimeMessage; - -struct _CamelIMAPPDriver { - CamelObject parent_object; - - struct _CamelIMAPPEngine *engine; - - struct _CamelIMAPPFolder *folder; - - /* current folder stuff */ - GPtrArray *summary; - guint32 uidvalidity; - guint32 exists; - guint32 recent; - guint32 unseen; - guint32 permanentflags; - - /* list stuff */ - GPtrArray *list_result; - GSList *list_commands; - guint32 list_flags; - - /* sem_t list_sem; for controlled access to list variables */ - - /* this is so the node is always in a list - easier exception management */ - EDList body_fetch; - EDList body_fetch_done; - - /* factory to get an appropriate sasl mech */ - CamelIMAPPSASLFunc get_sasl; - void *get_sasl_data; - - /* callbacks, get login username/pass */ - CamelIMAPPLoginFunc get_login; - void *get_login_data; -}; - -struct _CamelIMAPPDriverClass { - CamelObjectClass parent_class; -}; - -CamelType camel_imapp_driver_get_type (void); - -CamelIMAPPDriver * camel_imapp_driver_new(CamelIMAPPStream *stream); - -void camel_imapp_driver_set_sasl_factory(CamelIMAPPDriver *id, CamelIMAPPSASLFunc get_sasl, void *sasl_data); -void camel_imapp_driver_set_login_query(CamelIMAPPDriver *id, CamelIMAPPLoginFunc get_login, void *login_data); - -void camel_imapp_driver_login(CamelIMAPPDriver *id); - -void camel_imapp_driver_select(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder); -void camel_imapp_driver_update(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder); -void camel_imapp_driver_sync(CamelIMAPPDriver *id, gboolean expunge, struct _CamelIMAPPFolder *folder); - -struct _CamelStream * camel_imapp_driver_fetch(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder, const char *uid, const char *body); - -GPtrArray * camel_imapp_driver_list(CamelIMAPPDriver *id, const char *name, guint32 flags); - -struct _CamelStream *camel_imapp_driver_get(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder, const char *uid); -void camel_imapp_driver_append(CamelIMAPPDriver *id, struct _CamelIMAPPFolder *folder, struct _CamelDataWrapper *); - -#endif diff --git a/camel/providers/imapp/camel-imapp-engine.c b/camel/providers/imapp/camel-imapp-engine.c deleted file mode 100644 index 1eaa4b8025..0000000000 --- a/camel/providers/imapp/camel-imapp-engine.c +++ /dev/null @@ -1,1154 +0,0 @@ - -#include "config.h" - -#include <stdio.h> -#include <string.h> - -#include "camel-imapp-engine.h" -#include "camel-imapp-stream.h" -#include "camel-imapp-utils.h" -#include "camel-imapp-exception.h" - -#include <camel/camel-folder-summary.h> -#include <camel/camel-stream-mem.h> -#include <camel/camel-stream-null.h> -#include <camel/camel-data-wrapper.h> -#include <camel/camel-sasl.h> - -#include <ctype.h> - -#define e(x) -#define c(x) /* command build debug */ - -static void imap_engine_command_addv(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic, const char *fmt, va_list ap); -static void imap_engine_command_complete(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic); - -struct _handler { - CamelIMAPPEngineFunc func; - void *data; - char name[1]; -}; - -static void -class_init(CamelIMAPPEngineClass *ieclass) -{ - ieclass->tagprefix = 'A'; - - camel_object_class_add_event((CamelObjectClass *)ieclass, "status", NULL); -} - -static void -object_init(CamelIMAPPEngine *ie, CamelIMAPPEngineClass *ieclass) -{ - ie->handlers = g_hash_table_new(g_str_hash, g_str_equal); - e_dlist_init(&ie->active); - e_dlist_init(&ie->done); - - ie->port = e_msgport_new(); - - ie->tagprefix = ieclass->tagprefix; - ieclass->tagprefix++; - if (ieclass->tagprefix > 'Z') - ieclass->tagprefix = 'A'; - ie->tagprefix = 'A'; - - ie->state = IMAP_ENGINE_DISCONNECT; -} - -static void -handler_free(void *key, void *mem, void *data) -{ - g_free(mem); -} - -static void -object_finalise(CamelIMAPPEngine *ie, CamelIMAPPEngineClass *ieclass) -{ - /* FIXME: need to free the commands ... */ - while (camel_imapp_engine_iterate(ie, NULL) > 0) - ; - - g_hash_table_foreach(ie->handlers, (GHFunc)handler_free, NULL); - g_hash_table_destroy(ie->handlers); -} - -CamelType -camel_imapp_engine_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register ( - camel_object_get_type (), - "CamelIMAPPEngine", - sizeof (CamelIMAPPEngine), - sizeof (CamelIMAPPEngineClass), - (CamelObjectClassInitFunc) class_init, - NULL, - (CamelObjectInitFunc) object_init, - (CamelObjectFinalizeFunc) object_finalise); - } - - return type; -} - -/* FIXME: check this, just taken from old code, not rfc */ -struct { - char *name; - guint32 flag; -} capa_table[] = { - { "IMAP4", IMAP_CAPABILITY_IMAP4 }, - { "IMAP4REV1", IMAP_CAPABILITY_IMAP4REV1 }, - { "STATUS", IMAP_CAPABILITY_STATUS } , - { "NAMESPACE", IMAP_CAPABILITY_NAMESPACE }, - { "UIDPLUS", IMAP_CAPABILITY_UIDPLUS }, - { "LITERAL+", IMAP_CAPABILITY_LITERALPLUS }, - { "STARTTLS", IMAP_CAPABILITY_STARTTLS }, -}; - - -/* -capability_data ::= "CAPABILITY" SPACE [1#capability SPACE] "IMAP4rev1" - [SPACE 1#capability] - ;; IMAP4rev1 servers which offer RFC 1730 - ;; compatibility MUST list "IMAP4" as the first - ;; capability. -*/ -static int resp_capability(CamelIMAPPEngine *ie, guint32 id, void *data) -{ - int tok, len, i; - unsigned char *token, *p, c; - - /* FIXME: handle auth types */ - - printf("got capability response:\n"); - while (1) { - tok = camel_imapp_stream_token(ie->stream, &token, &len); - switch(tok) { - case IMAP_TOK_TOKEN: - p = token; - while ((c = *p)) - *p++ = toupper(c); - case IMAP_TOK_INT: - printf(" cap: '%s'\n", token); - for (i=0;i<(int)(sizeof(capa_table)/sizeof(capa_table[0]));i++) - if (strcmp(token, capa_table[i].name)) - ie->capa |= capa_table[i].flag; - break; - case '\n': - return 0; - case IMAP_TOK_ERROR: - case IMAP_TOK_PROTOCOL: - camel_imapp_engine_skip(ie); - return -1; - default: - printf("Unknown Response token %02x '%c'\n", tok, isprint(tok)?tok:'.'); - } - } while (tok != '\n'); - - return 0; -} - -/* expunge command, id is expunged seq number */ -/* message_data ::= nz_number SPACE ("EXPUNGE" / - ("FETCH" SPACE msg_att)) */ -static int resp_expunge(CamelIMAPPEngine *ie, guint32 id, void *data) -{ - printf("message expunged: %d\n", id); - - return camel_imapp_engine_skip(ie); -} - -static int resp_flags(CamelIMAPPEngine *ie, guint32 id, void *data) -{ - guint32 flags; - - imap_parse_flags(ie->stream, &flags); - - printf("flags: %08x\n", flags); - - return camel_imapp_engine_skip(ie); -} - -/* exists count */ -static int resp_exists(CamelIMAPPEngine *ie, guint32 id, void *data) -{ - printf("messages exist: %d\n", id); - - if (ie->select_response) - ie->select_response->exists = id; - - return camel_imapp_engine_skip(ie); -} - -static int resp_recent(CamelIMAPPEngine *ie, guint32 id, void *data) -{ - printf("messages recent: %d\n", id); - - if (ie->select_response) - ie->select_response->recent = id; - - return camel_imapp_engine_skip(ie); -} - -static int resp_fetch(CamelIMAPPEngine *ie, guint32 id, void *data) -{ - struct _fetch_info *finfo; - - finfo = imap_parse_fetch(ie->stream); - imap_dump_fetch(finfo); - imap_free_fetch(finfo); - - return camel_imapp_engine_skip(ie); -} - -#if 0 -static int resp_list(CamelIMAPPEngine *ie, guint32 id, void *data) -{ - struct _list_info *linfo; - - linfo = imap_parse_list(ie->stream); - printf("list: '%s' (%c)\n", linfo->name, linfo->separator); - imap_free_list(linfo); - - return camel_imapp_engine_skip(ie); -} -#endif - -CamelIMAPPEngine * -camel_imapp_engine_new(CamelIMAPPStream *stream) -{ - CamelIMAPPEngine * volatile engine; - - engine = CAMEL_IMAPP_ENGINE (camel_object_new (CAMEL_IMAPP_ENGINE_TYPE)); - engine->stream = stream; - camel_object_ref((CamelObject *)stream); - - camel_imapp_engine_add_handler(engine, "CAPABILITY", resp_capability, engine); - - /* mailbox_data */ - camel_imapp_engine_add_handler(engine, "FLAGS", (CamelIMAPPEngineFunc)resp_flags, engine); - camel_imapp_engine_add_handler(engine, "EXISTS", (CamelIMAPPEngineFunc)resp_exists, engine); - camel_imapp_engine_add_handler(engine, "RECENT", (CamelIMAPPEngineFunc)resp_recent, engine); - -#if 0 - camel_imapp_engine_add_handler(engine, "LIST", (CamelIMAPPEngineFunc)resp_list, engine); - camel_imapp_engine_add_handler(engine, "LSUB", (CamelIMAPPEngineFunc)resp_list, engine); -#endif - /* message_data */ - camel_imapp_engine_add_handler(engine, "EXPUNGE", (CamelIMAPPEngineFunc)resp_expunge, engine); - camel_imapp_engine_add_handler(engine, "FETCH", (CamelIMAPPEngineFunc)resp_fetch, engine); - - /* TODO: move this to a driver:connect call? */ - CAMEL_TRY { - unsigned char *token; - unsigned int len; - int tok; - - tok = camel_imapp_stream_token(stream, &token, &len); - if (tok == '*') { - struct _status_info *sinfo = imap_parse_status(stream); - - switch (sinfo->result) { - case IMAP_OK: - engine->state = IMAP_ENGINE_CONNECT; - printf("Server connected ok: %s\n", sinfo->text); - break; - case IMAP_PREAUTH: - printf("pre-authenticated ...\n"); - engine->state = IMAP_ENGINE_AUTH; - break; - default: - imap_free_status(sinfo); - camel_exception_throw(1, "Server refused connection: %s", sinfo->text); - break; - } - imap_free_status(sinfo); - } else { - engine->state = IMAP_ENGINE_CONNECT; - printf("unknwon server greeting, ignored\n"); - camel_imapp_engine_skip(engine); - } - camel_imapp_engine_capabilities(engine); - } CAMEL_CATCH(ex) { - printf("connection failed: %s\n", ex->desc); - camel_object_unref((CamelObject *)engine); - engine = NULL; - } CAMEL_DONE; - - return engine; -} - -void -camel_imapp_engine_add_handler(CamelIMAPPEngine *imap, const char *response, CamelIMAPPEngineFunc func, void *data) -{ - struct _handler *h; - const unsigned char *p; - unsigned char *o, c; - - h = g_malloc0(sizeof(*h) + strlen(response)); - h->func = func; - h->data = data; - - p = response; - o = h->name; - while ((c = *p++)) - *o++ = toupper(c); - *o = 0; - - g_hash_table_insert(imap->handlers, h->name, h); -} - -int -camel_imapp_engine_capabilities(CamelIMAPPEngine *ie) -{ - CamelIMAPPCommand *ic; - - /* reset capabilities */ - ie->capa = 0; - - ic = camel_imapp_engine_command_new(ie, "CAPABILITY", NULL, "CAPABILITY"); - camel_imapp_engine_command_queue(ie, ic); - while (camel_imapp_engine_iterate(ie, ic)>0) - ; - camel_imapp_engine_command_free(ie, ic); - - return 0; -} - -/* skip the rest of the line of tokens */ -int -camel_imapp_engine_skip(CamelIMAPPEngine *imap) -{ - int tok; - unsigned char *token; - unsigned int len; - - do { - tok = camel_imapp_stream_token(imap->stream, &token, &len); - if (tok == IMAP_TOK_LITERAL) { - camel_imapp_stream_set_literal(imap->stream, len); - while ((tok = camel_imapp_stream_getl(imap->stream, &token, &len)) > 0) { - printf("Skip literal data '%.*s'\n", (int)len, token); - } - } - } while (tok != '\n' && tok >= 0); - - if (tok < 0) - return -1; - - return 0; -} - -/* handle any untagged responses */ -static int -iterate_untagged(CamelIMAPPEngine *imap) -{ - unsigned int id, len; - unsigned char *token, *p, c; - int tok; - struct _handler *h; - struct _status_info *sinfo; - - e(printf("got untagged response\n")); - id = 0; - tok = camel_imapp_stream_token(imap->stream, &token, &len); - if (tok == IMAP_TOK_INT) { - id = strtoul(token, NULL, 10); - tok = camel_imapp_stream_token(imap->stream, &token, &len); - } - - if (tok == '\n') - camel_exception_throw(1, "truncated server response"); - - e(printf("Have token '%s' id %d\n", token, id)); - p = token; - while ((c = *p)) - *p++ = toupper(c); - - /* first, check for generic unsolicited response */ - h = g_hash_table_lookup(imap->handlers, token); - if (h) { - tok = h->func(imap, id, h->data); - if (tok < 0) - return tok; - return 1; - } - - /* TODO: apart from bye/preauth, these could be callbacks/events? */ - - /* now, check for status responses */ - switch (imap_tokenise(token, len)) { - case IMAP_BYE: - case IMAP_OK: - case IMAP_NO: - case IMAP_BAD: - case IMAP_PREAUTH: - /* TODO: validate which ones of these can happen as unsolicited responses */ - /* TODO: handle bye/preauth differently */ - /* FIXME: free sinfo */ - camel_imapp_stream_ungettoken(imap->stream, tok, token, len); - sinfo = imap_parse_status(imap->stream); - camel_object_trigger_event(imap, "status", sinfo); - imap_free_status(sinfo); -#if 0 - switch(sinfo->condition) { - case IMAP_READ_WRITE: - printf("folder is read-write\n"); - break; - case IMAP_READ_ONLY: - printf("folder is read-only\n"); - break; - case IMAP_UIDVALIDITY: - if (imap->select_response) - imap->select_response->uidvalidity = sinfo->u.uidvalidity; - break; -#if 0 - /* not defined yet ... */ - case IMAP_UIDNEXT: - printf("got uidnext for folder: %d\n", sinfo->u.uidnext); - break; -#endif - case IMAP_UNSEEN: - if (imap->select_response) - imap->select_response->unseen = sinfo->u.unseen; - break; - case IMAP_PERMANENTFLAGS: - if (imap->select_response) - imap->select_response->permanentflags = sinfo->u.permanentflags; - break; - case IMAP_ALERT: - printf("ALERT!: %s\n", sinfo->text); - break; - case IMAP_PARSE: - printf("PARSE: %s\n", sinfo->text); - break; - default: - break; - } -#endif - break; - default: - printf("unknown token: %s\n", token); - camel_imapp_engine_skip(imap); - /* unknown response, just ignore it */ - } - - return 1; -} - -/* handle any continuation requests - either data continuations, or auth continuation */ -static int -iterate_continuation(CamelIMAPPEngine *imap) -{ - CamelIMAPPCommand *ic; - CamelIMAPPCommandPart *cp; - - printf("got continuation response\n"); - - ic = imap->literal; - imap->literal = NULL; - if (ic == NULL) { - camel_imapp_engine_skip(imap); - printf("got continuation response with no outstanding continuation requests?\n"); - return 1; - } - - printf("got continuation response for data\n"); - cp = ic->current; - switch(cp->type & CAMEL_IMAPP_COMMAND_MASK) { - case CAMEL_IMAPP_COMMAND_DATAWRAPPER: - printf("writing data wrapper to literal\n"); - camel_data_wrapper_write_to_stream((CamelDataWrapper *)cp->ob, (CamelStream *)imap->stream); - break; - case CAMEL_IMAPP_COMMAND_STREAM: - printf("writing stream to literal\n"); - camel_stream_write_to_stream((CamelStream *)cp->ob, (CamelStream *)imap->stream); - break; - case CAMEL_IMAPP_COMMAND_AUTH: { - CamelException *ex = camel_exception_new(); - char *resp; - unsigned char *token; - int tok, len; - - tok = camel_imapp_stream_token(imap->stream, &token, &len); - resp = camel_sasl_challenge_base64((CamelSasl *)cp->ob, token, ex); - if (camel_exception_is_set(ex)) - camel_exception_throw_ex(ex); - camel_exception_free(ex); - - printf("got auth continuation, feeding token '%s' back to auth mech\n", resp); - - camel_stream_write((CamelStream *)imap->stream, resp, strlen(resp)); - - /* we want to keep getting called until we get a status reponse from the server - ignore what sasl tells us */ - imap->literal = ic; - - break; } - default: - /* should we just ignore? */ - camel_exception_throw(1, "continuation response for non-continuation request"); - } - - camel_imapp_engine_skip(imap); - - cp = cp->next; - if (cp->next) { - ic->current = cp; - printf("next part of command \"A%05u: %s\"\n", ic->tag, cp->data); - camel_stream_printf((CamelStream *)imap->stream, "%s\r\n", cp->data); - if (cp->type & CAMEL_IMAPP_COMMAND_CONTINUATION) { - imap->literal = ic; - } else { - g_assert(cp->next->next == NULL); - } - } else { - printf("%p: queueing continuation\n", ic); - camel_stream_printf((CamelStream *)imap->stream, "\r\n"); - } - - if (imap->literal == NULL) { - ic = (CamelIMAPPCommand *)e_dlist_remhead(&imap->queue); - if (ic) { - printf("found outstanding op, queueing\n"); - camel_imapp_engine_command_queue(imap, ic); - } - } - - return 1; -} - -/* handle a completion line */ -static int -iterate_completion(CamelIMAPPEngine *imap, unsigned char *token) -{ - CamelIMAPPCommand *ic; - unsigned int tag; - - if (token[0] != imap->tagprefix) - camel_exception_throw(1, "Server sent unexpected response: %s", token); - - tag = strtoul(token+1, NULL, 10); - ic = camel_imapp_engine_command_find_tag(imap, tag); - if (ic) { - printf("Got completion response for command %05u '%s'\n", ic->tag, ic->name); - printf("%p: removing command from qwueue, we were at '%s'\n", ic, ic->current->data); - printf("%p: removing command\n", ic); - e_dlist_remove((EDListNode *)ic); - e_dlist_addtail(&imap->done, (EDListNode *)ic); - if (imap->literal == ic) - imap->literal = NULL; - ic->status = imap_parse_status(imap->stream); - printf("got response code: %s\n", ic->status->text); - - /* TODO: remove this stuff and use a completion handler? */ - /* TODO: handle 'SELECT' command cleanup here */ - /* FIXME: have this use tokeniser, have this handle close/logout/select etc as well */ - /* ok response from login/authenticate, then we're in happy land */ - if ((!strcmp(ic->name, "LOGIN") || !strcmp(ic->name, "AUTHENTICATE")) - && ic->status->result == IMAP_OK) - imap->state = IMAP_ENGINE_AUTH; - - if (ic->complete) - ic->complete(imap, ic, ic->complete_data); - } else { - camel_exception_throw(1, "got response tag unexpectedly: %s", token); - } - - if (imap->literal != NULL) { - printf("Warning: continuation command '%s' finished with outstanding continuation\n", imap->literal->name); - ic = imap->literal; - /* set the command complete with a failure code? */ - e_dlist_remove((EDListNode *)ic); - e_dlist_addtail(&imap->done, (EDListNode *)ic); - imap->literal = NULL; - } - - ic = (CamelIMAPPCommand *)e_dlist_remhead(&imap->queue); - if (ic) { - printf("found outstanding op, queueing\n"); - camel_imapp_engine_command_queue(imap, ic); - } - - return 1; -} - - -/* Do work if there's any to do */ -int -camel_imapp_engine_iterate(CamelIMAPPEngine *imap, CamelIMAPPCommand *icwait) -/* throws IO,PARSE exception */ -{ - unsigned int len; - unsigned char *token; - int tok; - - if ((icwait && icwait->status != NULL) || e_dlist_empty(&imap->active)) - return 0; - - /* handle exceptions here? */ - - /* lock here? */ - - tok = camel_imapp_stream_token(imap->stream, &token, &len); - if (tok == '*') - iterate_untagged(imap); - else if (tok == IMAP_TOK_TOKEN) - iterate_completion(imap, token); - else if (tok == '+') - iterate_continuation(imap); - else - camel_exception_throw(1, "unexpected server response: %s", token); - - if (e_dlist_empty(&imap->active)) - return 0; - - return 1; -} - -CamelIMAPPCommand * -camel_imapp_engine_command_new(CamelIMAPPEngine *imap, const char *name, const char *select, const char *fmt, ...) -{ - CamelIMAPPCommand *ic; - va_list ap; - - ic = g_malloc0(sizeof(*ic)); - ic->tag = imap->tag++; - ic->name = name; - ic->mem = (CamelStreamMem *)camel_stream_mem_new(); - ic->select = g_strdup(select); - e_dlist_init(&ic->parts); - - if (fmt && fmt[0]) { - va_start(ap, fmt); - imap_engine_command_addv(imap, ic, fmt, ap); - va_end(ap); - } - - return ic; -} - -void -camel_imapp_engine_command_add(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic, const char *fmt, ...) -{ - va_list ap; - - g_assert(ic->mem); /* gets reset on queue */ - - if (fmt && fmt[0]) { - va_start(ap, fmt); - imap_engine_command_addv(imap, ic, fmt, ap); - va_end(ap); - } -} - -void -camel_imapp_engine_command_complete(CamelIMAPPEngine *imap, struct _CamelIMAPPCommand *ic, CamelIMAPPCommandFunc func, void *data) -{ - ic->complete = func; - ic->complete_data = data; -} - -/* FIXME: make imap command's refcounted? */ -void -camel_imapp_engine_command_free (CamelIMAPPEngine *imap, CamelIMAPPCommand *ic) -{ - CamelIMAPPCommandPart *cp, *cn; - - if (ic == NULL) - return; - - /* Note the command must not be in any queue? */ - - if (ic->mem) - camel_object_unref((CamelObject *)ic->mem); - imap_free_status(ic->status); - g_free(ic->select); - - while ( (cp = ((CamelIMAPPCommandPart *)e_dlist_remhead(&ic->parts))) ) { - g_free(cp->data); - if (cp->ob) - camel_object_unref(cp->ob); - g_free(cp); - } - - g_free(ic); -} - -/* FIXME: error handling */ -void -camel_imapp_engine_command_queue(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic) -{ - CamelIMAPPCommandPart *cp; - - g_assert(ic->msg.reply_port); - - if (ic->mem) - imap_engine_command_complete(imap, ic); - - e_msgport_put(imap->port, (EMsg *)ic); -} - -CamelIMAPPCommand * -camel_imapp_engine_command_find (CamelIMAPPEngine *imap, const char *name) -{ - CamelIMAPPCommand *ic, *in; - - ic = imap->literal; - if (ic && strcmp(ic->name, name) == 0) - return ic; - - /* first, try active */ - ic = (CamelIMAPPCommand *)imap->active.head; - in = ic->msg.ln.next; - while (in) { - if (strcmp(ic->name, name) == 0) - return ic; - ic = in; - in = in->msg.ln.next; - } - - return NULL; -} - -CamelIMAPPCommand * -camel_imapp_engine_command_find_tag(CamelIMAPPEngine *imap, unsigned int tag) -{ - CamelIMAPPCommand *ic, *in; - - ic = imap->literal; - if (ic && ic->tag == tag) - return ic; - - ic = (CamelIMAPPCommand *)imap->active.head; - in = ic->msg.ln.next; - while (in) { - if (ic->tag == tag) - return ic; - ic = in; - in = in->msg.ln.next; - } - - return NULL; -} - -/* ********************************************************************** */ - -CamelIMAPPSelectResponse * -camel_imapp_engine_select(CamelIMAPPEngine *imap, const char *name) -{ - CamelIMAPPSelectResponse * volatile resp; - CamelIMAPPCommand * volatile ic = NULL; - - resp = g_malloc0(sizeof(*resp)); - imap->select_response = resp; - - CAMEL_TRY { - ic = camel_imapp_engine_command_new(imap, "SELECT", NULL, "SELECT %s", name); - camel_imapp_engine_command_queue(imap, ic); - while (camel_imapp_engine_iterate(imap, ic) > 0) - ; - - if (ic->status->result != IMAP_OK) - camel_exception_throw(1, "select failed: %s", ic->status->text); - resp->status = ic->status; - ic->status = NULL; - } CAMEL_CATCH (e) { - camel_imapp_engine_command_free(imap, ic); - camel_imapp_engine_select_free(imap, resp); - imap->select_response = NULL; - camel_exception_throw_ex(e); - } CAMEL_DONE; - - camel_imapp_engine_command_free(imap, ic); - imap->select_response = NULL; - - return resp; -} - -void -camel_imapp_engine_select_free(CamelIMAPPEngine *imap, CamelIMAPPSelectResponse *select) -{ - if (select) { - imap_free_status(select->status); - g_free(select); - } -} - -/* ********************************************************************** */ - -static void -imap_engine_command_add_part(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic, camel_imapp_command_part_t type, CamelObject *ob) -{ - CamelIMAPPCommandPart *cp; - CamelStreamNull *null; - unsigned int ob_size = 0; - - switch(type & CAMEL_IMAPP_COMMAND_MASK) { - case CAMEL_IMAPP_COMMAND_DATAWRAPPER: - case CAMEL_IMAPP_COMMAND_STREAM: - null = (CamelStreamNull *)camel_stream_null_new(); - if ( (type & CAMEL_IMAPP_COMMAND_MASK) == CAMEL_IMAPP_COMMAND_DATAWRAPPER) { - camel_data_wrapper_write_to_stream((CamelDataWrapper *)ob, (CamelStream *)null); - } else { - camel_stream_reset((CamelStream *)ob); - camel_stream_write_to_stream((CamelStream *)ob, (CamelStream *)null); - camel_stream_reset((CamelStream *)ob); - } - type |= CAMEL_IMAPP_COMMAND_CONTINUATION; - camel_object_ref(ob); - ob_size = null->written; - camel_object_unref((CamelObject *)null); - camel_stream_printf((CamelStream *)ic->mem, "{%u}", ob_size); - break; - case CAMEL_IMAPP_COMMAND_AUTH: - /* we presume we'll need to get additional data only if we're not authenticated yet */ - camel_object_ref(ob); - camel_stream_printf((CamelStream *)ic->mem, "%s", ((CamelSasl *)ob)->mech); - if (!camel_sasl_authenticated((CamelSasl *)ob)) - type |= CAMEL_IMAPP_COMMAND_CONTINUATION; - break; - default: - ob_size = 0; - } - - cp = g_malloc0(sizeof(*cp)); - cp->type = type; - cp->ob_size = ob_size; - cp->ob = ob; - cp->data_size = ic->mem->buffer->len; - cp->data = g_malloc(cp->data_size+1); - memcpy(cp->data, ic->mem->buffer->data, cp->data_size); - cp->data[cp->data_size] = 0; - - camel_stream_reset((CamelStream *)ic->mem); - /* FIXME: hackish? */ - g_byte_array_set_size(ic->mem->buffer, 0); - - e_dlist_addtail(&ic->parts, (EDListNode *)cp); -} - -#if c(!)0 -static int len(EDList *list) -{ - int count = 0; - EDListNode *n = list->head; - - while (n->next) { - n = n->next; - count++; - } - return count; -} -#endif - -static void -imap_engine_command_complete(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic) -{ - c(printf("completing command buffer is [%d] '%.*s'\n", ic->mem->buffer->len, (int)ic->mem->buffer->len, ic->mem->buffer->data)); - c(printf("command has %d parts\n", len(&ic->parts))); - if (ic->mem->buffer->len > 0) - imap_engine_command_add_part(imap, ic, CAMEL_IMAPP_COMMAND_SIMPLE, NULL); - - c(printf("command has %d parts\n", len(&ic->parts))); - - camel_object_unref((CamelObject *)ic->mem); - ic->mem = NULL; -} - -static void -imap_engine_command_addv(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic, const char *fmt, va_list ap) -{ - const unsigned char *p, *ps, *start; - unsigned char c; - unsigned int width; - char ch; - int llong; - int left; - int fill; - int zero; - char *s; - int d; - long int l; - guint32 f; - CamelStream *S; - CamelDataWrapper *D; - CamelSasl *A; - char buffer[16]; - - c(printf("adding command, fmt = '%s'\n", fmt)); - - p = fmt; - ps = fmt; - while ( ( c = *p++ ) ) { - switch(c) { - case '%': - if (*p == '%') { - camel_stream_write((CamelStream *)ic->mem, ps, p-ps); - p++; - ps = p; - } else { - camel_stream_write((CamelStream *)ic->mem, ps, p-ps-1); - start = p-1; - width = 0; - left = FALSE; - fill = FALSE; - zero = FALSE; - llong = FALSE; - - do { - c = *p++; - if (c == '0') - zero = TRUE; - else if ( c== '-') - left = TRUE; - else - break; - } while (c); - - do { - if (isdigit(c)) - width = width * 10 + (c-'0'); - else - break; - } while ((c = *p++)); - - if (c == 'l') { - llong = TRUE; - c = *p++; - } - - switch(c) { - case 'A': /* auth object - sasl auth, treat as special kind of continuation */ - A = va_arg(ap, CamelSasl *); - imap_engine_command_add_part(imap, ic, CAMEL_IMAPP_COMMAND_AUTH, (CamelObject *)A); - break; - case 'S': /* stream */ - S = va_arg(ap, CamelStream *); - c(printf("got stream '%p'\n", S)); - imap_engine_command_add_part(imap, ic, CAMEL_IMAPP_COMMAND_STREAM, (CamelObject *)S); - break; - case 'D': /* datawrapper */ - D = va_arg(ap, CamelDataWrapper *); - c(printf("got data wrapper '%p'\n", D)); - imap_engine_command_add_part(imap, ic, CAMEL_IMAPP_COMMAND_DATAWRAPPER, (CamelObject *)D); - break; - case 't': /* token */ - s = va_arg(ap, char *); - camel_stream_write((CamelStream *)ic->mem, s, strlen(s)); - break; - case 's': /* simple string */ - s = va_arg(ap, char *); - c(printf("got string '%s'\n", s)); - /* FIXME: escpae chars, convert to literal or literal+, etc */ - camel_stream_printf((CamelStream *)ic->mem, "\"%s\"", s); - break; - case 'f': /* imap folder name */ - s = va_arg(ap, char *); - c(printf("got folder '%s'\n", s)); - /* FIXME: encode folder name */ - /* FIXME: namespace? */ - camel_stream_printf((CamelStream *)ic->mem, "\"%s\"", s?s:""); - break; - case 'F': /* IMAP flags set */ - f = va_arg(ap, guint32); - imap_write_flags((CamelStream *)ic->mem, f); - break; - case 'c': - d = va_arg(ap, int); - ch = d; - camel_stream_write((CamelStream *)ic->mem, &ch, 1); - break; - case 'd': /* int/unsigned */ - case 'u': - if (llong) { - l = va_arg(ap, long int); - c(printf("got long int '%d'\n", (int)l)); - memcpy(buffer, start, p-start); - buffer[p-start] = 0; - camel_stream_printf((CamelStream *)ic->mem, buffer, l); - } else { - d = va_arg(ap, int); - c(printf("got int '%d'\n", d)); - memcpy(buffer, start, p-start); - buffer[p-start] = 0; - camel_stream_printf((CamelStream *)ic->mem, buffer, d); - } - break; - } - - ps = p; - } - break; - case '\\': /* only for \\ really, we dont support \n\r etc at all */ - c = *p; - if (c) { - g_assert(c == '\\'); - camel_stream_write((CamelStream *)ic->mem, ps, p-ps); - p++; - ps = p; - } - } - } - - camel_stream_write((CamelStream *)ic->mem, ps, p-ps-1); -} - - -static void * -cie_worker(void *data) -{ - CamelIMAPPCommand *ic = data; - CamelIMAPPEngine *imap; - CamelIMAPPCommandPart *cp; - - /* FIXME: remove select stuff */ - - /* see if we need to pre-queue a select command to select the right folder first */ - if (ic->select && (imap->last_select == NULL || strcmp(ic->select, imap->last_select) != 0)) { - CamelIMAPPCommand *select; - - /* of course ... we can't do anything like store/search if we have to select - first, because it'll mess up all the sequence numbers ... hrm ... bugger */ - - select = camel_imapp_engine_command_new(imap, "SELECT", NULL, "SELECT %s", ic->select); - g_free(imap->last_select); - imap->last_select = g_strdup(ic->select); - camel_imapp_engine_command_queue(imap, select); - /* how does it get freed? handle inside engine? */ - } - - /* first, check if command can be sent yet ... queue if not */ - if (imap->literal != NULL) { - printf("%p: queueing while literal active\n", ic); - e_dlist_addtail(&imap->queue, (EDListNode *)ic); - return; - } - - cp = (CamelIMAPPCommandPart *)ic->parts.head; - g_assert(cp); - ic->current = cp; - - /* how to handle exceptions here? */ - - printf("queueing command \"%c%05u %s\"\n", imap->tagprefix, ic->tag, cp->data); - camel_stream_printf((CamelStream *)imap->stream, "%c%05u %s\r\n", imap->tagprefix, ic->tag, cp->data); - - if (cp->type & CAMEL_IMAPP_COMMAND_CONTINUATION) { - printf("%p: active literal\n", ic); - g_assert(cp->next); - imap->literal = ic; - e_dlist_addtail(&imap->active, (EDListNode *)ic); - } else { - printf("%p: active non-literal\n", ic); - g_assert(cp->next && cp->next->next == NULL); - e_dlist_addtail(&imap->active, (EDListNode *)ic); - } -} - - -/* here temporarily while its experimental */ - - -#ifdef ENABLE_THREADS -#include <pthread.h> - -static pthread_key_t handler_key = 0; - -void camel_exception_setup(void) -{ - pthread_key_create(&handler_key, NULL); -} - -#else -/* this is per-thread in threaded mode */ -static struct _CamelExceptionEnv *handler = NULL; - -void camel_exception_setup(void) -{ -} -#endif - -void -camel_exception_try(struct _CamelExceptionEnv *env) -{ -#ifdef ENABLE_THREADS - struct _CamelExceptionEnv *handler; - - handler = pthread_getspecific(handler_key); -#endif - env->parent = handler; - handler = env; - env->ex = NULL; - -#ifdef ENABLE_THREADS - pthread_setspecific(handler_key, handler); -#endif -} - -void -camel_exception_throw_ex(CamelException *ex) -{ - struct _CamelExceptionEnv *env; -#ifdef ENABLE_THREADS - struct _CamelExceptionEnv *handler; - - handler = pthread_getspecific(handler_key); -#endif - printf("throwing exception '%s'\n", ex->desc); - - env = handler; - if (env != NULL) { - env->ex = ex; - handler = env->parent; -#ifdef ENABLE_THREADS - pthread_setspecific(handler_key, handler); -#endif - longjmp(env->env, ex->id); - } else { - g_warning("Uncaught exception: %s\n", ex->desc); - /* we just crash and burn, this is a code problem */ - /* we dont use g_assert_not_reached() since its not a noreturn function */ - abort(); - } -} - -void -camel_exception_throw(int id, char *fmt, ...) -{ - CamelException *ex; - va_list ap; - - ex = camel_exception_new(); - ex->id = id; - va_start(ap, fmt); - ex->desc = g_strdup_vprintf(fmt, ap); - va_end(ap); - - camel_exception_throw_ex(ex); -} - -void -camel_exception_drop(struct _CamelExceptionEnv *env) -{ -#ifdef ENABLE_THREADS - pthread_setspecific(handler_key, env->parent); -#else - handler = env->parent; -#endif -} - -void -camel_exception_done(struct _CamelExceptionEnv *env) -{ -#ifdef ENABLE_THREADS - pthread_setspecific(handler_key, env->parent); -#else - handler = env->parent; -#endif - if (env->ex != NULL) { - camel_exception_free(env->ex); - } -} diff --git a/camel/providers/imapp/camel-imapp-engine.h b/camel/providers/imapp/camel-imapp-engine.h deleted file mode 100644 index 2cc19cd21f..0000000000 --- a/camel/providers/imapp/camel-imapp-engine.h +++ /dev/null @@ -1,156 +0,0 @@ - -#ifndef _CAMEL_IMAPP_ENGINE_H -#define _CAMEL_IMAPP_ENGINE_H - -#include <camel/camel-object.h> - -#include "camel-imapp-stream.h" -#include <libedataserver/e-msgport.h> -#include "camel-imapp-folder.h" - -#define CAMEL_IMAPP_ENGINE_TYPE (camel_imapp_engine_get_type ()) -#define CAMEL_IMAPP_ENGINE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAPP_ENGINE_TYPE, CamelIMAPPEngine)) -#define CAMEL_IMAPP_ENGINE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAPP_ENGINE_TYPE, CamelIMAPPEngineClass)) -#define CAMEL_IS_IMAP_ENGINE(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAPP_ENGINE_TYPE)) - -typedef struct _CamelIMAPPEngine CamelIMAPPEngine; -typedef struct _CamelIMAPPEngineClass CamelIMAPPEngineClass; - -typedef struct _CamelIMAPPCommandPart CamelIMAPPCommandPart; -typedef struct _CamelIMAPPCommand CamelIMAPPCommand; - -typedef enum { - CAMEL_IMAPP_COMMAND_SIMPLE = 0, - CAMEL_IMAPP_COMMAND_DATAWRAPPER, - CAMEL_IMAPP_COMMAND_STREAM, - CAMEL_IMAPP_COMMAND_AUTH, - CAMEL_IMAPP_COMMAND_MASK = 0xff, - CAMEL_IMAPP_COMMAND_CONTINUATION = 0x8000 /* does this command expect continuation? */ -} camel_imapp_command_part_t; - -struct _CamelIMAPPCommandPart { - struct _CamelIMAPPCommandPart *next; - struct _CamelIMAPPCommandPart *prev; - - struct _CamelIMAPPCommand *parent; - - int data_size; - char *data; - - camel_imapp_command_part_t type; - - int ob_size; - CamelObject *ob; -}; - -typedef int (*CamelIMAPPEngineFunc)(struct _CamelIMAPPEngine *engine, guint32 id, void *data); -typedef void (*CamelIMAPPCommandFunc)(struct _CamelIMAPPEngine *engine, struct _CamelIMAPPCommand *, void *data); - -struct _CamelIMAPPCommand { - EMsg msg; - - const char *name; /* command name/type (e.g. FETCH) */ - - /* FIXME: remove this select stuff */ - char *select; /* if we need to run against a specific folder */ - struct _status_info *status; /* status for command, indicates it is complete if != NULL */ - - unsigned int tag; - - struct _CamelStreamMem *mem; /* for building the part */ - EDList parts; - CamelIMAPPCommandPart *current; - - CamelIMAPPCommandFunc complete; - void *complete_data; -}; - -typedef struct _CamelIMAPPSelectResponse CamelIMAPPSelectResponse; - -struct _CamelIMAPPSelectResponse { - struct _status_info *status; - guint32 exists; - guint32 recent; - guint32 uidvalidity; - guint32 unseen; - guint32 permanentflags; -}; - -enum { - IMAP_CAPABILITY_IMAP4 = (1 << 0), - IMAP_CAPABILITY_IMAP4REV1 = (1 << 1), - IMAP_CAPABILITY_STATUS = (1 << 2), - IMAP_CAPABILITY_NAMESPACE = (1 << 3), - IMAP_CAPABILITY_UIDPLUS = (1 << 4), - IMAP_CAPABILITY_LITERALPLUS = (1 << 5), - IMAP_CAPABILITY_STARTTLS = (1 << 6), -}; - -/* currently selected states */ -typedef enum _camel_imapp_engine_state_t { - IMAP_ENGINE_DISCONNECT, /* only happens during shutdown */ - IMAP_ENGINE_CONNECT, /* connected, not authenticated */ - IMAP_ENGINE_AUTH, /* connected, and authenticated */ - IMAP_ENGINE_SELECT, /* and selected, select holds selected folder */ -} camel_imapp_engine_state_t; - -struct _CamelIMAPPEngine { - CamelObject parent_object; - - /* incoming requests */ - EMsgPort *port; - - CamelIMAPPStream *stream; - - camel_imapp_engine_state_t state; - - guint32 capa; /* capabilities for this server, refresh with :capabilities() */ - - GHashTable *handlers; - - unsigned char tagprefix; /* out tag prefix 'A' 'B' ... 'Z' */ - unsigned int tag; /* next command tag */ - - char *select; /* *currently* selected folder */ - char *last_select; /* last selected or to-be selected folder (e.g. outstanding queued select) */ - CamelIMAPPCommand *literal;/* current literal op */ - EDList active; /* active queue */ - EDList queue; /* outstanding queue */ - EDList done; /* done queue, awaiting reclamation */ - - /* keep track of running a select */ - struct _CamelIMAPPSelectResponse *select_response; -}; - -struct _CamelIMAPPEngineClass { - CamelObjectClass parent_class; - - unsigned char tagprefix; - - /* Events: - status(struct _status_info *); - */ -}; - -CamelType camel_imapp_engine_get_type (void); - -CamelIMAPPEngine *camel_imapp_engine_new(CamelIMAPPStream *stream); - -void camel_imapp_engine_add_handler(CamelIMAPPEngine *imap, const char *response, CamelIMAPPEngineFunc func, void *data); -int camel_imapp_engine_iterate(CamelIMAPPEngine *imap, CamelIMAPPCommand *wait); /* throws PARSE,IO exception */ -int camel_imapp_engine_skip(CamelIMAPPEngine *imap); -int camel_imapp_engine_capabilities(CamelIMAPPEngine *imap); - -CamelIMAPPCommand *camel_imapp_engine_command_new (CamelIMAPPEngine *imap, const char *name, const char *select, const char *fmt, ...); -void camel_imapp_engine_command_complete(CamelIMAPPEngine *imap, struct _CamelIMAPPCommand *, CamelIMAPPCommandFunc func, void *data); -void camel_imapp_engine_command_add (CamelIMAPPEngine *imap, CamelIMAPPCommand *ic, const char *fmt, ...); -void camel_imapp_engine_command_free (CamelIMAPPEngine *imap, CamelIMAPPCommand *ic); -void camel_imapp_engine_command_queue(CamelIMAPPEngine *imap, CamelIMAPPCommand *ic); /* throws IO exception */ -CamelIMAPPCommand *camel_imapp_engine_command_find (CamelIMAPPEngine *imap, const char *name); -CamelIMAPPCommand *camel_imapp_engine_command_find_tag(CamelIMAPPEngine *imap, unsigned int tag); - -/* util functions */ -CamelIMAPPSelectResponse *camel_imapp_engine_select(CamelIMAPPEngine *imap, const char *name); -void camel_imapp_engine_select_free(CamelIMAPPEngine *imap, CamelIMAPPSelectResponse *select); - -#endif diff --git a/camel/providers/imapp/camel-imapp-exception.h b/camel/providers/imapp/camel-imapp-exception.h deleted file mode 100644 index 5e18b6c815..0000000000 --- a/camel/providers/imapp/camel-imapp-exception.h +++ /dev/null @@ -1,35 +0,0 @@ - -/* This implements 'real' exceptions that work a bit like c++/java exceptions */ - -/* Still experimental code */ - -#ifndef __CAMEL_IMAPP_EXCEPTION_H -#define __CAMEL_IMAPP_EXCEPTION_H - -#include <setjmp.h> -#include "camel/camel-exception.h" - -struct _CamelExceptionEnv { - struct _CamelExceptionEnv *parent; - CamelException *ex; - jmp_buf env; -}; - -#define CAMEL_TRY { struct _CamelExceptionEnv __env; camel_exception_try(&__env); if (setjmp(__env.env) == 0) -#define CAMEL_IGNORE camel_exception_done(&__env); } -#define CAMEL_CATCH(x) { CamelException *x; x=__env.ex; if (x != NULL) -#define CAMEL_DONE } camel_exception_done(&__env); } -#define CAMEL_DROP() camel_exception_drop(&__env) - -void camel_exception_setup(void); - -/* internal functions, use macro's above */ -void camel_exception_try(struct _CamelExceptionEnv *env); -void camel_exception_done(struct _CamelExceptionEnv *env); -void camel_exception_drop(struct _CamelExceptionEnv *env); - -/* user functions */ -void camel_exception_throw_ex(CamelException *ex) __attribute__ ((noreturn)); -void camel_exception_throw(int id, char *fmt, ...) __attribute__ ((noreturn)); - -#endif diff --git a/camel/providers/imapp/camel-imapp-fetch-stream.c b/camel/providers/imapp/camel-imapp-fetch-stream.c deleted file mode 100644 index bf18aac57b..0000000000 --- a/camel/providers/imapp/camel-imapp-fetch-stream.c +++ /dev/null @@ -1,183 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Author: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <stdio.h> -#include <ctype.h> -#include <errno.h> - -#include <glib.h> - -#include <camel/camel-stream-mem.h> - -#include "camel-imapp-stream.h" -#include "camel-imapp-exception.h" - -#define t(x) -#define io(x) x - -static CamelObjectClass *parent_class = NULL; - -/* Returns the class for a CamelStream */ -#define CS_CLASS(so) CAMEL_IMAPP_FETCH_STREAM_CLASS(CAMEL_OBJECT_GET_CLASS(so)) - -static ssize_t -stream_read(CamelStream *stream, char *buffer, size_t n) -{ - CamelIMAPPFetchStream *is = (CamelIMAPPFetchStream *)stream; - ssize_t max; - - /* make sure we have all the data read in */ - while (camel_imapp_engine_iterate(is->engine, is->command)>0) - ; - - if (is->literal == 0 || n == 0) - return 0; - - max = is->end - is->ptr; - if (max > 0) { - max = MIN(max, is->literal); - max = MIN(max, n); - memcpy(buffer, is->ptr, max); - is->ptr += max; - } else { - max = MIN(is->literal, n); - max = camel_stream_read(is->source, buffer, max); - if (max <= 0) - return max; - } - - is->literal -= max; - - return max; -} - -static ssize_t -stream_write(CamelStream *stream, const char *buffer, size_t n) -{ - CamelIMAPPFetchStream *is = (CamelIMAPPFetchStream *)stream; - - return camel_stream_write(is->source, buffer, n); -} - -static int -stream_close(CamelStream *stream) -{ - /* nop? */ - return 0; -} - -static int -stream_flush(CamelStream *stream) -{ - /* nop? */ - return 0; -} - -static gboolean -stream_eos(CamelStream *stream) -{ - CamelIMAPPFetchStream *is = (CamelIMAPPFetchStream *)stream; - - return is->literal == 0; -} - -static int -stream_reset(CamelStream *stream) -{ - /* nop? reset literal mode? */ - return 0; -} - -static void -camel_imapp_fetch_stream_class_init (CamelStreamClass *camel_imapp_fetch_stream_class) -{ - CamelStreamClass *camel_stream_class = (CamelStreamClass *)camel_imapp_fetch_stream_class; - - parent_class = camel_type_get_global_classfuncs( CAMEL_OBJECT_TYPE ); - - /* virtual method definition */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->close = stream_close; - camel_stream_class->flush = stream_flush; - camel_stream_class->eos = stream_eos; - camel_stream_class->reset = stream_reset; -} - -static void -camel_imapp_fetch_stream_init(CamelIMAPPFetchStream *is, CamelIMAPPFetchStreamClass *isclass) -{ - ; -} - -static void -camel_imapp_fetch_stream_finalise(CamelIMAPPFetchStream *is) -{ - if (is->engine) - camel_object_unref(is->engine); -} - -CamelType -camel_imapp_fetch_stream_get_type (void) -{ - static CamelType camel_imapp_fetch_stream_type = CAMEL_INVALID_TYPE; - - if (camel_imapp_fetch_stream_type == CAMEL_INVALID_TYPE) { - setup_table(); - camel_imapp_fetch_stream_type = camel_type_register( camel_stream_get_type(), - "CamelIMAPPFetchStream", - sizeof( CamelIMAPPFetchStream ), - sizeof( CamelIMAPPFetchStreamClass ), - (CamelObjectClassInitFunc) camel_imapp_fetch_stream_class_init, - NULL, - (CamelObjectInitFunc) camel_imapp_fetch_stream_init, - (CamelObjectFinalizeFunc) camel_imapp_fetch_stream_finalise ); - } - - return camel_imapp_fetch_stream_type; -} - -/** - * camel_imapp_fetch_stream_new: - * - * Return value: the stream - **/ -CamelStream * -camel_imapp_fetch_stream_new(CamelIMAPPEngine *ie, const char *uid, const char *body) -{ - CamelIMAPPFetchStream *is; - - is = (CamelIMAPPFetchStream *)camel_object_new(camel_imapp_fetch_stream_get_type ()); - is->engine = ie; - camel_object_ref(ie); - - is->command = camel_imapp_engine_command_new(ie, "FETCH", NULL, "FETCH %t (BODY[%t]<0.4096>", uid, body); - camel_imapp_engine_command_queue(ie, command); - - return (CamelStream *)is; -} - diff --git a/camel/providers/imapp/camel-imapp-fetch-stream.h b/camel/providers/imapp/camel-imapp-fetch-stream.h deleted file mode 100644 index c9281ff64f..0000000000 --- a/camel/providers/imapp/camel-imapp-fetch-stream.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_IMAPP_FETCH_STREAM_H -#define _CAMEL_IMAPP_FETCH_STREAM_H - -#include <camel/camel-stream.h> - -#define CAMEL_IMAPP_FETCH_STREAM(obj) CAMEL_CHECK_CAST (obj, camel_imapp_fetch_stream_get_type (), CamelIMAPPFetchStream) -#define CAMEL_IMAPP_FETCH_STREAM_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imapp_fetch_stream_get_type (), CamelIMAPPFetchStreamClass) -#define CAMEL_IS_IMAP_FETCH_STREAM(obj) CAMEL_CHECK_TYPE (obj, camel_imapp_fetch_stream_get_type ()) - -typedef struct _CamelIMAPPFetchStreamClass CamelIMAPPFetchStreamClass; -typedef struct _CamelIMAPPFetchStream CamelIMAPPFetchStream; - -struct _CamelIMAPPFetchStream { - CamelStream parent; - - struct _CamelIMAPPEngine *engine; -}; - -struct _CamelIMAPPFetchStreamClass { - CamelStreamClass parent_class; -}; - -CamelType camel_imapp_fetch_stream_get_type (void); - -CamelStream *camel_imapp_fetch_stream_new (struct _CamelIMAPPEngine *src, const char *uid, const char *spec); - -#endif /* ! _CAMEL_IMAPP_FETCH_STREAM_H */ diff --git a/camel/providers/imapp/camel-imapp-folder.c b/camel/providers/imapp/camel-imapp-folder.c deleted file mode 100644 index a838e7c6e4..0000000000 --- a/camel/providers/imapp/camel-imapp-folder.c +++ /dev/null @@ -1,271 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-folder.c : class for a imap folder */ - -/* - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <errno.h> - -#include "camel/camel-exception.h" -#include "camel/camel-stream-mem.h" -#include "camel/camel-stream-filter.h" -#include "camel/camel-mime-message.h" -#include "camel/camel-operation.h" -#include "camel/camel-data-cache.h" -#include "camel/camel-session.h" -#include "camel/camel-file-utils.h" - -#include "camel-imapp-store.h" -#include "camel-imapp-folder.h" -#include "camel-imapp-summary.h" -#include "camel-imapp-exception.h" - -#include <libedataserver/md5-utils.h> - -#include <stdlib.h> -#include <string.h> - -#define d(x) - -#define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(o))) -static CamelFolderClass *parent_class; - -static void imap_finalize (CamelObject *object); -static void imap_refresh_info (CamelFolder *folder, CamelException *ex); -static void imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex); -static CamelMimeMessage *imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex); - -static void -imap_folder_class_init (CamelIMAPPFolderClass *camel_imapp_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_imapp_folder_class); - - parent_class = CAMEL_FOLDER_CLASS(camel_folder_get_type()); - - /* virtual method overload */ - camel_folder_class->refresh_info = imap_refresh_info; - camel_folder_class->sync = imap_sync; - - camel_folder_class->get_message = imap_get_message; -} - -static void -imap_folder_init(CamelObject *o, CamelObjectClass *klass) -{ - CamelFolder *folder = (CamelFolder *)o; - CamelIMAPPFolder *ifolder = (CamelIMAPPFolder *)o; - - folder->folder_flags |= (CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | - CAMEL_FOLDER_HAS_SEARCH_CAPABILITY); - - folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | - CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_DRAFT | - CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_USER; - - /* FIXME: this is just a skeleton */ - - ifolder->changes = camel_folder_change_info_new(); -} - -CamelType -camel_imapp_folder_get_type (void) -{ - static CamelType camel_imapp_folder_type = CAMEL_INVALID_TYPE; - - if (!camel_imapp_folder_type) { - camel_imapp_folder_type = camel_type_register (CAMEL_FOLDER_TYPE, "CamelIMAPPFolder", - sizeof (CamelIMAPPFolder), - sizeof (CamelIMAPPFolderClass), - (CamelObjectClassInitFunc) imap_folder_class_init, - NULL, - imap_folder_init, - (CamelObjectFinalizeFunc) imap_finalize); - } - - return camel_imapp_folder_type; -} - -void -imap_finalize (CamelObject *object) -{ - CamelIMAPPFolder *folder = (CamelIMAPPFolder *)object; - - camel_folder_change_info_free(folder->changes); -} - -CamelFolder * -camel_imapp_folder_new(CamelStore *store, const char *path) -{ - CamelFolder *folder; - char *root; - - d(printf("opening imap folder '%s'\n", path)); - - folder = CAMEL_FOLDER (camel_object_new (CAMEL_IMAPP_FOLDER_TYPE)); - camel_folder_construct(folder, store, path, path); - - ((CamelIMAPPFolder *)folder)->raw_name = g_strdup(path); - - folder->summary = camel_imapp_summary_new(); - - root = camel_session_get_storage_path(((CamelService *)store)->session, (CamelService *)store, NULL); - if (root) { - char *base = g_build_filename(root, path, NULL); - char *file = g_build_filename(base, ".ev-summary", NULL); - - camel_mkdir(base, 0777); - g_free(base); - - camel_folder_summary_set_filename(folder->summary, file); - printf("loading summary from '%s' (root=%s)\n", file, root); - g_free(file); - camel_folder_summary_load(folder->summary); - g_free(root); - } - - return folder; -} - -#if 0 -/* experimental interfaces */ -void -camel_imapp_folder_open(CamelIMAPPFolder *folder, CamelException *ex) -{ - /* */ -} - -void -camel_imapp_folder_delete(CamelIMAPPFolder *folder, CamelException *ex) -{ -} - -void -camel_imapp_folder_rename(CamelIMAPPFolder *folder, const char *new, CamelException *ex) -{ -} - -void -camel_imapp_folder_close(CamelIMAPPFolder *folder, CamelException *ex) -{ -} -#endif - -static void -imap_refresh_info (CamelFolder *folder, CamelException *ex) -{ - printf("imapp refresh info?\n"); -} - -static void -imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) -{ - camel_imapp_driver_sync(((CamelIMAPPStore *)(folder->parent_store))->driver, expunge, (CamelIMAPPFolder *) folder); -} - -static CamelMimeMessage * -imap_get_message (CamelFolder *folder, const char *uid, CamelException *ex) -{ - CamelMimeMessage * volatile msg = NULL; - CamelStream * volatile stream = NULL; - - printf("get message '%s'\n", uid); - - CAMEL_TRY { - /* simple implementation, just get whole message in 1 go */ - stream = camel_imapp_driver_fetch(((CamelIMAPPStore *)(folder->parent_store))->driver, (CamelIMAPPFolder *)folder, uid, ""); - camel_stream_reset(stream); - msg = camel_mime_message_new(); - if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)msg, stream) != -1) { - /* do we care? */ - } - } CAMEL_CATCH(e) { - if (msg) - camel_object_unref(msg); - msg = NULL; - camel_exception_xfer(ex, e); - } CAMEL_DONE; - - if (stream) - camel_object_unref(stream); - - return msg; -} - - -/* Algorithm for selecting a folder: - - - If uidvalidity == old uidvalidity - and exsists == old exists - and recent == old recent - and unseen == old unseen - Assume our summary is correct - for each summary item - mark the summary item as 'old/not updated' - rof - fetch flags from 1:* - for each fetch response - info = summary[index] - if info.uid != uid - info = summary_by_uid[uid] - fi - if info == NULL - create new info @ index - fi - if got.flags - update flags - fi - if got.header - update based on header - mark as retrieved - else if got.body - update based on imap body - mark as retrieved - fi - - Async fetch response: - info = summary[index] - if info == null - if uid == null - force resync/select? - info = empty @ index - else if uid && info.uid != uid - force a resync? - return - fi - - if got.flags { - info.flags = flags - } - if got.header { - info.init(header) - info.empty = false - } - -info.state - 2 bit field in flags - 0 = empty, nothing set - 1 = uid & flags set - 2 = update required - 3 = up to date -*/ - diff --git a/camel/providers/imapp/camel-imapp-folder.h b/camel/providers/imapp/camel-imapp-folder.h deleted file mode 100644 index 329c66b7fc..0000000000 --- a/camel/providers/imapp/camel-imapp-folder.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-folder.h : Class for a IMAP folder */ - -/* - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_IMAPP_FOLDER_H -#define CAMEL_IMAPP_FOLDER_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include <camel/camel-folder.h> - -#define CAMEL_IMAPP_FOLDER_TYPE (camel_imapp_folder_get_type ()) -#define CAMEL_IMAPP_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAPP_FOLDER_TYPE, CamelIMAPPFolder)) -#define CAMEL_IMAPP_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAPP_FOLDER_TYPE, CamelIMAPPFolderClass)) -#define CAMEL_IS_IMAP_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAPP_FOLDER_TYPE)) - -typedef struct _CamelIMAPPFolder { - CamelFolder parent_object; - - char *raw_name; - CamelFolderChangeInfo *changes; - - guint32 exists; - guint32 recent; - guint32 uidvalidity; - guint32 unseen; - guint32 permanentflags; -} CamelIMAPPFolder; - -typedef struct _CamelIMAPPFolderClass { - CamelFolderClass parent_class; -} CamelIMAPPFolderClass; - -/* Standard Camel function */ -CamelType camel_imapp_folder_get_type (void); - -/* public methods */ -CamelFolder *camel_imapp_folder_new(CamelStore *parent, const char *path); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_IMAPP_FOLDER_H */ diff --git a/camel/providers/imapp/camel-imapp-provider.c b/camel/providers/imapp/camel-imapp-provider.c deleted file mode 100644 index 21ec24cb77..0000000000 --- a/camel/providers/imapp/camel-imapp-provider.c +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-pop3-provider.c: pop3 provider registration code */ - -/* - * Authors : - * Dan Winship <danw@ximian.com> - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "camel/camel-provider.h" -#include "camel/camel-session.h" -#include "camel/camel-url.h" -#include "camel/camel-sasl.h" -#include "camel/camel-i18n.h" - -#include "camel-imapp-store.h" - -CamelProviderConfEntry imapp_conf_entries[] = { - { CAMEL_PROVIDER_CONF_SECTION_START, "storage", NULL, - N_("Message storage") }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider imapp_provider = { - "imapp", - - N_("IMAP+"), - - N_("Experimental IMAP 4(.1) client\n" - "This is untested and unsupported code, you want to use plain imap instead.\n\n" - " !!! DO NOT USE THIS FOR PRODUCTION EMAIL !!!\n"), - "mail", - - CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE | - CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_SUPPORTS_SSL, - - CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH, - - imapp_conf_entries, - - /* ... */ -}; - -CamelServiceAuthType camel_imapp_password_authtype = { - N_("Password"), - - N_("This option will connect to the IMAP server using a " - "plaintext password."), - - "", - TRUE -}; - -void camel_imapp_module_init(void); - -void -camel_imapp_module_init(void) -{ - extern void camel_exception_setup(void); - - imapp_provider.object_types[CAMEL_PROVIDER_STORE] = camel_imapp_store_get_type(); - imapp_provider.url_hash = camel_url_hash; - imapp_provider.url_equal = camel_url_equal; - - imapp_provider.authtypes = g_list_prepend(imapp_provider.authtypes, camel_sasl_authtype_list(FALSE)); - imapp_provider.authtypes = g_list_prepend(imapp_provider.authtypes, &camel_imapp_password_authtype); - - /* blah ... could just use it in object setup? */ - /* TEMPORARY */ - camel_exception_setup(); - - camel_provider_register(&imapp_provider); -} - -void -camel_provider_module_init(void) -{ - camel_imapp_module_init(); -} diff --git a/camel/providers/imapp/camel-imapp-store-summary.c b/camel/providers/imapp/camel-imapp-store-summary.c deleted file mode 100644 index 0c8d617d1a..0000000000 --- a/camel/providers/imapp/camel-imapp-store-summary.c +++ /dev/null @@ -1,616 +0,0 @@ -/* - * Copyright (C) 2002 Ximian Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <unistd.h> -#include <ctype.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> - -#include "camel-imapp-store-summary.h" - -#include "camel/camel-file-utils.h" - -#include "camel-string-utils.h" -#include "libedataserver/md5-utils.h" -#include "libedataserver/e-memory.h" - -#include "camel-private.h" -#include "camel-utf8.h" - -#define d(x) -#define io(x) /* io debug */ - -#define CAMEL_IMAPP_STORE_SUMMARY_VERSION_0 (0) - -#define CAMEL_IMAPP_STORE_SUMMARY_VERSION (0) - -#define _PRIVATE(o) (((CamelIMAPPStoreSummary *)(o))->priv) - -static int summary_header_load(CamelStoreSummary *, FILE *); -static int summary_header_save(CamelStoreSummary *, FILE *); - -/*static CamelStoreInfo * store_info_new(CamelStoreSummary *, const char *);*/ -static CamelStoreInfo * store_info_load(CamelStoreSummary *, FILE *); -static int store_info_save(CamelStoreSummary *, FILE *, CamelStoreInfo *); -static void store_info_free(CamelStoreSummary *, CamelStoreInfo *); - -static const char *store_info_string(CamelStoreSummary *, const CamelStoreInfo *, int); -static void store_info_set_string(CamelStoreSummary *, CamelStoreInfo *, int, const char *); - -static void camel_imapp_store_summary_class_init (CamelIMAPPStoreSummaryClass *klass); -static void camel_imapp_store_summary_init (CamelIMAPPStoreSummary *obj); -static void camel_imapp_store_summary_finalise (CamelObject *obj); - -static CamelStoreSummaryClass *camel_imapp_store_summary_parent; - -static void -camel_imapp_store_summary_class_init (CamelIMAPPStoreSummaryClass *klass) -{ - CamelStoreSummaryClass *ssklass = (CamelStoreSummaryClass *)klass; - - ssklass->summary_header_load = summary_header_load; - ssklass->summary_header_save = summary_header_save; - - /*ssklass->store_info_new = store_info_new;*/ - ssklass->store_info_load = store_info_load; - ssklass->store_info_save = store_info_save; - ssklass->store_info_free = store_info_free; - - ssklass->store_info_string = store_info_string; - ssklass->store_info_set_string = store_info_set_string; -} - -static void -camel_imapp_store_summary_init (CamelIMAPPStoreSummary *s) -{ - /*struct _CamelIMAPPStoreSummaryPrivate *p; - - p = _PRIVATE(s) = g_malloc0(sizeof(*p));*/ - - ((CamelStoreSummary *)s)->store_info_size = sizeof(CamelIMAPPStoreInfo); - s->version = CAMEL_IMAPP_STORE_SUMMARY_VERSION; -} - -static void -camel_imapp_store_summary_finalise (CamelObject *obj) -{ - /*struct _CamelIMAPPStoreSummaryPrivate *p;*/ - /*CamelIMAPPStoreSummary *s = (CamelIMAPPStoreSummary *)obj;*/ - - /*p = _PRIVATE(obj); - g_free(p);*/ -} - -CamelType -camel_imapp_store_summary_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - camel_imapp_store_summary_parent = (CamelStoreSummaryClass *)camel_store_summary_get_type(); - type = camel_type_register((CamelType)camel_imapp_store_summary_parent, "CamelIMAPPStoreSummary", - sizeof (CamelIMAPPStoreSummary), - sizeof (CamelIMAPPStoreSummaryClass), - (CamelObjectClassInitFunc) camel_imapp_store_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_imapp_store_summary_init, - (CamelObjectFinalizeFunc) camel_imapp_store_summary_finalise); - } - - return type; -} - -/** - * camel_imapp_store_summary_new: - * - * Create a new CamelIMAPPStoreSummary object. - * - * Return value: A new CamelIMAPPStoreSummary widget. - **/ -CamelIMAPPStoreSummary * -camel_imapp_store_summary_new (void) -{ - CamelIMAPPStoreSummary *new = CAMEL_IMAPP_STORE_SUMMARY ( camel_object_new (camel_imapp_store_summary_get_type ())); - - return new; -} - -/** - * camel_imapp_store_summary_full_name: - * @s: - * @path: - * - * Retrieve a summary item by full name. - * - * A referenced to the summary item is returned, which may be - * ref'd or free'd as appropriate. - * - * Return value: The summary item, or NULL if the @full_name name - * is not available. - * It must be freed using camel_store_summary_info_free(). - **/ -CamelIMAPPStoreInfo * -camel_imapp_store_summary_full_name(CamelIMAPPStoreSummary *s, const char *full_name) -{ - int count, i; - CamelIMAPPStoreInfo *info; - - count = camel_store_summary_count((CamelStoreSummary *)s); - for (i=0;i<count;i++) { - info = (CamelIMAPPStoreInfo *)camel_store_summary_index((CamelStoreSummary *)s, i); - if (info) { - if (strcmp(info->full_name, full_name) == 0) - return info; - camel_store_summary_info_free((CamelStoreSummary *)s, (CamelStoreInfo *)info); - } - } - - return NULL; -} - -char * -camel_imapp_store_summary_full_to_path(CamelIMAPPStoreSummary *s, const char *full_name, char dir_sep) -{ - char *path, *p; - int c; - const char *f; - - if (dir_sep != '/') { - p = path = alloca(strlen(full_name)*3+1); - f = full_name; - while ( (c = *f++ & 0xff) ) { - if (c == dir_sep) - *p++ = '/'; - else if (c == '/' || c == '%') - p += sprintf(p, "%%%02X", c); - else - *p++ = c; - } - *p = 0; - } else - path = (char *)full_name; - - return camel_utf7_utf8(path); -} - -static guint32 hexnib(guint32 c) -{ - if (c >= '0' && c <= '9') - return c-'0'; - else if (c>='A' && c <= 'Z') - return c-'A'+10; - else - return 0; -} - -char * -camel_imapp_store_summary_path_to_full(CamelIMAPPStoreSummary *s, const char *path, char dir_sep) -{ - unsigned char *full, *f; - guint32 c, v = 0; - const char *p; - int state=0; - char *subpath, *last = NULL; - CamelStoreInfo *si; - CamelIMAPPStoreNamespace *ns; - - /* check to see if we have a subpath of path already defined */ - subpath = alloca(strlen(path)+1); - strcpy(subpath, path); - do { - si = camel_store_summary_path((CamelStoreSummary *)s, subpath); - if (si == NULL) { - last = strrchr(subpath, '/'); - if (last) - *last = 0; - } - } while (si == NULL && last); - - /* path is already present, use the raw version we have */ - if (si && strlen(subpath) == strlen(path)) { - f = g_strdup(camel_imapp_store_info_full_name(s, si)); - camel_store_summary_info_free((CamelStoreSummary *)s, si); - return f; - } - - ns = camel_imapp_store_summary_namespace_find_path(s, path); - - f = full = alloca(strlen(path)*2+1); - if (si) - p = path + strlen(subpath); - else if (ns) - p = path + strlen(ns->path); - else - p = path; - - while ( (c = camel_utf8_getc((const unsigned char **)&p)) ) { - switch(state) { - case 0: - if (c == '%') - state = 1; - else { - if (c == '/') - c = dir_sep; - camel_utf8_putc(&f, c); - } - break; - case 1: - state = 2; - v = hexnib(c)<<4; - break; - case 2: - state = 0; - v |= hexnib(c); - camel_utf8_putc(&f, v); - break; - } - } - camel_utf8_putc(&f, c); - - /* merge old path part if required */ - f = camel_utf8_utf7(full); - if (si) { - full = g_strdup_printf("%s%s", camel_imapp_store_info_full_name(s, si), f); - g_free(f); - camel_store_summary_info_free((CamelStoreSummary *)s, si); - f = full; - } else if (ns) { - full = g_strdup_printf("%s%s", ns->full_name, f); - g_free(f); - f = full; - } - - return f; -} - -CamelIMAPPStoreInfo * -camel_imapp_store_summary_add_from_full(CamelIMAPPStoreSummary *s, const char *full, char dir_sep) -{ - CamelIMAPPStoreInfo *info; - char *pathu8, *prefix; - int len; - char *full_name; - CamelIMAPPStoreNamespace *ns; - - d(printf("adding full name '%s' '%c'\n", full, dir_sep)); - - len = strlen(full); - full_name = alloca(len+1); - strcpy(full_name, full); - if (full_name[len-1] == dir_sep) - full_name[len-1] = 0; - - info = camel_imapp_store_summary_full_name(s, full_name); - if (info) { - camel_store_summary_info_free((CamelStoreSummary *)s, (CamelStoreInfo *)info); - d(printf(" already there\n")); - return info; - } - - ns = camel_imapp_store_summary_namespace_find_full(s, full_name); - if (ns) { - d(printf("(found namespace for '%s' ns '%s') ", full_name, ns->path)); - len = strlen(ns->full_name); - if (len >= strlen(full_name)) { - pathu8 = g_strdup(ns->path); - } else { - if (full_name[len] == ns->sep) - len++; - - prefix = camel_imapp_store_summary_full_to_path(s, full_name+len, ns->sep); - if (*ns->path) { - pathu8 = g_strdup_printf ("%s/%s", ns->path, prefix); - g_free (prefix); - } else { - pathu8 = prefix; - } - } - d(printf(" (pathu8 = '%s')", pathu8)); - } else { - d(printf("(Cannot find namespace for '%s')\n", full_name)); - pathu8 = camel_imapp_store_summary_full_to_path(s, full_name, dir_sep); - } - - info = (CamelIMAPPStoreInfo *)camel_store_summary_add_from_path((CamelStoreSummary *)s, pathu8); - if (info) { - d(printf(" '%s' -> '%s'\n", pathu8, full_name)); - camel_store_info_set_string((CamelStoreSummary *)s, (CamelStoreInfo *)info, CAMEL_IMAPP_STORE_INFO_FULL_NAME, full_name); - } else - d(printf(" failed\n")); - - return info; -} - -/* should this be const? */ -/* TODO: deprecate/merge this function with path_to_full */ -char * -camel_imapp_store_summary_full_from_path(CamelIMAPPStoreSummary *s, const char *path) -{ - CamelIMAPPStoreNamespace *ns; - char *name = NULL; - - ns = camel_imapp_store_summary_namespace_find_path(s, path); - if (ns) - name = camel_imapp_store_summary_path_to_full(s, path, ns->sep); - - d(printf("looking up path %s -> %s\n", path, name?name:"not found")); - - return name; -} - -/* TODO: this api needs some more work */ -CamelIMAPPStoreNamespace *camel_imapp_store_summary_namespace_new(CamelIMAPPStoreSummary *s, const char *full_name, char dir_sep) -{ - CamelIMAPPStoreNamespace *ns; - char *p; - int len; - - ns = g_malloc0(sizeof(*ns)); - ns->full_name = g_strdup(full_name); - len = strlen(ns->full_name)-1; - if (len >= 0 && ns->full_name[len] == dir_sep) - ns->full_name[len] = 0; - ns->sep = dir_sep; - - p = ns->path = camel_imapp_store_summary_full_to_path(s, ns->full_name, dir_sep); - while (*p) { - if (*p == '/') - *p = '.'; - p++; - } - - return ns; -} - -void camel_imapp_store_summary_namespace_set(CamelIMAPPStoreSummary *s, CamelIMAPPStoreNamespace *ns) -{ - static void namespace_clear(CamelStoreSummary *s); - - d(printf("Setting namesapce to '%s' '%c' -> '%s'\n", ns->full_name, ns->sep, ns->path)); - namespace_clear((CamelStoreSummary *)s); - s->namespace = ns; - camel_store_summary_touch((CamelStoreSummary *)s); -} - -CamelIMAPPStoreNamespace * -camel_imapp_store_summary_namespace_find_path(CamelIMAPPStoreSummary *s, const char *path) -{ - int len; - CamelIMAPPStoreNamespace *ns; - - /* NB: this currently only compares against 1 namespace, in future compare against others */ - ns = s->namespace; - while (ns) { - len = strlen(ns->path); - if (len == 0 - || (strncmp(ns->path, path, len) == 0 - && (path[len] == '/' || path[len] == 0))) - break; - ns = NULL; - } - - /* have a default? */ - return ns; -} - -CamelIMAPPStoreNamespace * -camel_imapp_store_summary_namespace_find_full(CamelIMAPPStoreSummary *s, const char *full) -{ - int len; - CamelIMAPPStoreNamespace *ns; - - /* NB: this currently only compares against 1 namespace, in future compare against others */ - ns = s->namespace; - while (ns) { - len = strlen(ns->full_name); - d(printf("find_full: comparing namespace '%s' to name '%s'\n", ns->full_name, full)); - if (len == 0 - || (strncmp(ns->full_name, full, len) == 0 - && (full[len] == ns->sep || full[len] == 0))) - break; - ns = NULL; - } - - /* have a default? */ - return ns; -} - -static void -namespace_free(CamelStoreSummary *s, CamelIMAPPStoreNamespace *ns) -{ - g_free(ns->path); - g_free(ns->full_name); - g_free(ns); -} - -static void -namespace_clear(CamelStoreSummary *s) -{ - CamelIMAPPStoreSummary *is = (CamelIMAPPStoreSummary *)s; - - if (is->namespace) - namespace_free(s, is->namespace); - is->namespace = NULL; -} - -static CamelIMAPPStoreNamespace * -namespace_load(CamelStoreSummary *s, FILE *in) -{ - CamelIMAPPStoreNamespace *ns; - guint32 sep = '/'; - - ns = g_malloc0(sizeof(*ns)); - if (camel_file_util_decode_string(in, &ns->path) == -1 - || camel_file_util_decode_string(in, &ns->full_name) == -1 - || camel_file_util_decode_uint32(in, &sep) == -1) { - namespace_free(s, ns); - ns = NULL; - } else { - ns->sep = sep; - } - - return ns; -} - -static int -namespace_save(CamelStoreSummary *s, FILE *in, CamelIMAPPStoreNamespace *ns) -{ - if (camel_file_util_encode_string(in, ns->path) == -1 - || camel_file_util_encode_string(in, ns->full_name) == -1 - || camel_file_util_encode_uint32(in, (guint32)ns->sep) == -1) - return -1; - - return 0; -} - -static int -summary_header_load(CamelStoreSummary *s, FILE *in) -{ - CamelIMAPPStoreSummary *is = (CamelIMAPPStoreSummary *)s; - gint32 version, capabilities, count; - - namespace_clear(s); - - if (camel_imapp_store_summary_parent->summary_header_load((CamelStoreSummary *)s, in) == -1 - || camel_file_util_decode_fixed_int32(in, &version) == -1) - return -1; - - is->version = version; - - if (version < CAMEL_IMAPP_STORE_SUMMARY_VERSION_0) { - g_warning("Store summary header version too low"); - return -1; - } - - /* note file format can be expanded to contain more namespaces, but only 1 at the moment */ - if (camel_file_util_decode_fixed_int32(in, &capabilities) == -1 - || camel_file_util_decode_fixed_int32(in, &count) == -1 - || count > 1) - return -1; - - is->capabilities = capabilities; - if (count == 1) { - if ((is->namespace = namespace_load(s, in)) == NULL) - return -1; - } - - return 0; -} - -static int -summary_header_save(CamelStoreSummary *s, FILE *out) -{ - CamelIMAPPStoreSummary *is = (CamelIMAPPStoreSummary *)s; - guint32 count; - - count = is->namespace?1:0; - - /* always write as latest version */ - if (camel_imapp_store_summary_parent->summary_header_save((CamelStoreSummary *)s, out) == -1 - || camel_file_util_encode_fixed_int32(out, CAMEL_IMAPP_STORE_SUMMARY_VERSION) == -1 - || camel_file_util_encode_fixed_int32(out, is->capabilities) == -1 - || camel_file_util_encode_fixed_int32(out, count) == -1) - return -1; - - if (is->namespace && namespace_save(s, out, is->namespace) == -1) - return -1; - - return 0; -} - -static CamelStoreInfo * -store_info_load(CamelStoreSummary *s, FILE *in) -{ - CamelIMAPPStoreInfo *mi; - - mi = (CamelIMAPPStoreInfo *)camel_imapp_store_summary_parent->store_info_load(s, in); - if (mi) { - if (camel_file_util_decode_string(in, &mi->full_name) == -1) { - camel_store_summary_info_free(s, (CamelStoreInfo *)mi); - mi = NULL; - } - } - - return (CamelStoreInfo *)mi; -} - -static int -store_info_save(CamelStoreSummary *s, FILE *out, CamelStoreInfo *mi) -{ - CamelIMAPPStoreInfo *isi = (CamelIMAPPStoreInfo *)mi; - - if (camel_imapp_store_summary_parent->store_info_save(s, out, mi) == -1 - || camel_file_util_encode_string(out, isi->full_name) == -1) - return -1; - - return 0; -} - -static void -store_info_free(CamelStoreSummary *s, CamelStoreInfo *mi) -{ - CamelIMAPPStoreInfo *isi = (CamelIMAPPStoreInfo *)mi; - - g_free(isi->full_name); - camel_imapp_store_summary_parent->store_info_free(s, mi); -} - -static const char * -store_info_string(CamelStoreSummary *s, const CamelStoreInfo *mi, int type) -{ - CamelIMAPPStoreInfo *isi = (CamelIMAPPStoreInfo *)mi; - - /* FIXME: Locks? */ - - g_assert (mi != NULL); - - switch (type) { - case CAMEL_IMAPP_STORE_INFO_FULL_NAME: - return isi->full_name; - default: - return camel_imapp_store_summary_parent->store_info_string(s, mi, type); - } -} - -static void -store_info_set_string(CamelStoreSummary *s, CamelStoreInfo *mi, int type, const char *str) -{ - CamelIMAPPStoreInfo *isi = (CamelIMAPPStoreInfo *)mi; - - g_assert(mi != NULL); - - switch(type) { - case CAMEL_IMAPP_STORE_INFO_FULL_NAME: - d(printf("Set full name %s -> %s\n", isi->full_name, str)); - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - g_free(isi->full_name); - isi->full_name = g_strdup(str); - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); - break; - default: - camel_imapp_store_summary_parent->store_info_set_string(s, mi, type, str); - break; - } -} diff --git a/camel/providers/imapp/camel-imapp-store-summary.h b/camel/providers/imapp/camel-imapp-store-summary.h deleted file mode 100644 index 154fe8798e..0000000000 --- a/camel/providers/imapp/camel-imapp-store-summary.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2002 Ximian Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef _CAMEL_IMAPP_STORE_SUMMARY_H -#define _CAMEL_IMAPP_STORE_SUMMARY_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include <camel/camel-object.h> -#include <camel/camel-store-summary.h> - -#define CAMEL_IMAPP_STORE_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_imapp_store_summary_get_type (), CamelIMAPPStoreSummary) -#define CAMEL_IMAPP_STORE_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imapp_store_summary_get_type (), CamelIMAPPStoreSummaryClass) -#define CAMEL_IS_IMAP_STORE_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_imapp_store_summary_get_type ()) - -typedef struct _CamelIMAPPStoreSummary CamelIMAPPStoreSummary; -typedef struct _CamelIMAPPStoreSummaryClass CamelIMAPPStoreSummaryClass; - -typedef struct _CamelIMAPPStoreInfo CamelIMAPPStoreInfo; - -enum { - CAMEL_IMAPP_STORE_INFO_FULL_NAME = CAMEL_STORE_INFO_LAST, - CAMEL_IMAPP_STORE_INFO_LAST, -}; - -struct _CamelIMAPPStoreInfo { - CamelStoreInfo info; - char *full_name; -}; - -typedef struct _CamelIMAPPStoreNamespace CamelIMAPPStoreNamespace; - -struct _CamelIMAPPStoreNamespace { - char *path; /* display path */ - char *full_name; /* real name */ - char sep; /* directory separator */ -}; - -struct _CamelIMAPPStoreSummary { - CamelStoreSummary summary; - - struct _CamelIMAPPStoreSummaryPrivate *priv; - - /* header info */ - guint32 version; /* version of base part of file */ - guint32 capabilities; - CamelIMAPPStoreNamespace *namespace; /* eventually to be a list */ -}; - -struct _CamelIMAPPStoreSummaryClass { - CamelStoreSummaryClass summary_class; -}; - -CamelType camel_imapp_store_summary_get_type (void); -CamelIMAPPStoreSummary *camel_imapp_store_summary_new (void); - -/* TODO: this api needs some more work, needs to support lists */ -CamelIMAPPStoreNamespace *camel_imapp_store_summary_namespace_new(CamelIMAPPStoreSummary *s, const char *full_name, char dir_sep); -void camel_imapp_store_summary_namespace_set(CamelIMAPPStoreSummary *s, CamelIMAPPStoreNamespace *ns); -CamelIMAPPStoreNamespace *camel_imapp_store_summary_namespace_find_path(CamelIMAPPStoreSummary *s, const char *path); -CamelIMAPPStoreNamespace *camel_imapp_store_summary_namespace_find_full(CamelIMAPPStoreSummary *s, const char *full_name); - -/* converts to/from utf8 canonical nasmes */ -char *camel_imapp_store_summary_full_to_path(CamelIMAPPStoreSummary *s, const char *full_name, char dir_sep); -char *camel_imapp_store_summary_path_to_full(CamelIMAPPStoreSummary *s, const char *path, char dir_sep); - -CamelIMAPPStoreInfo *camel_imapp_store_summary_full_name(CamelIMAPPStoreSummary *s, const char *full_name); -CamelIMAPPStoreInfo *camel_imapp_store_summary_add_from_full(CamelIMAPPStoreSummary *s, const char *full_name, char dir_sep); - -/* a convenience lookup function. always use this if path known */ -char *camel_imapp_store_summary_full_from_path(CamelIMAPPStoreSummary *s, const char *path); - -/* helper macro's */ -#define camel_imapp_store_info_full_name(s, i) (camel_store_info_string((CamelStoreSummary *)s, (const CamelStoreInfo *)i, CAMEL_IMAPP_STORE_INFO_FULL_NAME)) - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_IMAPP_STORE_SUMMARY_H */ diff --git a/camel/providers/imapp/camel-imapp-store.c b/camel/providers/imapp/camel-imapp-store.c deleted file mode 100644 index 03f835da7a..0000000000 --- a/camel/providers/imapp/camel-imapp-store.c +++ /dev/null @@ -1,1018 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-store.c : class for a imap store */ - -/* - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2000-2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -#include "camel/camel-operation.h" - -#include "camel/camel-stream-buffer.h" -#include "camel/camel-session.h" -#include "camel/camel-exception.h" -#include "camel/camel-url.h" -#include "camel/camel-sasl.h" -#include "camel/camel-data-cache.h" -#include "camel/camel-tcp-stream.h" -#include "camel/camel-tcp-stream-raw.h" -#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" -#include "camel-imapp-folder.h" -#include "camel-imapp-engine.h" -#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 - -static CamelStoreClass *parent_class = NULL; - -static void finalize (CamelObject *object); - -static void imap_construct(CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex); -/* static char *imap_get_name(CamelService *service, gboolean brief);*/ -static gboolean imap_connect (CamelService *service, CamelException *ex); -static gboolean imap_disconnect (CamelService *service, gboolean clean, CamelException *ex); -static GList *imap_query_auth_types (CamelService *service, CamelException *ex); - -static CamelFolder *imap_get_trash (CamelStore *store, CamelException *ex); - -static CamelFolder *imap_get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex); -static CamelFolder *imap_get_inbox (CamelStore *store, CamelException *ex); -static void imap_rename_folder(CamelStore *store, const char *old_name, const char *new_name, CamelException *ex); -static CamelFolderInfo *imap_get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex); -static void imap_delete_folder(CamelStore *store, const char *folder_name, CamelException *ex); -static void imap_rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex); -static CamelFolderInfo *imap_create_folder(CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex); - -/* yet to see if this should go global or not */ -void camel_imapp_store_folder_selected(CamelIMAPPStore *store, CamelIMAPPFolder *folder, CamelIMAPPSelectResponse *select); - -static void -camel_imapp_store_class_init (CamelIMAPPStoreClass *camel_imapp_store_class) -{ - CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS(camel_imapp_store_class); - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS(camel_imapp_store_class); - - parent_class = CAMEL_STORE_CLASS(camel_type_get_global_classfuncs(camel_store_get_type())); - - /* virtual method overload */ - camel_service_class->construct = imap_construct; - /*camel_service_class->get_name = imap_get_name;*/ - camel_service_class->query_auth_types = imap_query_auth_types; - camel_service_class->connect = imap_connect; - camel_service_class->disconnect = imap_disconnect; - - camel_store_class->get_trash = imap_get_trash; - camel_store_class->get_folder = imap_get_folder; - camel_store_class->get_inbox = imap_get_inbox; - - camel_store_class->create_folder = imap_create_folder; - camel_store_class->rename_folder = imap_rename_folder; - camel_store_class->delete_folder = imap_delete_folder; - camel_store_class->get_folder_info = imap_get_folder_info; -} - -static void -camel_imapp_store_init (gpointer object, gpointer klass) -{ - /*CamelIMAPPStore *istore = object;*/ -} - -CamelType -camel_imapp_store_get_type (void) -{ - static CamelType camel_imapp_store_type = CAMEL_INVALID_TYPE; - - if (!camel_imapp_store_type) { - camel_imapp_store_type = camel_type_register(CAMEL_STORE_TYPE, - "CamelIMAPPStore", - sizeof (CamelIMAPPStore), - sizeof (CamelIMAPPStoreClass), - (CamelObjectClassInitFunc) camel_imapp_store_class_init, - NULL, - (CamelObjectInitFunc) camel_imapp_store_init, - finalize); - } - - return camel_imapp_store_type; -} - -static void -finalize (CamelObject *object) -{ - CamelIMAPPStore *imap_store = CAMEL_IMAPP_STORE (object); - - /* force disconnect so we dont have it run later, after we've cleaned up some stuff */ - /* SIGH */ - - camel_service_disconnect((CamelService *)imap_store, TRUE, NULL); - - if (imap_store->driver) - camel_object_unref(imap_store->driver); - if (imap_store->cache) - camel_object_unref(imap_store->cache); -} - -static void imap_construct(CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex) -{ - char *root, *summary; - CamelIMAPPStore *store = (CamelIMAPPStore *)service; - - CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); - if (camel_exception_is_set(ex)) - return; - - CAMEL_TRY { - store->summary = camel_imapp_store_summary_new(); - root = camel_session_get_storage_path(service->session, service, ex); - if (root) { - summary = g_build_filename(root, ".ev-store-summary", NULL); - camel_store_summary_set_filename((CamelStoreSummary *)store->summary, summary); - /* FIXME: need to remove params, passwords, etc */ - camel_store_summary_set_uri_base((CamelStoreSummary *)store->summary, service->url); - camel_store_summary_load((CamelStoreSummary *)store->summary); - } - } CAMEL_CATCH(e) { - camel_exception_xfer(ex, e); - } CAMEL_DONE; -} - -enum { - 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 void -connect_to_server (CamelService *service, int ssl_mode, int try_starttls) -/* throws IO exception */ -{ - CamelIMAPPStore *store = CAMEL_IMAPP_STORE (service); - CamelStream * volatile tcp_stream = NULL; - CamelIMAPPStream * volatile imap_stream = NULL; - int ret; - CamelException *ex; - - ex = camel_exception_new(); - CAMEL_TRY { - char *serv; - const char *port = NULL; - struct addrinfo *ai, hints = { 0 }; - - /* parent class connect initialization */ - CAMEL_SERVICE_CLASS (parent_class)->connect (service, ex); - if (ex->id) - camel_exception_throw_ex(ex); - - if (service->url->port) { - serv = g_alloca(16); - sprintf(serv, "%d", service->url->port); - } else { - serv = "imap"; - port = "143"; - } - -#ifdef HAVE_SSL - if (camel_url_get_param (service->url, "use_ssl")) { - 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 = "993"; - } - tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, SSL_PORT_FLAGS); - } - } 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 (ex->id && ex->id != CAMEL_EXCEPTION_USER_CANCEL && port != NULL) { - camel_exception_clear(ex); - ai = camel_getaddrinfo(service->url->host, port, &hints, ex); - } - - if (ex->id) - camel_exception_throw_ex(ex); - - ret = camel_tcp_stream_connect(CAMEL_TCP_STREAM(tcp_stream), ai); - camel_freeaddrinfo(ai); - if (ret == -1) { - if (errno == EINTR) - camel_exception_throw(CAMEL_EXCEPTION_USER_CANCEL, _("Connection cancelled")); - else - camel_exception_throw(CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s (port %s): %s"), - service->url->host, serv, strerror(errno)); - } - - imap_stream = (CamelIMAPPStream *)camel_imapp_stream_new(tcp_stream); - store->driver = camel_imapp_driver_new(imap_stream); - - camel_object_unref(imap_stream); - camel_object_unref(tcp_stream); - } CAMEL_CATCH(e) { - if (tcp_stream) - camel_object_unref(tcp_stream); - if (imap_stream) - camel_object_unref((CamelObject *)imap_stream); - camel_exception_throw_ex(e); - } CAMEL_DONE; - - camel_exception_free(ex); -} - -#if 0 - -/* leave this stuff out for now */ - - -static struct { - char *value; - int mode; -} ssl_options[] = { - { "", 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) -{ -#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, use_ssl)) - break; - 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 { - /* User doesn't care about SSL */ - return connect_to_server (service, ssl_mode, FALSE, ex); - } -#else - return connect_to_server (service, USE_SSL_NEVER, FALSE, ex); -#endif -} -#endif - -extern CamelServiceAuthType camel_imapp_password_authtype; -extern CamelServiceAuthType camel_imapp_apop_authtype; - -static GList * -imap_query_auth_types (CamelService *service, CamelException *ex) -{ - /*CamelIMAPPStore *store = CAMEL_IMAPP_STORE (service);*/ - GList *types = NULL; - - types = CAMEL_SERVICE_CLASS (parent_class)->query_auth_types (service, ex); - if (types == NULL) - return NULL; - -#if 0 - if (connect_to_server_wrapper (service, NULL)) { - types = g_list_concat(types, g_list_copy(store->engine->auth)); - imap_disconnect (service, TRUE, NULL); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to POP server on %s"), - service->url->host); - } -#endif - return types; -} - -static void -store_get_pass(CamelIMAPPStore *store) -{ - if (((CamelService *)store)->url->passwd == NULL) { - char *prompt; - CamelException ex; - - camel_exception_init(&ex); - - prompt = g_strdup_printf (_("%sPlease enter the IMAP password for %s@%s"), - store->login_error?store->login_error:"", - ((CamelService *)store)->url->user, - ((CamelService *)store)->url->host); - ((CamelService *)store)->url->passwd = camel_session_get_password(camel_service_get_session((CamelService *)store), - (CamelService *)store, NULL, - prompt, "password", CAMEL_SESSION_PASSWORD_SECRET, &ex); - g_free (prompt); - if (camel_exception_is_set(&ex)) - camel_exception_throw_ex(&ex); - } -} - -static struct _CamelSasl * -store_get_sasl(struct _CamelIMAPPDriver *driver, CamelIMAPPStore *store) -{ - store_get_pass(store); - - if (((CamelService *)store)->url->authmech) - return camel_sasl_new("imap", ((CamelService *)store)->url->authmech, (CamelService *)store); - - return NULL; -} - -static void -store_get_login(struct _CamelIMAPPDriver *driver, char **login, char **pass, CamelIMAPPStore *store) -{ - store_get_pass(store); - - *login = g_strdup(((CamelService *)store)->url->user); - *pass = g_strdup(((CamelService *)store)->url->passwd); -} - -static gboolean -imap_connect (CamelService *service, CamelException *ex) -{ - CamelIMAPPStore *store = (CamelIMAPPStore *)service; - volatile int ret = FALSE; - - CAMEL_TRY { - volatile int retry = TRUE; - - if (store->cache == NULL) { - char *root; - - root = camel_session_get_storage_path(service->session, service, ex); - if (root) { - store->cache = camel_data_cache_new(root, 0, ex); - g_free(root); - if (store->cache) { - /* Default cache expiry - 1 week or not visited in a day */ - camel_data_cache_set_expire_age(store->cache, 60*60*24*7); - camel_data_cache_set_expire_access(store->cache, 60*60*24); - } - } - if (camel_exception_is_set(ex)) - camel_exception_throw_ex(ex); - } - - connect_to_server(service, USE_SSL_NEVER, FALSE); - - camel_imapp_driver_set_sasl_factory(store->driver, (CamelIMAPPSASLFunc)store_get_sasl, store); - camel_imapp_driver_set_login_query(store->driver, (CamelIMAPPLoginFunc)store_get_login, store); - store->login_error = NULL; - - do { - CAMEL_TRY { - if (store->driver->engine->state != IMAP_ENGINE_AUTH) - camel_imapp_driver_login(store->driver); - ret = TRUE; - retry = FALSE; - } CAMEL_CATCH(e) { - g_free(store->login_error); - store->login_error = NULL; - switch (e->id) { - case CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE: - store->login_error = g_strdup_printf("%s\n\n", e->desc); - camel_session_forget_password(service->session, service, NULL, "password", ex); - camel_url_set_passwd(service->url, NULL); - break; - default: - camel_exception_throw_ex(e); - break; - } - } CAMEL_DONE; - } while (retry); - } CAMEL_CATCH(e) { - camel_exception_xfer(ex, e); - camel_service_disconnect(service, TRUE, NULL); - ret = FALSE; - } CAMEL_DONE; - - g_free(store->login_error); - store->login_error = NULL; - - return ret; -} - -static gboolean -imap_disconnect (CamelService *service, gboolean clean, CamelException *ex) -{ - CamelIMAPPStore *store = CAMEL_IMAPP_STORE (service); - - /* FIXME: logout */ - - if (!CAMEL_SERVICE_CLASS (parent_class)->disconnect (service, clean, ex)) - return FALSE; - - /* logout/disconnect */ - if (store->driver) { - camel_object_unref(store->driver); - store->driver = NULL; - } - - return TRUE; -} - -static CamelFolder * -imap_get_trash (CamelStore *store, CamelException *ex) -{ - /* no-op */ - return NULL; -} - -static CamelFolder * -imap_get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex) -{ - CamelIMAPPStore *istore = (CamelIMAPPStore *)store; - CamelIMAPPFolder * volatile folder = NULL; - - /* ??? */ - - /* 1. create the folder */ - /* 2. run select? */ - /* 3. update the folder */ - - CAMEL_TRY { - folder = (CamelIMAPPFolder *)camel_imapp_folder_new(store, folder_name); - camel_imapp_driver_select(istore->driver, folder); - } CAMEL_CATCH (e) { - if (folder) { - camel_object_unref(folder); - folder = NULL; - } - camel_exception_xfer(ex, e); - } CAMEL_DONE; - - return (CamelFolder *)folder; -} - -static CamelFolder * -imap_get_inbox(CamelStore *store, CamelException *ex) -{ - camel_exception_setv(ex, 1, "get_inbox::unimplemented"); - - return NULL; -} - -/* 8 bit, string compare */ -static int folders_build_cmp(const void *app, const void *bpp) -{ - struct _list_info *a = *((struct _list_info **)app); - struct _list_info *b = *((struct _list_info **)bpp); - unsigned char *ap = (unsigned char *)(a->name); - unsigned char *bp = (unsigned char *)(b->name); - - printf("qsort, cmp '%s' <> '%s'\n", ap, bp); - - while (*ap && *ap == *bp) { - ap++; - bp++; - } - - if (*ap < *bp) - return -1; - else if (*ap > *bp) - return 1; - return 0; -} - -/* FIXME: this should go via storesummary? */ -static CamelFolderInfo * -folders_build_info(CamelURL *base, struct _list_info *li) -{ - char *path, *full_name, *name; - CamelFolderInfo *fi; - - full_name = imapp_list_get_path(li); - name = strrchr(full_name, '/'); - if (name) - name++; - else - name = full_name; - - path = alloca(strlen(full_name)+2); - sprintf(path, "/%s", full_name); - camel_url_set_path(base, path); - - fi = g_malloc0(sizeof(*fi)); - fi->uri = camel_url_to_string(base, CAMEL_URL_HIDE_ALL); - fi->name = g_strdup(name); - fi->full_name = full_name; - fi->unread = -1; - fi->total = -1; - fi->flags = li->flags; - - if (!g_ascii_strcasecmp(fi->full_name, "inbox")) - fi->flags |= CAMEL_FOLDER_SYSTEM; - - /* TODO: could look up count here ... */ - /* ?? */ - /*folder = camel_object_bag_get(store->folders, "INBOX");*/ - - return fi; -} - -/* - a - a/b - a/b/c - a/d - b - c/d - -*/ - -/* note, pname is the raw name, not the folderinfo name */ -/* note also this free's as we go, since we never go 'backwards' */ -static CamelFolderInfo * -folders_build_rec(CamelURL *base, GPtrArray *folders, int *ip, CamelFolderInfo *pfi, char *pname) -{ - int plen = 0; - CamelFolderInfo *last = NULL, *first = NULL; - - if (pfi) - plen = strlen(pname); - - for(;(*ip)<(int)folders->len;) { - CamelFolderInfo *fi; - struct _list_info *li; - - li = folders->pdata[*ip]; - printf("checking '%s' is child of '%s'\n", li->name, pname); - - /* is this a child of the parent? */ - if (pfi != NULL - && (strncmp(pname, li->name, strlen(pname)) != 0 - || li->name[plen] != li->separator)) { - printf(" nope\n"); - break; - } - printf(" yep\n"); - - /* is this not an immediate child of the parent? */ -#if 0 - char *p; - if (pfi != NULL - && li->separator != 0 - && (p = strchr(li->name + plen + 1, li->separator)) != NULL) { - if (last == NULL) { - struct _list_info tli; - - tli.flags = CAMEL_FOLDER_NOSELECT|CAMEL_FOLDER_CHILDREN; - tli.separator = li->separator; - tli.name = g_strndup(li->name, p-li->name+1); - fi = folders_build_info(base, &tli); - fi->parent = pfi; - if (pfi && pfi->child == NULL) - pfi->child = fi; - i = folders_build_rec(folders, i, fi, tli.name); - break; - } - } -#endif - - fi = folders_build_info(base, li); - fi->parent = pfi; - if (last != NULL) - last->next = fi; - last = fi; - if (first == NULL) - first = fi; - - (*ip)++; - fi->child = folders_build_rec(base, folders, ip, fi, li->name); - imap_free_list(li); - } - - return first; -} - -static void -folder_info_dump(CamelFolderInfo *fi, int depth) -{ - char *s; - - s = alloca(depth+1); - memset(s, ' ', depth); - s[depth] = 0; - while (fi) { - printf("%s%s (%s)\n", s, fi->name, fi->uri); - if (fi->child) - folder_info_dump(fi->child, depth+2); - fi = fi->next; - } - -} - -static CamelFolderInfo * -imap_get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - CamelIMAPPStore *istore = (CamelIMAPPStore *)store; - CamelFolderInfo * fi= NULL; - char *name; - - /* FIXME: temporary, since this is not a disco store */ - if (istore->driver == NULL - && !camel_service_connect((CamelService *)store, ex)) - return NULL; - - name = (char *)top; - if (name == NULL || name[0] == 0) { - /* namespace? */ - name = ""; - } - - name = ""; - - CAMEL_TRY { - CamelURL *base; - int i; - GPtrArray *folders; - - /* FIXME: subscriptions? lsub? */ - folders = camel_imapp_driver_list(istore->driver, name, flags); - - /* this greatly simplifies the tree algorithm ... but it might - be faster just to use a hashtable to find parents? */ - qsort(folders->pdata, folders->len, sizeof(folders->pdata[0]), folders_build_cmp); - - i = 0; - base = camel_url_copy(((CamelService *)store)->url); - fi = folders_build_rec(base, folders, &i, NULL, NULL); - camel_url_free(base); - g_ptr_array_free(folders, TRUE); - } CAMEL_CATCH(e) { - camel_exception_xfer(ex, e); - } CAMEL_DONE; - - printf("built folder info:\n"); - folder_info_dump(fi, 2); - - return fi; - -#if 0 - if (top == NULL || !g_ascii_strcasecmp(top, "inbox")) { - CamelURL *uri = camel_url_copy(((CamelService *)store)->url); - - camel_url_set_path(uri, "/INBOX"); - fi = g_malloc0(sizeof(*fi)); - fi->url = camel_url_to_string(uri, CAMEL_URL_HIDE_ALL); - camel_url_free(uri); - fi->name = g_strdup("INBOX"); - fi->full_name = g_strdup("INBOX"); - fi->path = g_strdup("/INBOX"); - fi->unread_message_count = -1; - fi->flags = 0; - - folder = camel_object_bag_get(store->folders, "INBOX"); - if (folder) { - /*if (!cflags & FAST)*/ - camel_imapp_driver_update(istore->driver, (CamelIMAPPFolder *)folder); - fi->unread_message_count = camel_folder_get_unread_message_count(folder); - camel_object_unref(folder); - } - } else { - camel_exception_setv(ex, 1, "not implemented"); - } -#endif - return fi; - -#if 0 - istore->pending_list = g_ptr_array_new(); - - CAMEL_TRY { - ic = camel_imapp_engine_command_new(istore->driver->engine, "LIST", NULL, "LIST \"\" %f", top); - camel_imapp_engine_command_queue(istore->driver->engine, ic); - while (camel_imapp_engine_iterate(istore->driver->engine, ic) > 0) - ; - - if (ic->status->result != IMAP_OK) - camel_exception_throw(1, "list failed: %s", ic->status->text); - } CAMEL_CATCH (e) { - camel_exception_xfer(ex, e); - } CAMEL_DONE; - - camel_imapp_engine_command_free(istore->driver->engine, ic); - - printf("got folder list:\n"); - for (i=0;i<(int)istore->pending_list->len;i++) { - struct _list_info *linfo = istore->pending_list->pdata[i]; - - printf("%s (%c)\n", linfo->name, linfo->separator); - imap_free_list(linfo); - } - istore->pending_list = NULL; - - return NULL; -#endif -} - -static void -imap_delete_folder(CamelStore *store, const char *folder_name, CamelException *ex) -{ - camel_exception_setv(ex, 1, "delete_folder::unimplemented"); -} - -static void -imap_rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex) -{ - camel_exception_setv(ex, 1, "rename_folder::unimplemented"); -} - -static CamelFolderInfo * -imap_create_folder(CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex) -{ - camel_exception_setv(ex, 1, "create_folder::unimplemented"); - return NULL; -} - -/* ********************************************************************** */ -#if 0 -static int store_resp_fetch(CamelIMAPPEngine *ie, guint32 id, void *data) -{ - struct _fetch_info *finfo; - CamelIMAPPStore *istore = data; - CamelMessageInfo *info; - struct _pending_fetch *pending; - - finfo = imap_parse_fetch(ie->stream); - if (istore->selected) { - if ((finfo->got & FETCH_UID) == 0) { - printf("didn't get uid in fetch response?\n"); - } else { - info = camel_folder_summary_index(((CamelFolder *)istore->selected)->summary, id-1); - /* exists, check/update */ - if (info) { - 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); - info = camel_folder_summary_uid(((CamelFolder *)istore->selected)->summary, finfo->uid); - } - } - - if (info) { - if (finfo->got & (FETCH_FLAGS)) { - printf("updating flags for uid '%s'\n", finfo->uid); - info->flags = finfo->flags; - camel_folder_change_info_change_uid(istore->selected->changes, finfo->uid); - } - if (finfo->got & FETCH_MINFO) { - printf("got envelope unexpectedly?\n"); - } - /* other things go here, like body fetches */ - } else { - pending = g_hash_table_lookup(istore->pending_fetch_table, finfo->uid); - - /* we need to create a new info, we only care about flags and minfo */ - - if (pending) - info = pending->info; - else { - info = camel_folder_summary_info_new(((CamelFolder *)istore->selected)->summary); - camel_message_info_set_uid(info, g_strdup(finfo->uid)); - } - - if (finfo->got & FETCH_FLAGS) - info->flags = finfo->flags; - - if (finfo->got & FETCH_MINFO) { - /* if we only use ENVELOPE? */ - camel_message_info_set_subject(info, g_strdup(camel_message_info_subject(finfo->minfo))); - camel_message_info_set_from(info, g_strdup(camel_message_info_from(finfo->minfo))); - camel_message_info_set_to(info, g_strdup(camel_message_info_to(finfo->minfo))); - camel_message_info_set_cc(info, g_strdup(camel_message_info_cc(finfo->minfo))); - info->date_sent = finfo->minfo->date_sent; - camel_folder_summary_add(((CamelFolder *)istore->selected)->summary, info); - camel_folder_change_info_add_uid(istore->selected->changes, finfo->uid); - if (pending) { - e_dlist_remove((EDListNode *)pending); - g_hash_table_remove(istore->pending_fetch_table, finfo->uid); - /*e_memchunk_free(istore->pending_fetch_chunks, pending);*/ - } - } else if (finfo->got & FETCH_HEADER) { - /* if we only use HEADER? */ - CamelMimeParser *mp; - - if (pending == NULL) - camel_message_info_free(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); - camel_object_unref(mp); - camel_message_info_set_uid(info, g_strdup(finfo->uid)); - - camel_folder_summary_add(((CamelFolder *)istore->selected)->summary, info); - camel_folder_change_info_add_uid(istore->selected->changes, finfo->uid); - if (pending) { - /* 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); - /*e_memchunk_free(istore->pending_fetch_chunks, pending);*/ - } - } else if (finfo->got & FETCH_FLAGS) { - if (pending == NULL) { - pending = e_memchunk_alloc(istore->pending_fetch_chunks); - pending->info = info; - g_hash_table_insert(istore->pending_fetch_table, (char *)camel_message_info_uid(info), pending); - e_dlist_addtail(&istore->pending_fetch_list, (EDListNode *)pending); - } - } else { - if (pending == NULL) - camel_message_info_free(info); - printf("got unexpected fetch response?\n"); - imap_dump_fetch(finfo); - } - } - } - } else { - printf("unexpected fetch response, no folder selected?\n"); - } - /*imap_dump_fetch(finfo);*/ - imap_free_fetch(finfo); - - return camel_imapp_engine_skip(ie); -} -#endif - -/* ********************************************************************** */ - -/* should be moved to imapp-utils? - stuff in imapp-utils should be moved to imapp-parse? */ - -/* ********************************************************************** */ - -#if 0 -void -camel_imapp_store_folder_selected(CamelIMAPPStore *store, CamelIMAPPFolder *folder, CamelIMAPPSelectResponse *select) -{ - CamelIMAPPCommand * volatile ic = NULL; - CamelIMAPPStore *istore = (CamelIMAPPStore *)store; - int i; - struct _uidset_state ss; - GPtrArray *fetch; - CamelMessageInfo *info; - struct _pending_fetch *fw, *fn; - - printf("imap folder selected\n"); - - if (select->uidvalidity == folder->uidvalidity - && select->exists == folder->exists - && select->recent == folder->recent - && select->unseen == folder->unseen) { - /* no work to do? */ - return; - } - - istore->pending_fetch_table = g_hash_table_new(g_str_hash, g_str_equal); - istore->pending_fetch_chunks = e_memchunk_new(256, sizeof(struct _pending_fetch)); - - /* perform an update - flags first (and see what we have) */ - CAMEL_TRY { - ic = camel_imapp_engine_command_new(istore->engine, "FETCH", NULL, "FETCH 1:%d (UID FLAGS)", select->exists); - camel_imapp_engine_command_queue(istore->engine, ic); - while (camel_imapp_engine_iterate(istore->engine, ic) > 0) - ; - - if (ic->status->result != IMAP_OK) - camel_exception_throw(1, "fetch failed: %s", ic->status->text); - - /* pending_fetch_list now contains any new messages */ - /* FIXME: how do we work out no-longer present messages? */ - printf("now fetching info for messages?\n"); - uidset_init(&ss, store->engine); - ic = camel_imapp_engine_command_new(istore->engine, "FETCH", NULL, "UID FETCH "); - fw = (struct _pending_fetch *)istore->pending_fetch_list.head; - fn = fw->next; - while (fn) { - info = fw->info; - /* if the uid set fills, then flush the command out */ - if (uidset_add(&ss, ic, camel_message_info_uid(info)) - || (fn->next == NULL && uidset_done(&ss, ic))) { - camel_imapp_engine_command_add(istore->engine, ic, " (FLAGS RFC822.HEADER)"); - camel_imapp_engine_command_queue(istore->engine, ic); - while (camel_imapp_engine_iterate(istore->engine, ic) > 0) - ; - if (ic->status->result != IMAP_OK) - camel_exception_throw(1, "fetch failed: %s", ic->status->text); - /* if not end ... */ - camel_imapp_engine_command_free(istore->engine, ic); - ic = camel_imapp_engine_command_new(istore->engine, "FETCH", NULL, "UID FETCH "); - } - fw = fn; - fn = fn->next; - } - - printf("The pending list should now be empty: %s\n", e_dlist_empty(&istore->pending_fetch_list)?"TRUE":"FALSE"); - for (i=0;i<10;i++) { - info = camel_folder_summary_index(((CamelFolder *)istore->selected)->summary, i); - if (info) { - printf("message info [%d] =\n", i); - camel_message_info_dump(info); - camel_message_info_free(info); - } - } - } CAMEL_CATCH (e) { - /* FIXME: cleanup */ - camel_exception_throw_ex(e); - } CAMEL_DONE; - - g_hash_table_destroy(istore->pending_fetch_table); - istore->pending_fetch_table = NULL; - e_memchunk_destroy(istore->pending_fetch_chunks); - - camel_imapp_engine_command_free(istore->engine, ic); -} -#endif - -#if 0 -/*char *uids[] = {"1", "2", "4", "5", "6", "7", "9", "11", "12", 0};*/ -/*char *uids[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", 0};*/ -char *uids[] = {"1", "3", "5", "7", "9", "11", "12", "13", "14", "15", "20", "21", "24", "25", "26", 0}; - -void -uidset_test(CamelIMAPPEngine *ie) -{ - struct _uidset_state ss; - CamelIMAPPCommand *ic; - int i; - - /*ic = camel_imapp_engine_command_new(ie, 0, "FETCH", NULL, "FETCH ");*/ - uidset_init(&ss, 0, 0); - for (i=0;uids[i];i++) { - if (uidset_add(&ss, uids[i])) { - printf("\n[%d] flushing uids\n", i); - } - } - - if (uidset_done(&ss)) { - printf("\nflushing uids\n"); - } -} -#endif diff --git a/camel/providers/imapp/camel-imapp-store.h b/camel/providers/imapp/camel-imapp-store.h deleted file mode 100644 index c26be59baf..0000000000 --- a/camel/providers/imapp/camel-imapp-store.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-imap-store.h : class for an imap store */ - -/* - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_IMAPP_STORE_H -#define CAMEL_IMAPP_STORE_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include <camel/camel-types.h> -#include <camel/camel-store.h> -#include "camel-imapp-driver.h" -#include "libedataserver/e-memory.h" - -#define CAMEL_IMAPP_STORE_TYPE (camel_imapp_store_get_type ()) -#define CAMEL_IMAPP_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_IMAPP_STORE_TYPE, CamelIMAPPStore)) -#define CAMEL_IMAPP_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_IMAPP_STORE_TYPE, CamelIMAPPStoreClass)) -#define CAMEL_IS_IMAP_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_IMAPP_STORE_TYPE)) - -struct _pending_fetch { - struct _pending_fetch *next; - struct _pending_fetch *prev; - - struct _CamelMessageInfo *info; -}; - -typedef struct { - CamelStore parent_object; - - struct _CamelIMAPPStoreSummary *summary; /* in-memory list of folders */ - struct _CamelIMAPPDriver *driver; /* IMAP processing engine */ - struct _CamelDataCache *cache; - - /* if we had a login error, what to show to user */ - char *login_error; - - GPtrArray *pending_list; -} CamelIMAPPStore; - -typedef struct { - CamelStoreClass parent_class; - -} CamelIMAPPStoreClass; - -/* Standard Camel function */ -CamelType camel_imapp_store_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_IMAPP_STORE_H */ - - diff --git a/camel/providers/imapp/camel-imapp-stream.c b/camel/providers/imapp/camel-imapp-stream.c deleted file mode 100644 index 20876beae2..0000000000 --- a/camel/providers/imapp/camel-imapp-stream.c +++ /dev/null @@ -1,761 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Author: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <stdio.h> -#include <ctype.h> -#include <errno.h> - -#include <glib.h> - -#include <camel/camel-stream-mem.h> - -#include "camel-imapp-stream.h" -#include "camel-imapp-exception.h" - -#define t(x) -#define io(x) x - -static void setup_table(void); - -static CamelObjectClass *parent_class = NULL; - -/* Returns the class for a CamelStream */ -#define CS_CLASS(so) CAMEL_IMAPP_STREAM_CLASS(CAMEL_OBJECT_GET_CLASS(so)) - -#define CAMEL_IMAPP_STREAM_SIZE (4096) -#define CAMEL_IMAPP_STREAM_TOKEN (4096) /* maximum token size */ - -static int -stream_fill(CamelIMAPPStream *is) -{ - int left = 0; - - if (is->source) { - left = is->end - is->ptr; - memcpy(is->buf, is->ptr, left); - is->end = is->buf + left; - is->ptr = is->buf; - left = camel_stream_read(is->source, is->end, CAMEL_IMAPP_STREAM_SIZE - (is->end - is->buf)); - if (left > 0) { - is->end += left; - io(printf("camel_imapp_read: buffer is '%.*s'\n", is->end - is->ptr, is->ptr)); - return is->end - is->ptr; - } else { - io(printf("camel_imapp_read: -1\n")); - return -1; - } - } - - printf("camel_imapp_read: -1\n"); - - return -1; -} - -static ssize_t -stream_read(CamelStream *stream, char *buffer, size_t n) -{ - CamelIMAPPStream *is = (CamelIMAPPStream *)stream; - ssize_t max; - - if (is->literal == 0 || n == 0) - return 0; - - max = is->end - is->ptr; - if (max > 0) { - max = MIN(max, is->literal); - max = MIN(max, n); - memcpy(buffer, is->ptr, max); - is->ptr += max; - } else { - max = MIN(is->literal, n); - max = camel_stream_read(is->source, buffer, max); - if (max <= 0) - return max; - } - - is->literal -= max; - - return max; -} - -static ssize_t -stream_write(CamelStream *stream, const char *buffer, size_t n) -{ - CamelIMAPPStream *is = (CamelIMAPPStream *)stream; - - return camel_stream_write(is->source, buffer, n); -} - -static int -stream_close(CamelStream *stream) -{ - /* nop? */ - return 0; -} - -static int -stream_flush(CamelStream *stream) -{ - /* nop? */ - return 0; -} - -static gboolean -stream_eos(CamelStream *stream) -{ - CamelIMAPPStream *is = (CamelIMAPPStream *)stream; - - return is->literal == 0; -} - -static int -stream_reset(CamelStream *stream) -{ - /* nop? reset literal mode? */ - return 0; -} - -static void -camel_imapp_stream_class_init (CamelStreamClass *camel_imapp_stream_class) -{ - CamelStreamClass *camel_stream_class = (CamelStreamClass *)camel_imapp_stream_class; - - parent_class = camel_type_get_global_classfuncs( CAMEL_OBJECT_TYPE ); - - /* virtual method definition */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->close = stream_close; - camel_stream_class->flush = stream_flush; - camel_stream_class->eos = stream_eos; - camel_stream_class->reset = stream_reset; -} - -static void -camel_imapp_stream_init(CamelIMAPPStream *is, CamelIMAPPStreamClass *isclass) -{ - /* +1 is room for appending a 0 if we need to for a token */ - is->ptr = is->end = is->buf = g_malloc(CAMEL_IMAPP_STREAM_SIZE+1); - is->tokenptr = is->tokenbuf = g_malloc(CAMEL_IMAPP_STREAM_SIZE+1); - is->tokenend = is->tokenbuf + CAMEL_IMAPP_STREAM_SIZE; -} - -static void -camel_imapp_stream_finalise(CamelIMAPPStream *is) -{ - g_free(is->buf); - if (is->source) - camel_object_unref((CamelObject *)is->source); -} - -CamelType -camel_imapp_stream_get_type (void) -{ - static CamelType camel_imapp_stream_type = CAMEL_INVALID_TYPE; - - if (camel_imapp_stream_type == CAMEL_INVALID_TYPE) { - setup_table(); - camel_imapp_stream_type = camel_type_register( camel_stream_get_type(), - "CamelIMAPPStream", - sizeof( CamelIMAPPStream ), - sizeof( CamelIMAPPStreamClass ), - (CamelObjectClassInitFunc) camel_imapp_stream_class_init, - NULL, - (CamelObjectInitFunc) camel_imapp_stream_init, - (CamelObjectFinalizeFunc) camel_imapp_stream_finalise ); - } - - return camel_imapp_stream_type; -} - -/** - * camel_imapp_stream_new: - * - * Returns a NULL stream. A null stream is always at eof, and - * always returns success for all reads and writes. - * - * Return value: the stream - **/ -CamelStream * -camel_imapp_stream_new(CamelStream *source) -{ - CamelIMAPPStream *is; - - is = (CamelIMAPPStream *)camel_object_new(camel_imapp_stream_get_type ()); - camel_object_ref((CamelObject *)source); - is->source = source; - - return (CamelStream *)is; -} - - -/* - From rfc2060 - -ATOM_CHAR ::= <any CHAR except atom_specials> - -atom_specials ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards / - quoted_specials - -CHAR ::= <any 7-bit US-ASCII character except NUL, - 0x01 - 0x7f> - -CTL ::= <any ASCII control character and DEL, - 0x00 - 0x1f, 0x7f> - -SPACE ::= <ASCII SP, space, 0x20> - -list_wildcards ::= "%" / "*" - -quoted_specials ::= <"> / "\" -*/ - -static unsigned char imap_specials[256] = { -/* 00 */0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 10 */0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* 20 */0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, -/* 30 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/* 40 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/* 50 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, -/* 60 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -/* 70 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; - -#define imap_is_atom(c) ((imap_specials[(c)&0xff] & 0x01) != 0) -#define imap_is_simple(c) ((imap_specials[(c)&0xff] & 0x02) != 0) -#define imap_not_id(c) ((imap_specials[(c)&0xff] & 0x04) != 0) - -/* could be pregenerated, but this is cheap */ -static struct { - unsigned char *chars; - unsigned char mask; -} is_masks[] = { - { "\n*()[]+", 2 }, - { " \r\n()[]+", 4 }, -}; - -static void setup_table(void) -{ - int i; - unsigned char *p, c; - - for (i=0;i<(int)(sizeof(is_masks)/sizeof(is_masks[0]));i++) { - p = is_masks[i].chars; - while ((c = *p++)) - imap_specials[c] |= is_masks[i].mask; - } -} - -#if 0 - -static int -skip_ws(CamelIMAPPStream *is, unsigned char *pp, unsigned char *pe) -{ - register unsigned char c, *p; - unsigned char *e; - - p = is->ptr; - e = is->end; - - do { - while (p >= e ) { - is->ptr = p; - if (stream_fill(is) == IMAP_TOK_ERROR) - return IMAP_TOK_ERROR; - p = is->ptr; - e = is->end; - } - c = *p++; - } while (c == ' ' || c == '\r'); - - is->ptr = p; - is->end = e; - - return c; -} -#endif - -/* FIXME: these should probably handle it themselves, - and get rid of the token interface? */ -int -camel_imapp_stream_atom(CamelIMAPPStream *is, unsigned char **data, unsigned int *lenp) -{ - unsigned char *p, c; - - /* this is only 'approximate' atom */ - switch(camel_imapp_stream_token(is, data, lenp)) { - case IMAP_TOK_TOKEN: - p = *data; - while ((c = *p)) - *p++ = toupper(c); - case IMAP_TOK_INT: - return 0; - case IMAP_TOK_ERROR: - return IMAP_TOK_ERROR; - default: - camel_exception_throw(1, "expecting atom"); - printf("expecting atom!\n"); - return IMAP_TOK_PROTOCOL; - } -} - -/* gets an atom, a quoted_string, or a literal */ -int -camel_imapp_stream_astring(CamelIMAPPStream *is, unsigned char **data) -{ - unsigned char *p, *start; - unsigned int len, inlen; - - switch(camel_imapp_stream_token(is, data, &len)) { - case IMAP_TOK_TOKEN: - case IMAP_TOK_INT: - case IMAP_TOK_STRING: - return 0; - case IMAP_TOK_LITERAL: - /* FIXME: just grow buffer */ - if (len >= CAMEL_IMAPP_STREAM_TOKEN) { - camel_exception_throw(1, "astring: literal too long"); - printf("astring too long\n"); - return IMAP_TOK_PROTOCOL; - } - p = is->tokenptr; - camel_imapp_stream_set_literal(is, len); - do { - len = camel_imapp_stream_getl(is, &start, &inlen); - if (len < 0) - return len; - memcpy(p, start, inlen); - p += inlen; - } while (len > 0); - *data = is->tokenptr; - return 0; - case IMAP_TOK_ERROR: - /* wont get unless no exception hanlder*/ - return IMAP_TOK_ERROR; - default: - camel_exception_throw(1, "expecting astring"); - printf("expecting astring!\n"); - return IMAP_TOK_PROTOCOL; - } -} - -/* check for NIL or (small) quoted_string or literal */ -int -camel_imapp_stream_nstring(CamelIMAPPStream *is, unsigned char **data) -{ - unsigned char *p, *start; - unsigned int len, inlen; - - switch(camel_imapp_stream_token(is, data, &len)) { - case IMAP_TOK_STRING: - return 0; - case IMAP_TOK_LITERAL: - /* FIXME: just grow buffer */ - if (len >= CAMEL_IMAPP_STREAM_TOKEN) { - camel_exception_throw(1, "nstring: literal too long"); - return IMAP_TOK_PROTOCOL; - } - p = is->tokenptr; - camel_imapp_stream_set_literal(is, len); - do { - len = camel_imapp_stream_getl(is, &start, &inlen); - if (len < 0) - return len; - memcpy(p, start, inlen); - p += inlen; - } while (len > 0); - *data = is->tokenptr; - return 0; - case IMAP_TOK_TOKEN: - p = *data; - if (toupper(p[0]) == 'N' && toupper(p[1]) == 'I' && toupper(p[2]) == 'L' && p[3] == 0) { - *data = NULL; - return 0; - } - default: - camel_exception_throw(1, "expecting nstring"); - return IMAP_TOK_PROTOCOL; - case IMAP_TOK_ERROR: - /* we'll never get this unless there are no exception handlers anyway */ - return IMAP_TOK_ERROR; - - } -} - -/* parse an nstring as a stream */ -int -camel_imapp_stream_nstring_stream(CamelIMAPPStream *is, CamelStream **stream) -/* throws IO,PARSE exception */ -{ - unsigned char *token; - unsigned int len; - int ret = 0; - CamelStream * volatile mem = NULL; - - *stream = NULL; - - CAMEL_TRY { - switch(camel_imapp_stream_token(is, &token, &len)) { - case IMAP_TOK_STRING: - mem = camel_stream_mem_new_with_buffer(token, len); - *stream = mem; - break; - case IMAP_TOK_LITERAL: - /* if len is big, we could automatically use a file backing */ - camel_imapp_stream_set_literal(is, len); - mem = camel_stream_mem_new(); - if (camel_stream_write_to_stream((CamelStream *)is, mem) == -1) - camel_exception_throw(1, "nstring: io error: %s", strerror(errno)); - camel_stream_reset(mem); - *stream = mem; - break; - case IMAP_TOK_TOKEN: - if (toupper(token[0]) == 'N' && toupper(token[1]) == 'I' && toupper(token[2]) == 'L' && token[3] == 0) { - *stream = NULL; - break; - } - default: - ret = -1; - camel_exception_throw(1, "nstring: token not string"); - } - } CAMEL_CATCH(ex) { - if (mem) - camel_object_unref((CamelObject *)mem); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - /* never reaches here anyway */ - return ret; -} - -guint32 -camel_imapp_stream_number(CamelIMAPPStream *is) -{ - unsigned char *token; - unsigned int len; - - if (camel_imapp_stream_token(is, &token, &len) != IMAP_TOK_INT) { - camel_exception_throw(1, "expecting number"); - return 0; - } - - return strtoul(token, 0, 10); -} - -int -camel_imapp_stream_text(CamelIMAPPStream *is, unsigned char **text) -{ - GByteArray *build = g_byte_array_new(); - unsigned char *token; - unsigned int len; - int tok; - - CAMEL_TRY { - while (is->unget > 0) { - switch (is->unget_tok) { - case IMAP_TOK_TOKEN: - case IMAP_TOK_STRING: - case IMAP_TOK_INT: - g_byte_array_append(build, is->unget_token, is->unget_len); - g_byte_array_append(build, " ", 1); - default: /* invalid, but we'll ignore */ - break; - } - is->unget--; - } - - do { - tok = camel_imapp_stream_gets(is, &token, &len); - if (tok < 0) - camel_exception_throw(1, "io error: %s", strerror(errno)); - if (len) - g_byte_array_append(build, token, len); - } while (tok > 0); - } CAMEL_CATCH(ex) { - *text = NULL; - g_byte_array_free(build, TRUE); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - g_byte_array_append(build, "", 1); - *text = build->data; - g_byte_array_free(build, FALSE); - - return 0; -} - -/* Get one token from the imap stream */ -camel_imapp_token_t -/* throws IO,PARSE exception */ -camel_imapp_stream_token(CamelIMAPPStream *is, unsigned char **data, unsigned int *len) -{ - register unsigned char c, *p, *o, *oe; - unsigned char *e; - unsigned int literal; - int digits; - - if (is->unget > 0) { - is->unget--; - *data = is->unget_token; - *len = is->unget_len; - /*printf("token UNGET '%c' %s\n", is->unget_tok, is->unget_token);*/ - return is->unget_tok; - } - - if (is->literal > 0) - g_warning("stream_token called with literal %d", is->literal); - - p = is->ptr; - e = is->end; - - /* skip whitespace/prefill buffer */ - do { - while (p >= e ) { - is->ptr = p; - if (stream_fill(is) == IMAP_TOK_ERROR) - goto io_error; - p = is->ptr; - e = is->end; - } - c = *p++; - } while (c == ' ' || c == '\r'); - - /*strchr("\n*()[]+", c)*/ - if (imap_is_simple(c)) { - is->ptr = p; - t(printf("token '%c'\n", c)); - return c; - } else if (c == '{') { - literal = 0; - *data = p; - while (1) { - while (p < e) { - c = *p++; - if (isdigit(c) && literal < (UINT_MAX/10)) { - literal = literal * 10 + (c - '0'); - } else if (c == '}') { - while (1) { - while (p < e) { - c = *p++; - if (c == '\n') { - *len = literal; - is->ptr = p; - is->literal = literal; - t(printf("token LITERAL %d\n", literal)); - return IMAP_TOK_LITERAL; - } - } - is->ptr = p; - if (stream_fill(is) == IMAP_TOK_ERROR) - goto io_error; - p = is->ptr; - e = is->end; - } - } else { - if (isdigit(c)) - printf("Protocol error: literal too big\n"); - else - printf("Protocol error: literal contains invalid char %02x '%c'\n", c, isprint(c)?c:c); - goto protocol_error; - } - } - is->ptr = p; - if (stream_fill(is) == IMAP_TOK_ERROR) - goto io_error; - p = is->ptr; - e = is->end; - } - } else if (c == '"') { - o = is->tokenptr; - oe = is->tokenptr + CAMEL_IMAPP_STREAM_TOKEN - 1; - while (1) { - while (p < e) { - c = *p++; - if (c == '\\') { - while (p >= e) { - is->ptr = p; - if (stream_fill(is) == IMAP_TOK_ERROR) - goto io_error; - p = is->ptr; - e = is->end; - } - c = *p++; - } else if (c == '\"') { - is->ptr = p; - *o = 0; - *data = is->tokenbuf; - *len = o - is->tokenbuf; - t(printf("token STRING '%s'\n", is->tokenbuf)); - return IMAP_TOK_STRING; - } - - if (c == '\n' || c == '\r' || o>=oe) { - if (o >= oe) - printf("Protocol error: string too long\n"); - else - printf("Protocol error: truncated string\n"); - goto protocol_error; - } else { - *o++ = c; - } - } - is->ptr = p; - if (stream_fill(is) == IMAP_TOK_ERROR) - goto io_error; - p = is->ptr; - e = is->end; - } - } else { - o = is->tokenptr; - oe = is->tokenptr + CAMEL_IMAPP_STREAM_TOKEN - 1; - digits = isdigit(c); - *o++ = c; - while (1) { - while (p < e) { - c = *p++; - /*if (strchr(" \r\n*()[]+", c) != NULL) {*/ - if (imap_not_id(c)) { - if (c == ' ' || c == '\r') - is->ptr = p; - else - is->ptr = p-1; - *o = 0; - *data = is->tokenbuf; - *len = o - is->tokenbuf; - t(printf("token TOKEN '%s'\n", is->tokenbuf)); - return digits?IMAP_TOK_INT:IMAP_TOK_TOKEN; - } else if (o < oe) { - digits &= isdigit(c); - *o++ = c; - } else { - printf("Protocol error: token too long\n"); - goto protocol_error; - } - } - is->ptr = p; - if (stream_fill(is) == IMAP_TOK_ERROR) - goto io_error; - p = is->ptr; - e = is->end; - } - } - - /* Had an i/o erorr */ -io_error: - printf("Got io error\n"); - camel_exception_throw(1, "io error"); - return IMAP_TOK_ERROR; - - /* Protocol error, skip until next lf? */ -protocol_error: - printf("Got protocol error\n"); - - if (c == '\n') - is->ptr = p-1; - else - is->ptr = p; - - camel_exception_throw(1, "protocol error"); - return IMAP_TOK_PROTOCOL; -} - -void -camel_imapp_stream_ungettoken(CamelIMAPPStream *is, camel_imapp_token_t tok, unsigned char *token, unsigned int len) -{ - /*printf("ungettoken: '%c' '%s'\n", tok, token);*/ - is->unget_tok = tok; - is->unget_token = token; - is->unget_len = len; - is->unget++; -} - -/* returns -1 on error, 0 if last lot of data, >0 if more remaining */ -int camel_imapp_stream_gets(CamelIMAPPStream *is, unsigned char **start, unsigned int *len) -{ - int max; - unsigned char *end; - - *len = 0; - - max = is->end - is->ptr; - if (max == 0) { - max = stream_fill(is); - if (max <= 0) - return max; - } - - *start = is->ptr; - end = memchr(is->ptr, '\n', max); - if (end) - max = (end - is->ptr) + 1; - *start = is->ptr; - *len = max; - is->ptr += max; - - return end == NULL?1:0; -} - -void camel_imapp_stream_set_literal(CamelIMAPPStream *is, unsigned int literal) -{ - is->literal = literal; -} - -/* returns -1 on erorr, 0 if last data, >0 if more data left */ -int camel_imapp_stream_getl(CamelIMAPPStream *is, unsigned char **start, unsigned int *len) -{ - int max; - - *len = 0; - - if (is->literal > 0) { - max = is->end - is->ptr; - if (max == 0) { - max = stream_fill(is); - if (max <= 0) - return max; - } - - max = MIN(max, is->literal); - *start = is->ptr; - *len = max; - is->ptr += max; - is->literal -= max; - } - - if (is->literal > 0) - return 1; - - return 0; -} diff --git a/camel/providers/imapp/camel-imapp-stream.h b/camel/providers/imapp/camel-imapp-stream.h deleted file mode 100644 index 802c018672..0000000000 --- a/camel/providers/imapp/camel-imapp-stream.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_IMAPP_STREAM_H -#define _CAMEL_IMAPP_STREAM_H - -#include <camel/camel-stream.h> - -#define CAMEL_IMAPP_STREAM(obj) CAMEL_CHECK_CAST (obj, camel_imapp_stream_get_type (), CamelIMAPPStream) -#define CAMEL_IMAPP_STREAM_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imapp_stream_get_type (), CamelIMAPPStreamClass) -#define CAMEL_IS_IMAP_STREAM(obj) CAMEL_CHECK_TYPE (obj, camel_imapp_stream_get_type ()) - -typedef struct _CamelIMAPPStreamClass CamelIMAPPStreamClass; -typedef struct _CamelIMAPPStream CamelIMAPPStream; - -typedef enum { - IMAP_TOK_PROTOCOL = -2, - IMAP_TOK_ERROR = -1, - IMAP_TOK_TOKEN = 256, - IMAP_TOK_STRING, - IMAP_TOK_INT, - IMAP_TOK_LITERAL, -} camel_imapp_token_t; - -struct _CamelIMAPPStream { - CamelStream parent; - - CamelStream *source; - - /*int state;*/ - unsigned char *buf, *ptr, *end; - unsigned int literal; - - unsigned int unget; - camel_imapp_token_t unget_tok; - unsigned char *unget_token; - unsigned int unget_len; - - unsigned char *tokenbuf, *tokenptr, *tokenend; -}; - -struct _CamelIMAPPStreamClass { - CamelStreamClass parent_class; -}; - -CamelType camel_imapp_stream_get_type (void); - -CamelStream *camel_imapp_stream_new (CamelStream *source); - -camel_imapp_token_t camel_imapp_stream_token (CamelIMAPPStream *is, unsigned char **start, unsigned int *len); /* throws IO,PARSE exception */ -void camel_imapp_stream_ungettoken (CamelIMAPPStream *is, camel_imapp_token_t tok, unsigned char *token, unsigned int len); - -void camel_imapp_stream_set_literal (CamelIMAPPStream *is, unsigned int literal); -int camel_imapp_stream_gets (CamelIMAPPStream *is, unsigned char **start, unsigned int *len); -int camel_imapp_stream_getl (CamelIMAPPStream *is, unsigned char **start, unsigned int *len); - -/* all throw IO,PARSE exceptions */ - -/* gets an atom, upper-cases */ -int camel_imapp_stream_atom (CamelIMAPPStream *is, unsigned char **start, unsigned int *len); -/* gets an atom or string */ -int camel_imapp_stream_astring (CamelIMAPPStream *is, unsigned char **start); -/* gets a NIL or a string, start==NULL if NIL */ -int camel_imapp_stream_nstring (CamelIMAPPStream *is, unsigned char **start); -/* gets a NIL or string into a stream, stream==NULL if NIL */ -int camel_imapp_stream_nstring_stream(CamelIMAPPStream *is, CamelStream **stream); -/* gets 'text' */ -int camel_imapp_stream_text (CamelIMAPPStream *is, unsigned char **text); - -/* gets a 'number' */ -guint32 camel_imapp_stream_number(CamelIMAPPStream *is); - -#endif /* ! _CAMEL_IMAPP_STREAM_H */ diff --git a/camel/providers/imapp/camel-imapp-summary.c b/camel/providers/imapp/camel-imapp-summary.c deleted file mode 100644 index 1b5a2c7155..0000000000 --- a/camel/providers/imapp/camel-imapp-summary.c +++ /dev/null @@ -1,184 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright(C) 2000 Ximian Inc. - * - * Authors: - * Michael Zucchi <notzed@ximian.com> - * Dan Winship <danw@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/stat.h> -#include <sys/uio.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> - -#include "camel-imapp-summary.h" -#include <camel/camel-file-utils.h> - -#define CAMEL_IMAPP_SUMMARY_VERSION (1) - -static int summary_header_load(CamelFolderSummary *, FILE *); -static int summary_header_save(CamelFolderSummary *, FILE *); - -static CamelMessageInfo *message_info_load(CamelFolderSummary *s, FILE *in); -static int message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *info); - -static void camel_imapp_summary_class_init(CamelIMAPPSummaryClass *klass); -static void camel_imapp_summary_init (CamelIMAPPSummary *obj); - -static CamelFolderSummaryClass *camel_imapp_summary_parent; - -CamelType -camel_imapp_summary_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register( - camel_folder_summary_get_type(), "CamelIMAPPSummary", - sizeof(CamelIMAPPSummary), - sizeof(CamelIMAPPSummaryClass), - (CamelObjectClassInitFunc) camel_imapp_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_imapp_summary_init, - NULL); - } - - return type; -} - -static void -camel_imapp_summary_class_init(CamelIMAPPSummaryClass *klass) -{ - CamelFolderSummaryClass *cfs_class =(CamelFolderSummaryClass *) klass; - - camel_imapp_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS(camel_type_get_global_classfuncs(camel_folder_summary_get_type())); - - cfs_class->summary_header_load = summary_header_load; - cfs_class->summary_header_save = summary_header_save; - cfs_class->message_info_load = message_info_load; - cfs_class->message_info_save = message_info_save; -} - -static void -camel_imapp_summary_init(CamelIMAPPSummary *obj) -{ - CamelFolderSummary *s =(CamelFolderSummary *)obj; - - /* subclasses need to set the right instance data sizes */ - s->message_info_size = sizeof(CamelIMAPPMessageInfo); - s->content_info_size = sizeof(CamelMessageContentInfo); - - /* and a unique file version */ - s->version += CAMEL_IMAPP_SUMMARY_VERSION; -} - -/** - * camel_imapp_summary_new: - * @filename: the file to store the summary in. - * - * This will create a new CamelIMAPPSummary object and read in the - * summary data from disk, if it exists. - * - * Return value: A new CamelIMAPPSummary object. - **/ -CamelFolderSummary * -camel_imapp_summary_new(void) -{ - CamelFolderSummary *summary = CAMEL_FOLDER_SUMMARY(camel_object_new(camel_imapp_summary_get_type())); - - return summary; -} - - -static int -summary_header_load(CamelFolderSummary *s, FILE *in) -{ - CamelIMAPPSummary *ims = CAMEL_IMAPP_SUMMARY(s); - - if (camel_imapp_summary_parent->summary_header_load(s, in) == -1) - return -1; - - /* Legacy version */ - if (s->version == 0x100c) - return camel_file_util_decode_uint32(in, &ims->uidvalidity); - - if (camel_file_util_decode_fixed_int32(in, &ims->version) == -1 - || camel_file_util_decode_fixed_int32(in, &ims->uidvalidity) == -1) - return -1; - - if (ims->version > CAMEL_IMAPP_SUMMARY_VERSION) { - g_warning("Unkown summary version\n"); - errno = EINVAL; - return -1; - } - - return 0; -} - -static int -summary_header_save(CamelFolderSummary *s, FILE *out) -{ - CamelIMAPPSummary *ims = CAMEL_IMAPP_SUMMARY(s); - - if (camel_imapp_summary_parent->summary_header_save(s, out) == -1) - return -1; - - if (camel_file_util_encode_fixed_int32(out, CAMEL_IMAPP_SUMMARY_VERSION) == -1 - || camel_file_util_encode_fixed_int32(out, ims->uidvalidity) == -1) - return -1; - - return 0; -} - - -static CamelMessageInfo * -message_info_load(CamelFolderSummary *s, FILE *in) -{ - CamelMessageInfo *info; - CamelIMAPPMessageInfo *iinfo; - - info = camel_imapp_summary_parent->message_info_load(s, in); - if (info) { - iinfo =(CamelIMAPPMessageInfo *)info; - - if (camel_file_util_decode_uint32(in, &iinfo->server_flags) == -1) - goto error; - } - - return info; -error: - camel_message_info_free(info); - return NULL; -} - -static int -message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *info) -{ - CamelIMAPPMessageInfo *iinfo =(CamelIMAPPMessageInfo *)info; - - if (camel_imapp_summary_parent->message_info_save(s, out, info) == -1) - return -1; - - return camel_file_util_encode_uint32(out, iinfo->server_flags); -} diff --git a/camel/providers/imapp/camel-imapp-summary.h b/camel/providers/imapp/camel-imapp-summary.h deleted file mode 100644 index 1189bac075..0000000000 --- a/camel/providers/imapp/camel-imapp-summary.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: - * Michael Zucchi <notzed@ximian.com> - * Dan Winship <danw@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_IMAPP_SUMMARY_H -#define _CAMEL_IMAPP_SUMMARY_H - -#include <camel/camel-folder-summary.h> -#include <camel/camel-exception.h> - -#define CAMEL_IMAPP_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_imapp_summary_get_type (), CamelIMAPPSummary) -#define CAMEL_IMAPP_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_imapp_summary_get_type (), CamelIMAPPSummaryClass) -#define CAMEL_IS_IMAPP_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_imapp_summary_get_type ()) - -#define CAMEL_IMAPP_SERVER_FLAGS (CAMEL_MESSAGE_ANSWERED | \ - CAMEL_MESSAGE_DELETED | \ - CAMEL_MESSAGE_DRAFT | \ - CAMEL_MESSAGE_FLAGGED | \ - CAMEL_MESSAGE_SEEN) - -#define CAMEL_IMAPP_MESSAGE_RECENT (1 << 8) - -typedef struct _CamelIMAPPSummaryClass CamelIMAPPSummaryClass; -typedef struct _CamelIMAPPSummary CamelIMAPPSummary; - -typedef struct _CamelIMAPPMessageInfo { - CamelMessageInfoBase info; - - guint32 server_flags; -} CamelIMAPPMessageInfo; - -struct _CamelIMAPPSummary { - CamelFolderSummary parent; - - guint32 version; - guint32 uidvalidity; -}; - -struct _CamelIMAPPSummaryClass { - CamelFolderSummaryClass parent_class; - -}; - -CamelType camel_imapp_summary_get_type (void); -CamelFolderSummary *camel_imapp_summary_new (void); - -#endif /* ! _CAMEL_IMAPP_SUMMARY_H */ - diff --git a/camel/providers/imapp/camel-imapp-utils.c b/camel/providers/imapp/camel-imapp-utils.c deleted file mode 100644 index 1460157848..0000000000 --- a/camel/providers/imapp/camel-imapp-utils.c +++ /dev/null @@ -1,1342 +0,0 @@ - -#include <ctype.h> -#include <errno.h> -#include <string.h> - -#include <camel/camel-folder-summary.h> -#include <camel/camel-store.h> -#include <camel/camel-utf8.h> -#include <camel/camel-string-utils.h> - -#include "camel-imapp-folder.h" -#include "camel-imapp-stream.h" -#include "camel-imapp-utils.h" -#include "camel-imapp-exception.h" -#include "camel-imapp-engine.h" -#include "libedataserver/e-memory.h" - -/* high-level parser state */ -#define p(x) -/* debug */ -#define d(x) - -/* ANSI-C code produced by gperf version 2.7 */ -/* Command-line: gperf -H imap_hash -N imap_tokenise -L ANSI-C -o -t -k1,$ imap-tokens.txt */ -struct _imap_keyword { char *name; enum _imap_id id; }; -/* - gperf input file - best hash generated using: gperf -o -s-2 -k1,'$' -t -H imap_hash -N imap_tokenise -L ANSI-C -*/ - -#define TOTAL_KEYWORDS 23 -#define MIN_WORD_LENGTH 2 -#define MAX_WORD_LENGTH 14 -#define MIN_HASH_VALUE 2 -#define MAX_HASH_VALUE 38 -/* maximum key range = 37, duplicates = 0 */ - -#ifdef __GNUC__ -__inline -#endif -static unsigned int -imap_hash (register const char *str, register unsigned int len) -{ - static unsigned char asso_values[] = - { - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 10, 15, 39, 20, 0, - 0, 39, 0, 10, 39, 0, 39, 39, 10, 0, - 0, 39, 0, 10, 5, 10, 39, 39, 39, 0, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39 - }; - return len + asso_values[(unsigned char)str[len - 1]] + asso_values[(unsigned char)str[0]]; -} - -#ifdef __GNUC__ -__inline -#endif -enum _imap_id -imap_tokenise (register const char *str, register unsigned int len) -{ - static struct _imap_keyword wordlist[] = - { - {""}, {""}, - {"OK", IMAP_OK}, - {""}, {""}, - {"PARSE", IMAP_PARSE}, - {""}, - {"PREAUTH", IMAP_PREAUTH}, - {"ENVELOPE", IMAP_ENVELOPE}, - {"READ-ONLY", IMAP_READ_ONLY}, - {"READ-WRITE", IMAP_READ_WRITE}, - {"RFC822.SIZE", IMAP_RFC822_SIZE}, - {"NO", IMAP_NO}, - {"RFC822.HEADER", IMAP_RFC822_HEADER}, - {"TRYCREATE", IMAP_TRYCREATE}, - {"FLAGS", IMAP_FLAGS}, - {"RFC822.TEXT", IMAP_RFC822_TEXT}, - {"NEWNAME", IMAP_NEWNAME}, - {"BYE", IMAP_BYE}, - {"BODY", IMAP_BODY}, - {"ALERT", IMAP_ALERT}, - {"UIDVALIDITY", IMAP_UIDVALIDITY}, - {"INTERNALDATE", IMAP_INTERNALDATE}, - {""}, - {"PERMANENTFLAGS", IMAP_PERMANENTFLAGS}, - {""}, - {"UNSEEN", IMAP_UNSEEN}, - {""}, - {"BODYSTRUCTURE", IMAP_BODYSTRUCTURE}, - {""}, {""}, {""}, {""}, - {"UID", IMAP_UID}, - {""}, {""}, {""}, {""}, - {"BAD", IMAP_BAD} - }; - - if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) - { - register int key = imap_hash (str, len); - - if (key <= MAX_HASH_VALUE && key >= 0) - { - register const char *s = wordlist[key].name; - - if (*str == *s && !strcmp (str + 1, s + 1)) - return wordlist[key].id; - } - } - return 0; -} - -/* flag table */ -static struct { - char *name; - guint32 flag; -} flag_table[] = { - { "\\ANSWERED", CAMEL_MESSAGE_ANSWERED }, - { "\\DELETED", CAMEL_MESSAGE_DELETED }, - { "\\DRAFT", CAMEL_MESSAGE_DRAFT }, - { "\\FLAGGED", CAMEL_MESSAGE_FLAGGED }, - { "\\SEEN", CAMEL_MESSAGE_SEEN }, - { "\\RECENT", CAMEL_IMAPP_MESSAGE_RECENT }, - { "\\*", CAMEL_MESSAGE_USER }, -}; - -/* utility functions - shoudl this be part of imapp-driver? */ -/* mabye this should be a stream op? */ -void -imap_parse_flags(CamelIMAPPStream *stream, guint32 *flagsp) -/* throws IO,PARSE exception */ -{ - int tok, len, i; - unsigned char *token, *p, c; - guint32 flags = 0; - - *flagsp = flags; - - tok = camel_imapp_stream_token(stream, &token, &len); - if (tok == '(') { - do { - tok = camel_imapp_stream_token(stream, &token, &len); - if (tok == IMAP_TOK_TOKEN) { - p = token; - while ((c=*p)) - *p++ = toupper(c); - for (i=0;i<(int)(sizeof(flag_table)/sizeof(flag_table[0]));i++) - if (!strcmp(token, flag_table[i].name)) - flags |= flag_table[i].flag; - } else if (tok != ')') { - camel_exception_throw(1, "expecting flag"); - } - } while (tok != ')'); - } else { - camel_exception_throw(1, "expecting flag list"); - } - - *flagsp = flags; -} - -void -imap_write_flags(CamelStream *stream, guint32 flags) -/* throws IO exception */ -{ - int i; - - /* all this ugly exception throwing goes away once camel streams throw their own? */ - if (camel_stream_write(stream, "(", 1) == -1) - camel_exception_throw(1, "io error: %s", strerror(errno)); - - for (i=0;flags!=0 && i<(int)(sizeof(flag_table)/sizeof(flag_table[0]));i++) { - if (flag_table[i].flag & flags) { - if (camel_stream_write(stream, flag_table[i].name, strlen(flag_table[i].name)) == -1) - camel_exception_throw(1, "io error: %s", strerror(errno)); - flags &= ~flag_table[i].flag; - if (flags != 0) - if (camel_stream_write(stream, " ", 1) == -1) - camel_exception_throw(1, "io error: %s", strerror(errno)); - } - } - - if (camel_stream_write(stream, ")", 1) == -1) - camel_exception_throw(1, "io error: %s", strerror(errno)); -} - -/* -body ::= "(" body_type_1part / body_type_mpart ")" - -body_extension ::= nstring / number / "(" 1#body_extension ")" - ;; Future expansion. Client implementations - ;; MUST accept body_extension fields. Server - ;; implementations MUST NOT generate - ;; body_extension fields except as defined by - ;; future standard or standards-track - ;; revisions of this specification. - -body_ext_1part ::= body_fld_md5 [SPACE body_fld_dsp - [SPACE body_fld_lang - [SPACE 1#body_extension]]] - ;; MUST NOT be returned on non-extensible - ;; "BODY" fetch - -body_ext_mpart ::= body_fld_param - [SPACE body_fld_dsp SPACE body_fld_lang - [SPACE 1#body_extension]] - ;; MUST NOT be returned on non-extensible - ;; "BODY" fetch - -body_fields ::= body_fld_param SPACE body_fld_id SPACE - body_fld_desc SPACE body_fld_enc SPACE - body_fld_octets - -body_fld_desc ::= nstring - -body_fld_dsp ::= "(" string SPACE body_fld_param ")" / nil - -body_fld_enc ::= (<"> ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ - "QUOTED-PRINTABLE") <">) / string - -body_fld_id ::= nstring - -body_fld_lang ::= nstring / "(" 1#string ")" - -body_fld_lines ::= number - -body_fld_md5 ::= nstring - -body_fld_octets ::= number - -body_fld_param ::= "(" 1#(string SPACE string) ")" / nil - -body_type_1part ::= (body_type_basic / body_type_msg / body_type_text) - [SPACE body_ext_1part] - -body_type_basic ::= media_basic SPACE body_fields - ;; MESSAGE subtype MUST NOT be "RFC822" - -body_type_mpart ::= 1*body SPACE media_subtype - [SPACE body_ext_mpart] - -body_type_msg ::= media_message SPACE body_fields SPACE envelope - SPACE body SPACE body_fld_lines - -body_type_text ::= media_text SPACE body_fields SPACE body_fld_lines - -envelope ::= "(" env_date SPACE env_subject SPACE env_from - SPACE env_sender SPACE env_reply_to SPACE env_to - SPACE env_cc SPACE env_bcc SPACE env_in_reply_to - SPACE env_message_id ")" - -env_bcc ::= "(" 1*address ")" / nil - -env_cc ::= "(" 1*address ")" / nil - -env_date ::= nstring - -env_from ::= "(" 1*address ")" / nil - -env_in_reply_to ::= nstring - -env_message_id ::= nstring - -env_reply_to ::= "(" 1*address ")" / nil - -env_sender ::= "(" 1*address ")" / nil - -env_subject ::= nstring - -env_to ::= "(" 1*address ")" / nil - -media_basic ::= (<"> ("APPLICATION" / "AUDIO" / "IMAGE" / - "MESSAGE" / "VIDEO") <">) / string) - SPACE media_subtype - ;; Defined in [MIME-IMT] - -media_message ::= <"> "MESSAGE" <"> SPACE <"> "RFC822" <"> - ;; Defined in [MIME-IMT] - -media_subtype ::= string - ;; Defined in [MIME-IMT] - -media_text ::= <"> "TEXT" <"> SPACE media_subtype - ;; Defined in [MIME-IMT] - - - - ( "type" "subtype" body_fields [envelope body body_fld_lines] - [body_fld_lines] - - - - (("TEXT" "PLAIN" ("CHARSET" - "US-ASCII") NIL NIL "7BIT" 1152 23)("TEXT" "PLAIN" - ("CHARSET" "US-ASCII" "NAME" "cc.diff") - "<960723163407.20117h@cac.washington.edu>" - "Compiler diff" "BASE64" 4554 73) "MIXED")) - -*/ - -/* -struct _body_fields { - CamelContentType *ct; - char *msgid, *desc; - CamelTransferEncoding encoding; - guint32 size; - };*/ - -void -imap_free_body(struct _CamelMessageContentInfo *cinfo) -{ - struct _CamelMessageContentInfo *list, *next; - - list = cinfo->childs; - while (list) { - next = list->next; - imap_free_body(list); - list = next; - } - - if (cinfo->type) - camel_content_type_unref(cinfo->type); - g_free(cinfo->id); - g_free(cinfo->description); - g_free(cinfo->encoding); - g_free(cinfo); -} - -void -imap_parse_param_list(CamelIMAPPStream *is, struct _camel_header_param **plist) -{ - int tok, len; - unsigned char *token, *param; - - p(printf("body_fld_param\n")); - - /* body_fld_param ::= "(" 1#(string SPACE string) ")" / nil */ - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == '(') { - while (1) { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == ')') - break; - camel_imapp_stream_ungettoken(is, tok, token, len); - - camel_imapp_stream_astring(is, &token); - param = alloca(strlen(token)+1); - strcpy(param, token); - camel_imapp_stream_astring(is, &token); - camel_header_set_param(plist, param, token); - } - } /* else check nil? no need */ -} - -struct _CamelContentDisposition * -imap_parse_ext_optional(CamelIMAPPStream *is) -{ - int tok, len; - unsigned char *token; - struct _CamelContentDisposition * volatile dinfo = NULL; - - /* this parses both extension types, from the body_fld_dsp onwards */ - /* although the grammars are different, they can be parsed the same way */ - - /* body_ext_1part ::= body_fld_md5 [SPACE body_fld_dsp - [SPACE body_fld_lang - [SPACE 1#body_extension]]] - ;; MUST NOT be returned on non-extensible - ;; "BODY" fetch */ - - /* body_ext_mpart ::= body_fld_param - [SPACE body_fld_dsp SPACE body_fld_lang - [SPACE 1#body_extension]] - ;; MUST NOT be returned on non-extensible - ;; "BODY" fetch */ - - CAMEL_TRY { - /* body_fld_dsp ::= "(" string SPACE body_fld_param ")" / nil */ - - tok = camel_imapp_stream_token(is, &token, &len); - switch (tok) { - case '(': - dinfo = g_malloc0(sizeof(*dinfo)); - dinfo->refcount = 1; - /* should be string */ - camel_imapp_stream_astring(is, &token); - - dinfo->disposition = g_strdup(token); - imap_parse_param_list(is, &dinfo->params); - case IMAP_TOK_TOKEN: - d(printf("body_fld_dsp: NIL\n")); - break; - default: - camel_exception_throw(1, "body_fld_disp: expecting nil or list"); - } - - p(printf("body_fld_lang\n")); - - /* body_fld_lang ::= nstring / "(" 1#string ")" */ - - /* we just drop the lang string/list, save it somewhere? */ - - tok = camel_imapp_stream_token(is, &token, &len); - switch (tok) { - case '(': - while (1) { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == ')') { - break; - } else if (tok != IMAP_TOK_STRING) { - camel_exception_throw(1, "expecting string"); - } - } - break; - case IMAP_TOK_TOKEN: - d(printf("body_fld_lang = nil\n")); - /* treat as 'nil' */ - break; - case IMAP_TOK_STRING: - /* we have a string */ - break; - case IMAP_TOK_LITERAL: - /* we have a literal string */ - camel_imapp_stream_set_literal(is, len); - while ((tok = camel_imapp_stream_getl(is, &token, &len)) > 0) { - d(printf("Skip literal data '%.*s'\n", (int)len, token)); - } - break; - - } - } CAMEL_CATCH(ex) { - if (dinfo) - camel_content_disposition_unref(dinfo); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - return dinfo; -} - -struct _CamelMessageContentInfo * -imap_parse_body_fields(CamelIMAPPStream *is) -{ - unsigned char *token, *type; - struct _CamelMessageContentInfo *cinfo; - - /* body_fields ::= body_fld_param SPACE body_fld_id SPACE - body_fld_desc SPACE body_fld_enc SPACE - body_fld_octets */ - - p(printf("body_fields\n")); - - cinfo = g_malloc0(sizeof(*cinfo)); - - CAMEL_TRY { - /* this should be string not astring */ - camel_imapp_stream_astring(is, &token); - type = alloca(strlen(token)+1); - strcpy(type, token); - camel_imapp_stream_astring(is, &token); - cinfo->type = camel_content_type_new(type, token); - imap_parse_param_list(is, &cinfo->type->params); - - /* body_fld_id ::= nstring */ - camel_imapp_stream_nstring(is, &token); - cinfo->id = g_strdup(token); - - /* body_fld_desc ::= nstring */ - camel_imapp_stream_nstring(is, &token); - cinfo->description = g_strdup(token); - - /* body_fld_enc ::= (<"> ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ - "QUOTED-PRINTABLE") <">) / string */ - camel_imapp_stream_astring(is, &token); - cinfo->encoding = g_strdup(token); - - /* body_fld_octets ::= number */ - cinfo->size = camel_imapp_stream_number(is); - } CAMEL_CATCH(ex) { - imap_free_body(cinfo); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - return cinfo; -} - -struct _camel_header_address * -imap_parse_address_list(CamelIMAPPStream *is) -/* throws PARSE,IO exception */ -{ - int tok, len; - unsigned char *token, *host, *mbox; - struct _camel_header_address *list = NULL; - - /* "(" 1*address ")" / nil */ - - CAMEL_TRY { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == '(') { - while (1) { - struct _camel_header_address *addr, *group = NULL; - - /* address ::= "(" addr_name SPACE addr_adl SPACE addr_mailbox - SPACE addr_host ")" */ - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == ')') - break; - if (tok != '(') - camel_exception_throw(1, "missing '(' for address"); - - addr = camel_header_address_new(); - addr->type = CAMEL_HEADER_ADDRESS_NAME; - tok = camel_imapp_stream_nstring(is, &token); - addr->name = g_strdup(token); - /* we ignore the route, nobody uses it in the real world */ - tok = camel_imapp_stream_nstring(is, &token); - - /* [RFC-822] group syntax is indicated by a special - form of address structure in which the host name - field is NIL. If the mailbox name field is also - NIL, this is an end of group marker (semi-colon in - RFC 822 syntax). If the mailbox name field is - non-NIL, this is a start of group marker, and the - mailbox name field holds the group name phrase. */ - - tok = camel_imapp_stream_nstring(is, &mbox); - mbox = g_strdup(mbox); - tok = camel_imapp_stream_nstring(is, &host); - if (host == NULL) { - if (mbox == NULL) { - group = NULL; - } else { - d(printf("adding group '%s'\n", mbox)); - g_free(addr->name); - addr->name = mbox; - addr->type = CAMEL_HEADER_ADDRESS_GROUP; - camel_header_address_list_append(&list, addr); - group = addr; - } - } else { - addr->v.addr = g_strdup_printf("%s%s%s", mbox?(char *)mbox:"", host?"@":"", host?(char *)host:""); - g_free(mbox); - d(printf("adding address '%s'\n", addr->v.addr)); - if (group != NULL) - camel_header_address_add_member(group, addr); - else - camel_header_address_list_append(&list, addr); - } - do { - tok = camel_imapp_stream_token(is, &token, &len); - } while (tok != ')'); - } - } else { - d(printf("empty, nil '%s'\n", token)); - } - } CAMEL_CATCH(ex) { - camel_header_address_list_clear(&list); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - return list; -} - -struct _CamelMessageInfo * -imap_parse_envelope(CamelIMAPPStream *is) -{ - int tok, len; - unsigned char *token; - struct _camel_header_address *addr, *addr_from; - char *addrstr; - struct _CamelMessageInfoBase *minfo; - - /* envelope ::= "(" env_date SPACE env_subject SPACE env_from - SPACE env_sender SPACE env_reply_to SPACE env_to - SPACE env_cc SPACE env_bcc SPACE env_in_reply_to - SPACE env_message_id ")" */ - - p(printf("envelope\n")); - - minfo = (CamelMessageInfoBase *)camel_message_info_new(NULL); - - CAMEL_TRY { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok != '(') - camel_exception_throw(1, "envelope: expecting '('"); - - /* env_date ::= nstring */ - camel_imapp_stream_nstring(is, &token); - minfo->date_sent = camel_header_decode_date(token, NULL); - - /* env_subject ::= nstring */ - tok = camel_imapp_stream_nstring(is, &token); - minfo->subject = camel_pstring_strdup(token); - - /* we merge from/sender into from, append should probably merge more smartly? */ - - /* env_from ::= "(" 1*address ")" / nil */ - addr_from = imap_parse_address_list(is); - - /* env_sender ::= "(" 1*address ")" / nil */ - addr = imap_parse_address_list(is); - if (addr_from) { - camel_header_address_list_clear(&addr); -#if 0 - if (addr) - camel_header_address_list_append_list(&addr_from, &addr); -#endif - } else { - if (addr) - addr_from = addr; - } - - if (addr_from) { - addrstr = camel_header_address_list_format(addr_from); - minfo->from = camel_pstring_strdup(addrstr); - g_free(addrstr); - camel_header_address_list_clear(&addr_from); - } - - /* we dont keep reply_to */ - - /* env_reply_to ::= "(" 1*address ")" / nil */ - addr = imap_parse_address_list(is); - camel_header_address_list_clear(&addr); - - /* env_to ::= "(" 1*address ")" / nil */ - addr = imap_parse_address_list(is); - if (addr) { - addrstr = camel_header_address_list_format(addr); - minfo->to = camel_pstring_strdup(addrstr); - g_free(addrstr); - camel_header_address_list_clear(&addr); - } - - /* env_cc ::= "(" 1*address ")" / nil */ - addr = imap_parse_address_list(is); - if (addr) { - addrstr = camel_header_address_list_format(addr); - minfo->cc = camel_pstring_strdup(addrstr); - g_free(addrstr); - camel_header_address_list_clear(&addr); - } - - /* we dont keep bcc either */ - - /* env_bcc ::= "(" 1*address ")" / nil */ - addr = imap_parse_address_list(is); - camel_header_address_list_clear(&addr); - - /* FIXME: need to put in-reply-to into references hash list */ - - /* env_in_reply_to ::= nstring */ - tok = camel_imapp_stream_nstring(is, &token); - - /* FIXME: need to put message-id into message-id hash */ - - /* env_message_id ::= nstring */ - tok = camel_imapp_stream_nstring(is, &token); - - tok = camel_imapp_stream_token(is, &token, &len); - if (tok != ')') - camel_exception_throw(1, "expecting ')'"); - } CAMEL_CATCH(ex) { - camel_message_info_free(minfo); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - return (CamelMessageInfo *)minfo; -} - -struct _CamelMessageContentInfo * -imap_parse_body(CamelIMAPPStream *is) -{ - int tok, len; - unsigned char *token; - struct _CamelMessageContentInfo * volatile cinfo = NULL; - struct _CamelMessageContentInfo *subinfo, *last; - struct _CamelContentDisposition * volatile dinfo = NULL; - struct _CamelMessageInfo * volatile minfo = NULL; - - /* body ::= "(" body_type_1part / body_type_mpart ")" */ - - p(printf("body\n")); - - CAMEL_TRY { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok != '(') - camel_exception_throw(1, "body: expecting '('"); - - /* 1*body (optional for multiparts) */ - tok = camel_imapp_stream_token(is, &token, &len); - camel_imapp_stream_ungettoken(is, tok, token, len); - if (tok == '(') { - /* body_type_mpart ::= 1*body SPACE media_subtype - [SPACE body_ext_mpart] */ - - cinfo = g_malloc0(sizeof(*cinfo)); - last = (struct _CamelMessageContentInfo *)&cinfo->childs; - do { - subinfo = imap_parse_body(is); - last->next = subinfo; - last = subinfo; - subinfo->parent = cinfo; - tok = camel_imapp_stream_token(is, &token, &len); - camel_imapp_stream_ungettoken(is, tok, token, len); - } while (tok == '('); - - d(printf("media_subtype\n")); - - camel_imapp_stream_astring(is, &token); - cinfo->type = camel_content_type_new("multipart", token); - - /* body_ext_mpart ::= body_fld_param - [SPACE body_fld_dsp SPACE body_fld_lang - [SPACE 1#body_extension]] - ;; MUST NOT be returned on non-extensible - ;; "BODY" fetch */ - - d(printf("body_ext_mpart\n")); - - tok = camel_imapp_stream_token(is, &token, &len); - camel_imapp_stream_ungettoken(is, tok, token, len); - if (tok == '(') { - imap_parse_param_list(is, &cinfo->type->params); - - /* body_fld_dsp ::= "(" string SPACE body_fld_param ")" / nil */ - - tok = camel_imapp_stream_token(is, &token, &len); - camel_imapp_stream_ungettoken(is, tok, token, len); - if (tok == '(' || tok == IMAP_TOK_TOKEN) { - dinfo = imap_parse_ext_optional(is); - /* other extension fields?, soaked up below */ - } else { - camel_imapp_stream_ungettoken(is, tok, token, len); - } - } - } else { - /* body_type_1part ::= (body_type_basic / body_type_msg / body_type_text) - [SPACE body_ext_1part] - - body_type_basic ::= media_basic SPACE body_fields - body_type_text ::= media_text SPACE body_fields SPACE body_fld_lines - body_type_msg ::= media_message SPACE body_fields SPACE envelope - SPACE body SPACE body_fld_lines */ - - d(printf("Single part body\n")); - - cinfo = imap_parse_body_fields(is); - - d(printf("envelope?\n")); - - /* do we have an envelope following */ - tok = camel_imapp_stream_token(is, &token, &len); - camel_imapp_stream_ungettoken(is, tok, token, len); - if (tok == '(') { - /* what do we do with the envelope?? */ - minfo = imap_parse_envelope(is); - /* what do we do with the message content info?? */ - ((CamelMessageInfoBase *)minfo)->content = imap_parse_body(is); - camel_message_info_free(minfo); - minfo = NULL; - d(printf("Scanned envelope - what do i do with it?\n")); - } - - d(printf("fld_lines?\n")); - - /* do we have fld_lines following? */ - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == IMAP_TOK_INT) { - d(printf("field lines: %s\n", token)); - tok = camel_imapp_stream_token(is, &token, &len); - } - camel_imapp_stream_ungettoken(is, tok, token, len); - - /* body_ext_1part ::= body_fld_md5 [SPACE body_fld_dsp - [SPACE body_fld_lang - [SPACE 1#body_extension]]] - ;; MUST NOT be returned on non-extensible - ;; "BODY" fetch */ - - d(printf("extension data?\n")); - - if (tok != ')') { - camel_imapp_stream_nstring(is, &token); - - d(printf("md5: %s\n", token?(char *)token:"NIL")); - - /* body_fld_dsp ::= "(" string SPACE body_fld_param ")" / nil */ - - tok = camel_imapp_stream_token(is, &token, &len); - camel_imapp_stream_ungettoken(is, tok, token, len); - if (tok == '(' || tok == IMAP_TOK_TOKEN) { - dinfo = imap_parse_ext_optional(is); - /* then other extension fields, soaked up below */ - } - } - } - - /* soak up any other extension fields that may be present */ - /* there should only be simple tokens, no lists */ - do { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok != ')') - d(printf("Dropping extension data '%s'\n", token)); - } while (tok != ')'); - } CAMEL_CATCH(ex) { - if (cinfo) - imap_free_body(cinfo); - if (dinfo) - camel_content_disposition_unref(dinfo); - if (minfo) - camel_message_info_free(minfo); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - /* FIXME: do something with the disposition, currently we have no way to pass it out? */ - if (dinfo) - camel_content_disposition_unref(dinfo); - - return cinfo; -} - -char * -imap_parse_section(CamelIMAPPStream *is) -{ - int tok, len; - unsigned char *token; - char * volatile section = NULL; - - /* currently we only return the part within the [section] specifier - any header fields are parsed, but dropped */ - - /* - section ::= "[" [section_text / - (nz_number *["." nz_number] ["." (section_text / "MIME")])] "]" - - section_text ::= "HEADER" / "HEADER.FIELDS" [".NOT"] - SPACE header_list / "TEXT" - */ - - CAMEL_TRY { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok != '[') - camel_exception_throw(1, "section: expecting '['"); - - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == IMAP_TOK_INT || tok == IMAP_TOK_TOKEN) - section = g_strdup(token); - else if (tok == ']') { - section = g_strdup(""); - camel_imapp_stream_ungettoken(is, tok, token, len); - } else - camel_exception_throw(1, "section: expecting token"); - - /* header_list ::= "(" 1#header_fld_name ")" - header_fld_name ::= astring */ - - /* we dont need the header specifiers */ - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == '(') { - do { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == IMAP_TOK_STRING || tok == IMAP_TOK_TOKEN || tok == IMAP_TOK_INT) { - /* ?do something? */ - } else if (tok != ')') - camel_exception_throw(1, "section: header fields: expecting string"); - } while (tok != ')'); - tok = camel_imapp_stream_token(is, &token, &len); - } - - if (tok != ']') - camel_exception_throw(1, "section: expecting ']'"); - } CAMEL_CATCH(ex) { - g_free(section); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - return section; -} - -void -imap_free_fetch(struct _fetch_info *finfo) -{ - if (finfo == NULL) - return; - - if (finfo->body) - camel_object_unref((CamelObject *)finfo->body); - if (finfo->text) - camel_object_unref((CamelObject *)finfo->text); - if (finfo->header) - camel_object_unref((CamelObject *)finfo->header); - if (finfo->minfo) - camel_message_info_free(finfo->minfo); - if (finfo->cinfo) - imap_free_body(finfo->cinfo); - g_free(finfo->date); - g_free(finfo->section); - g_free(finfo->uid); - g_free(finfo); -} - -extern void camel_content_info_dump(CamelMessageContentInfo *ci, int depth); -extern void camel_message_info_dump(CamelMessageInfo *mi); - -#include <camel/camel-stream-fs.h> - -/* debug, dump one out */ -void -imap_dump_fetch(struct _fetch_info *finfo) -{ - CamelStream *sout; - int fd; - - printf("Fetch info:\n"); - if (finfo == NULL) { - printf("Empty\n"); - return; - } - - fd = dup(1); - sout = camel_stream_fs_new_with_fd(fd); - if (finfo->body) { - camel_stream_printf(sout, "Body content:\n"); - camel_stream_write_to_stream(finfo->body, sout); - } - if (finfo->text) { - camel_stream_printf(sout, "Text content:\n"); - camel_stream_write_to_stream(finfo->text, sout); - } - if (finfo->header) { - camel_stream_printf(sout, "Header content:\n"); - camel_stream_write_to_stream(finfo->header, sout); - } - if (finfo->minfo) { - camel_stream_printf(sout, "Message Info:\n"); - camel_message_info_dump(finfo->minfo); - } - if (finfo->cinfo) { - camel_stream_printf(sout, "Content Info:\n"); - camel_content_info_dump(finfo->cinfo, 0); - } - if (finfo->got & FETCH_SIZE) - camel_stream_printf(sout, "Size: %d\n", (int)finfo->size); - if (finfo->got & FETCH_BODY) - camel_stream_printf(sout, "Offset: %d\n", (int)finfo->offset); - if (finfo->got & FETCH_FLAGS) - camel_stream_printf(sout, "Flags: %08x\n", (int)finfo->flags); - if (finfo->date) - camel_stream_printf(sout, "Date: '%s'\n", finfo->date); - if (finfo->section) - camel_stream_printf(sout, "Section: '%s'\n", finfo->section); - if (finfo->date) - camel_stream_printf(sout, "UID: '%s'\n", finfo->uid); - camel_object_unref((CamelObject *)sout); -} - -struct _fetch_info * -imap_parse_fetch(CamelIMAPPStream *is) -{ - int tok, len; - unsigned char *token, *p, c; - struct _fetch_info *finfo; - - finfo = g_malloc0(sizeof(*finfo)); - - CAMEL_TRY { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok != '(') - camel_exception_throw(1, "fetch: expecting '('"); - - while ( (tok = camel_imapp_stream_token(is, &token, &len)) == IMAP_TOK_TOKEN ) { - - p = token; - while ((c=*p)) - *p++ = toupper(c); - - switch(imap_tokenise(token, len)) { - case IMAP_ENVELOPE: - finfo->minfo = imap_parse_envelope(is); - finfo->got |= FETCH_MINFO; - break; - case IMAP_FLAGS: - imap_parse_flags(is, &finfo->flags); - finfo->got |= FETCH_FLAGS; - break; - case IMAP_INTERNALDATE: - camel_imapp_stream_nstring(is, &token); - /* TODO: convert to camel format? */ - finfo->date = g_strdup(token); - finfo->got |= FETCH_DATE; - break; - case IMAP_RFC822_HEADER: - camel_imapp_stream_nstring_stream(is, &finfo->header); - finfo->got |= FETCH_HEADER; - break; - case IMAP_RFC822_TEXT: - camel_imapp_stream_nstring_stream(is, &finfo->text); - finfo->got |= FETCH_TEXT; - break; - case IMAP_RFC822_SIZE: - finfo->size = camel_imapp_stream_number(is); - finfo->got |= FETCH_SIZE; - break; - case IMAP_BODYSTRUCTURE: - finfo->cinfo = imap_parse_body(is); - finfo->got |= FETCH_CINFO; - break; - case IMAP_BODY: - tok = camel_imapp_stream_token(is, &token, &len); - camel_imapp_stream_ungettoken(is, tok, token, len); - if (tok == '(') { - finfo->cinfo = imap_parse_body(is); - finfo->got |= FETCH_CINFO; - } else if (tok == '[') { - finfo->section = imap_parse_section(is); - finfo->got |= FETCH_SECTION; - tok = camel_imapp_stream_token(is, &token, &len); - if (token[0] == '<') { - finfo->offset = strtoul(token+1, NULL, 10); - } else { - camel_imapp_stream_ungettoken(is, tok, token, len); - } - camel_imapp_stream_nstring_stream(is, &finfo->body); - finfo->got |= FETCH_BODY; - } else { - camel_exception_throw(1, "unknown body response"); - } - break; - case IMAP_UID: - tok = camel_imapp_stream_token(is, &token, &len); - if (tok != IMAP_TOK_INT) - camel_exception_throw(1, "uid not integer"); - finfo->uid = g_strdup(token); - finfo->got |= FETCH_UID; - break; - default: - camel_exception_throw(1, "unknown body response"); - } - } - - if (tok != ')') - camel_exception_throw(1, "missing closing ')' on fetch response"); - } CAMEL_CATCH(ex) { - imap_free_fetch(finfo); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - return finfo; -} - -/* rfc 2060 section 7.1 Status Responses */ -/* shoudl this start after [ or before the [? token_unget anyone? */ -struct _status_info * -imap_parse_status(CamelIMAPPStream *is) -{ - int tok, len; - unsigned char *token; - struct _status_info *sinfo; - - sinfo = g_malloc0(sizeof(*sinfo)); - - CAMEL_TRY { - camel_imapp_stream_atom(is, &token, &len); - - /* - resp_cond_auth ::= ("OK" / "PREAUTH") SPACE resp_text - ;; Authentication condition - - resp_cond_bye ::= "BYE" SPACE resp_text - - resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text - ;; Status condition - */ - - sinfo->result = imap_tokenise(token, len); - switch (sinfo->result) { - case IMAP_OK: - case IMAP_NO: - case IMAP_BAD: - case IMAP_PREAUTH: - case IMAP_BYE: - break; - default: - camel_exception_throw(1, "expecting OK/NO/BAD"); - } - - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == '[') { - camel_imapp_stream_atom(is, &token, &len); - sinfo->condition = imap_tokenise(token, len); - - /* parse any details */ - switch (sinfo->condition) { - case IMAP_READ_ONLY: - case IMAP_READ_WRITE: - case IMAP_ALERT: - case IMAP_PARSE: - case IMAP_TRYCREATE: - break; - case IMAP_NEWNAME: - /* the rfc doesn't specify the bnf for this */ - camel_imapp_stream_astring(is, &token); - sinfo->u.newname.oldname = g_strdup(token); - camel_imapp_stream_astring(is, &token); - sinfo->u.newname.newname = g_strdup(token); - break; - case IMAP_PERMANENTFLAGS: - imap_parse_flags(is, &sinfo->u.permanentflags); - break; - case IMAP_UIDVALIDITY: - sinfo->u.uidvalidity = camel_imapp_stream_number(is); - break; - case IMAP_UNSEEN: - sinfo->u.unseen = camel_imapp_stream_number(is); - break; - default: - sinfo->condition = IMAP_UNKNOWN; - printf("Got unknown response code: %s: ignored\n", token); - } - - /* ignore anything we dont know about */ - do { - tok = camel_imapp_stream_token(is, &token, &len); - if (tok == '\n') - camel_exception_throw(1, "server response truncated"); - } while (tok != ']'); - } else { - camel_imapp_stream_ungettoken(is, tok, token, len); - } - - /* and take the human readable response */ - camel_imapp_stream_text(is, (unsigned char **)&sinfo->text); - } CAMEL_CATCH(ex) { - imap_free_status(sinfo); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - return sinfo; -} - -void -imap_free_status(struct _status_info *sinfo) -{ - if (sinfo == NULL) - return; - - switch (sinfo->condition) { - case IMAP_NEWNAME: - g_free(sinfo->u.newname.oldname); - g_free(sinfo->u.newname.newname); - default: - break; - } - - g_free(sinfo->text); - g_free(sinfo); -} - -/* FIXME: use tokeniser? */ -/* FIXME: real flags */ -static struct { - char *name; - guint32 flag; -} list_flag_table[] = { - { "\\NOINFERIORS", CAMEL_FOLDER_NOINFERIORS }, - { "\\NOSELECT", CAMEL_FOLDER_NOSELECT }, - { "\\MARKED", 1<<8 }, - { "\\UNMARKED", 1<<9 }, -}; - -struct _list_info * -imap_parse_list(CamelIMAPPStream *is) -/* throws io, parse */ -{ - int tok, len, i; - unsigned char *token, *p, c; - struct _list_info * volatile linfo; - - linfo = g_malloc0(sizeof(*linfo)); - - CAMEL_TRY { - /* mailbox_list ::= "(" #("\Marked" / "\Noinferiors" / - "\Noselect" / "\Unmarked" / flag_extension) ")" - SPACE (<"> QUOTED_CHAR <"> / nil) SPACE mailbox */ - - tok = camel_imapp_stream_token(is, &token, &len); - if (tok != '(') - camel_exception_throw(1, "list: expecting '('"); - - while ( (tok = camel_imapp_stream_token(is, &token, &len)) != ')' ) { - if (tok == IMAP_TOK_STRING || tok == IMAP_TOK_TOKEN) { - p = token; - while ((c=*p)) - *p++ = toupper(c); - for (i=0;i<(int)(sizeof(list_flag_table)/sizeof(list_flag_table[0]));i++) - if (!strcmp(token, list_flag_table[i].name)) - linfo->flags |= list_flag_table[i].flag; - } else { - camel_exception_throw(1, "list: expecting flag or ')'"); - } - } - - camel_imapp_stream_nstring(is, &token); - linfo->separator = token?*token:0; - camel_imapp_stream_astring(is, &token); - linfo->name = g_strdup(token); - } CAMEL_CATCH(ex) { - imap_free_list(linfo); - camel_exception_throw_ex(ex); - } CAMEL_DONE; - - return linfo; -} - -char * -imapp_list_get_path(struct _list_info *li) -{ - char *path, *p; - int c; - const char *f; - - if (li->separator != 0 && li->separator != '/') { - p = path = alloca(strlen(li->name)*3+1); - f = li->name; - while ( (c = *f++ & 0xff) ) { - if (c == li->separator) - *p++ = '/'; - else if (c == '/' || c == '%') - p += sprintf(p, "%%%02X", c); - else - *p++ = c; - } - *p = 0; - } else - path = li->name; - - return camel_utf7_utf8(path); -} - -void -imap_free_list(struct _list_info *linfo) -{ - if (linfo) { - g_free(linfo->name); - g_free(linfo); - } -} - - -/* ********************************************************************** */ -/* utility functions */ - -/* should the rest of imapp-utils go into imapp-parse? */ - -/* this creates a uid (or sequence number) set directly into the command, - optionally breaking it into smaller chunks */ - -void -imapp_uidset_init(struct _uidset_state *ss, CamelIMAPPEngine *ie) -{ - ss->ie = ie; - ss->len = 0; - ss->start = 0; - ss->last = 0; -} - -int -imapp_uidset_done(struct _uidset_state *ss, CamelIMAPPCommand *ic) -{ - int ret = 0; - - if (ss->last != 0 && ss->last != ss->start) { - camel_imapp_engine_command_add(ss->ie, ic, ":%d", ss->last); - printf(":%d", ss->last); - } - - ret = ss->last != 0; - - ss->start = 0; - ss->last = 0; - ss->len = 0; - - return ret; -} - -int -imapp_uidset_add(struct _uidset_state *ss, CamelIMAPPCommand *ic, const char *uid) -{ - guint32 uidn; - - uidn = strtoul(uid, NULL, 10); - if (uidn == 0) - return -1; - - if (ss->last == 0) { - camel_imapp_engine_command_add(ss->ie, ic, "%d", uidn); - printf("%d", uidn); - ss->len ++; - ss->start = uidn; - } else { - if (ss->last != uidn-1) { - if (ss->last == ss->start) { - camel_imapp_engine_command_add(ss->ie, ic, ",%d", uidn); - printf(",%d", uidn); - ss->len ++; - } else { - camel_imapp_engine_command_add(ss->ie, ic, ":%d,%d", ss->last, uidn); - printf(":%d,%d", ss->last, uidn); - ss->len+=2; - } - ss->start = uidn; - } - } - - ss->last = uidn; - - if (ss->len > 10) { - imapp_uidset_done(ss, ic); - return 1; - } - - return 0; -} diff --git a/camel/providers/imapp/camel-imapp-utils.h b/camel/providers/imapp/camel-imapp-utils.h deleted file mode 100644 index 2734cd0dc3..0000000000 --- a/camel/providers/imapp/camel-imapp-utils.h +++ /dev/null @@ -1,145 +0,0 @@ - -#ifndef _CAMEL_IMAPP_UTILS_H -#define _CAMEL_IMAPP_UTILS_H - -#include <camel/camel-mime-utils.h> - -/* FIXME: the enum should be split up into logical groups, so that testing - can be done more accurately? */ - -/* list of strings we know about that can be *quickly* tokenised */ -enum _imap_id { - IMAP_UNKNOWN = 0, - IMAP_ALERT, - IMAP_BYE, - IMAP_BAD, - IMAP_NO, - IMAP_OK, - IMAP_PREAUTH, - IMAP_NEWNAME, - IMAP_PARSE, - IMAP_PERMANENTFLAGS, - IMAP_READ_ONLY, - IMAP_READ_WRITE, - IMAP_TRYCREATE, - IMAP_UIDVALIDITY, - IMAP_UNSEEN, - IMAP_ENVELOPE, - IMAP_FLAGS, - IMAP_INTERNALDATE, - IMAP_RFC822_HEADER, - IMAP_RFC822_TEXT, - IMAP_RFC822_SIZE, - IMAP_BODYSTRUCTURE, - IMAP_BODY, - IMAP_UID, -}; - -/* str MUST be in upper case, tokenised using gperf function */ -enum _imap_id imap_tokenise(register const char *str, register unsigned int len); - -/* this flag should be part of imapfoldersummary */ -enum { - CAMEL_IMAPP_MESSAGE_RECENT = (1<<8), -}; - -/* ********************************************************************** */ -void imap_parse_flags(CamelIMAPPStream *stream, guint32 *flagsp) /* IO,PARSE */; -void imap_write_flags(CamelStream *stream, guint32 flags) /* IO */; - -/* ********************************************************************** */ -void imap_parse_param_list(CamelIMAPPStream *is, struct _camel_header_param **plist) /* IO,PARSE */; -struct _CamelContentDisposition *imap_parse_ext_optional(CamelIMAPPStream *is) /* IO,PARSE */; -struct _CamelMessageContentInfo *imap_parse_body_fields(CamelIMAPPStream *is) /* IO,PARSE */; -struct _camel_header_address *imap_parse_address_list(CamelIMAPPStream *is) /* IO,PARSE */; -struct _CamelMessageInfo *imap_parse_envelope(CamelIMAPPStream *is) /* IO, PARSE */; -struct _CamelMessageContentInfo *imap_parse_body(CamelIMAPPStream *is) /* IO,PARSE */; -char *imap_parse_section(CamelIMAPPStream *is) /* IO,PARSE */; -void imap_free_body(struct _CamelMessageContentInfo *cinfo); - -/* ********************************************************************** */ -/* all the possible stuff we might get from a fetch request */ -/* this assumes the caller/server doesn't send any one of these types twice */ -struct _fetch_info { - guint32 got; /* what we got, see below */ - CamelStream *body; /* BODY[.*](<.*>)? */ - CamelStream *text; /* RFC822.TEXT */ - CamelStream *header; /* RFC822.HEADER */ - struct _CamelMessageInfo *minfo; /* ENVELOPE */ - struct _CamelMessageContentInfo *cinfo; /* BODYSTRUCTURE,BODY */ - guint32 size; /* RFC822.SIZE */ - guint32 offset; /* start offset of a BODY[]<offset.length> request */ - guint32 flags; /* FLAGS */ - char *date; /* INTERNALDATE */ - char *section; /* section for a BODY[section] request */ - char *uid; /* UID */ -}; - -#define FETCH_BODY (1<<0) -#define FETCH_TEXT (1<<1) -#define FETCH_HEADER (1<<2) -#define FETCH_MINFO (1<<3) -#define FETCH_CINFO (1<<4) -#define FETCH_SIZE (1<<5) -#define FETCH_OFFSET (1<<6) -#define FETCH_FLAGS (1<<7) -#define FETCH_DATE (1<<8) -#define FETCH_SECTION (1<<9) -#define FETCH_UID (1<<10) - -struct _fetch_info *imap_parse_fetch(CamelIMAPPStream *is); -void imap_free_fetch(struct _fetch_info *finfo); -void imap_dump_fetch(struct _fetch_info *finfo); - -/* ********************************************************************** */ - -struct _status_info { - enum _imap_id result; /* ok/no/bad/preauth only */ - enum _imap_id condition; /* read-only/read-write/alert/parse/trycreate/newname/permanentflags/uidvalidity/unseen */ - - union { - struct { - char *oldname; - char *newname; - } newname; - guint32 permanentflags; - guint32 uidvalidity; - guint32 unseen; - } u; - - char *text; -}; - -struct _status_info *imap_parse_status(CamelIMAPPStream *is); -void imap_free_status(struct _status_info *sinfo); - -/* ********************************************************************** */ - -/* should this just return a FolderInfo? - should this just return the name & flags & separator by reference? */ -struct _list_info { - guint32 flags:24; - char separator; - char *name; -}; - -struct _list_info *imap_parse_list(CamelIMAPPStream *is); -char *imapp_list_get_path(struct _list_info *li); -void imap_free_list(struct _list_info *linfo); - -/* ********************************************************************** */ - -struct _uidset_state { - struct _CamelIMAPPEngine *ie; - int len; - guint32 start; - guint32 last; -}; - -struct _CamelIMAPPEngine; -struct _CamelIMAPPCommand; -void imapp_uidset_init(struct _uidset_state *ss, struct _CamelIMAPPEngine *ie); -int imapp_uidset_done(struct _uidset_state *ss, struct _CamelIMAPPCommand *ic); -int imapp_uidset_add(struct _uidset_state *ss, struct _CamelIMAPPCommand *ic, const char *uid); - -#endif diff --git a/camel/providers/imapp/libcamelimapp.urls b/camel/providers/imapp/libcamelimapp.urls deleted file mode 100644 index aad1347834..0000000000 --- a/camel/providers/imapp/libcamelimapp.urls +++ /dev/null @@ -1 +0,0 @@ -imapp diff --git a/camel/providers/local/.cvsignore b/camel/providers/local/.cvsignore deleted file mode 100644 index 3fa8afaa38..0000000000 --- a/camel/providers/local/.cvsignore +++ /dev/null @@ -1,11 +0,0 @@ -.deps -Makefile -Makefile.in -.libs -.deps -*.lo -*.la -*.bb -*.bbg -*.da -*.gcov diff --git a/camel/providers/local/Makefile.am b/camel/providers/local/Makefile.am deleted file mode 100644 index fbf3199a8b..0000000000 --- a/camel/providers/local/Makefile.am +++ /dev/null @@ -1,54 +0,0 @@ -## Process this file with automake to produce Makefile.in - -camel_provider_LTLIBRARIES = libcamellocal.la -camel_provider_DATA = libcamellocal.urls - -INCLUDES = \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir) \ - $(CAMEL_CFLAGS) \ - -DG_LOG_DOMAIN=\"camel-local-provider\" - -libcamellocal_la_SOURCES = \ - camel-local-folder.c \ - camel-local-store.c \ - camel-local-summary.c \ - camel-local-provider.c \ - camel-mh-folder.c \ - camel-mh-store.c \ - camel-mh-summary.c \ - camel-mbox-folder.c \ - camel-mbox-store.c \ - camel-mbox-summary.c \ - camel-maildir-folder.c \ - camel-maildir-store.c \ - camel-maildir-summary.c \ - camel-spool-folder.c \ - camel-spool-store.c \ - camel-spool-summary.c - -noinst_HEADERS = \ - camel-local-folder.h \ - camel-local-store.h \ - camel-local-summary.h \ - camel-mh-folder.h \ - camel-mh-store.h \ - camel-mh-summary.h \ - camel-mbox-folder.h \ - camel-mbox-store.h \ - camel-mbox-summary.h \ - camel-maildir-folder.h \ - camel-maildir-store.h \ - camel-maildir-summary.h \ - camel-spool-folder.h \ - camel-spool-store.h \ - camel-spool-summary.h \ - camel-local-private.h - -libcamellocal_la_LDFLAGS = -avoid-version -module - -libcamellocal_la_LIBADD = \ - $(top_builddir)/libedataserver/libedataserver-${BASE_VERSION}.la - -EXTRA_DIST = libcamellocal.urls diff --git a/camel/providers/local/camel-local-folder.c b/camel/providers/local/camel-local-folder.c deleted file mode 100644 index 70673d9687..0000000000 --- a/camel/providers/local/camel-local-folder.c +++ /dev/null @@ -1,631 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright 1999-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <limits.h> -#include <sys/types.h> -#include <dirent.h> -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <fcntl.h> - -#ifndef _POSIX_PATH_MAX -#include <posix1_lim.h> -#endif - -#include "camel-local-folder.h" -#include "camel-local-store.h" -#include "camel-stream-fs.h" -#include "camel-local-summary.h" -#include "camel-data-wrapper.h" -#include "camel-mime-message.h" -#include "camel-stream-filter.h" -#include "camel-mime-filter-from.h" -#include "camel-exception.h" -#include "camel-i18n.h" - -#include "camel-local-private.h" - -#include "camel-text-index.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -#ifndef PATH_MAX -#define PATH_MAX _POSIX_PATH_MAX -#endif - -static CamelFolderClass *parent_class; -static GSList *local_folder_properties; - -/* Returns the class for a CamelLocalFolder */ -#define CLOCALF_CLASS(so) CAMEL_LOCAL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CLOCALS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static int local_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args); -static int local_setv(CamelObject *object, CamelException *ex, CamelArgV *args); - -static int local_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex); -static void local_unlock(CamelLocalFolder *lf); - -static char *local_get_full_path(CamelLocalFolder *lf, const char *toplevel_dir, const char *full_name); -static char *local_get_meta_path(CamelLocalFolder *lf, const char *toplevel_dir, const char *full_name, const char *ext); - -static void local_refresh_info(CamelFolder *folder, CamelException *ex); - -static void local_sync(CamelFolder *folder, gboolean expunge, CamelException *ex); -static void local_expunge(CamelFolder *folder, CamelException *ex); - -static GPtrArray *local_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex); -static GPtrArray *local_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex); -static void local_search_free(CamelFolder *folder, GPtrArray * result); - -static void local_delete(CamelFolder *folder); -static void local_rename(CamelFolder *folder, const char *newname); - -static void local_finalize(CamelObject * object); - -static void -camel_local_folder_class_init(CamelLocalFolderClass * camel_local_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_local_folder_class); - CamelObjectClass *oklass = (CamelObjectClass *)camel_local_folder_class; - - /* virtual method definition */ - - /* virtual method overload */ - oklass->getv = local_getv; - oklass->setv = local_setv; - - camel_folder_class->refresh_info = local_refresh_info; - camel_folder_class->sync = local_sync; - camel_folder_class->expunge = local_expunge; - - camel_folder_class->search_by_expression = local_search_by_expression; - camel_folder_class->search_by_uids = local_search_by_uids; - camel_folder_class->search_free = local_search_free; - - camel_folder_class->delete = local_delete; - camel_folder_class->rename = local_rename; - - camel_local_folder_class->get_full_path = local_get_full_path; - camel_local_folder_class->get_meta_path = local_get_meta_path; - - camel_local_folder_class->lock = local_lock; - camel_local_folder_class->unlock = local_unlock; -} - -static void -local_init(gpointer object, gpointer klass) -{ - CamelFolder *folder = object; - CamelLocalFolder *local_folder = object; - - folder->folder_flags |= (CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | - CAMEL_FOLDER_HAS_SEARCH_CAPABILITY); - - folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | - CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_DRAFT | - CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN | - CAMEL_MESSAGE_ANSWERED_ALL | CAMEL_MESSAGE_USER; - - folder->summary = NULL; - local_folder->search = NULL; - - local_folder->priv = g_malloc0(sizeof(*local_folder->priv)); - local_folder->priv->search_lock = g_mutex_new(); -} - -static void -local_finalize(CamelObject * object) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(object); - CamelFolder *folder = (CamelFolder *)object; - - if (folder->summary) { - camel_local_summary_sync((CamelLocalSummary *)folder->summary, FALSE, local_folder->changes, NULL); - camel_object_unref((CamelObject *)folder->summary); - folder->summary = NULL; - } - - if (local_folder->search) { - camel_object_unref((CamelObject *)local_folder->search); - } - - if (local_folder->index) - camel_object_unref((CamelObject *)local_folder->index); - - while (local_folder->locked> 0) - camel_local_folder_unlock(local_folder); - - g_free(local_folder->base_path); - g_free(local_folder->folder_path); - g_free(local_folder->summary_path); - g_free(local_folder->index_path); - - camel_folder_change_info_free(local_folder->changes); - - g_mutex_free(local_folder->priv->search_lock); - - g_free(local_folder->priv); -} - -static CamelProperty local_property_list[] = { - { CAMEL_LOCAL_FOLDER_INDEX_BODY, "index_body", N_("Index message body data") }, -}; - -CamelType -camel_local_folder_get_type(void) -{ - static CamelType camel_local_folder_type = CAMEL_INVALID_TYPE; - - if (camel_local_folder_type == CAMEL_INVALID_TYPE) { - int i; - - parent_class = (CamelFolderClass *)camel_folder_get_type(); - camel_local_folder_type = camel_type_register(camel_folder_get_type(), "CamelLocalFolder", - sizeof(CamelLocalFolder), - sizeof(CamelLocalFolderClass), - (CamelObjectClassInitFunc) camel_local_folder_class_init, - NULL, - (CamelObjectInitFunc) local_init, - (CamelObjectFinalizeFunc) local_finalize); - - for (i=0;i<sizeof(local_property_list)/sizeof(local_property_list[0]);i++) { - local_property_list[i].description = _(local_property_list[i].description); - local_folder_properties = g_slist_prepend(local_folder_properties, &local_property_list[i]); - } - } - - return camel_local_folder_type; -} - -CamelLocalFolder * -camel_local_folder_construct(CamelLocalFolder *lf, CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex) -{ - CamelFolderInfo *fi; - CamelFolder *folder; - const char *root_dir_path, *name; - char *tmp, *statepath; - char folder_path[PATH_MAX]; - struct stat st; - int forceindex, len; - CamelURL *url; - - folder = (CamelFolder *)lf; - - name = strrchr(full_name, '/'); - if (name) - name++; - else - name = full_name; - - camel_folder_construct(folder, parent_store, full_name, name); - - root_dir_path = camel_local_store_get_toplevel_dir(CAMEL_LOCAL_STORE(folder->parent_store)); - /* strip the trailing '/' which is always present */ - len = strlen (root_dir_path); - tmp = g_alloca (len + 1); - strcpy (tmp, root_dir_path); - if (len>1 && tmp[len-1] == '/') - tmp[len-1] = 0; - - lf->base_path = g_strdup(root_dir_path); - - /* if the base store points to a file, then use that */ - if (stat(tmp, &st) != -1 && S_ISREG(st.st_mode)) { - lf->folder_path = g_strdup(tmp); - /* not really sure to do with these for now? */ - lf->summary_path = g_strdup_printf("%s.ev-summary", tmp); - lf->index_path = g_strdup_printf("%s.ibex", tmp); - statepath = g_strdup_printf("%s.cmeta", tmp); - } else { - lf->folder_path = CLOCALF_CLASS(lf)->get_full_path(lf, root_dir_path, full_name); - lf->summary_path = CLOCALF_CLASS(lf)->get_meta_path(lf, root_dir_path, full_name, ".ev-summary"); - lf->index_path = CLOCALF_CLASS(lf)->get_meta_path(lf, root_dir_path, full_name, ".ibex"); - statepath = CLOCALF_CLASS(lf)->get_meta_path(lf, root_dir_path, full_name, ".cmeta"); - } - camel_object_set(lf, NULL, CAMEL_OBJECT_STATE_FILE, statepath, NULL); - g_free(statepath); - - lf->flags = flags; - - if (camel_object_state_read(lf) == -1) { - /* No metadata - load defaults and persitify */ - camel_object_set(lf, NULL, CAMEL_LOCAL_FOLDER_INDEX_BODY, TRUE, 0); - camel_object_state_write(lf); - } - - /* follow any symlinks to the mailbox */ - if (lstat (lf->folder_path, &st) != -1 && S_ISLNK (st.st_mode) && - realpath (lf->folder_path, folder_path) != NULL) { - g_free (lf->folder_path); - lf->folder_path = g_strdup (folder_path); - } - - lf->changes = camel_folder_change_info_new(); - - /* TODO: Remove the following line, it is a temporary workaround to remove - the old-format 'ibex' files that might be lying around */ - unlink(lf->index_path); - - /* FIXME: Need to run indexing off of the setv method */ - - /* if we have no/invalid index file, force it */ - forceindex = camel_text_index_check(lf->index_path) == -1; - if (lf->flags & CAMEL_STORE_FOLDER_BODY_INDEX) { - int flag = O_RDWR|O_CREAT; - - if (forceindex) - flag |= O_TRUNC; - - lf->index = (CamelIndex *)camel_text_index_new(lf->index_path, flag); - if (lf->index == NULL) { - /* yes, this isn't fatal at all */ - g_warning("Could not open/create index file: %s: indexing not performed", strerror (errno)); - forceindex = FALSE; - /* record that we dont have an index afterall */ - lf->flags &= ~CAMEL_STORE_FOLDER_BODY_INDEX; - } - } else { - /* if we do have an index file, remove it (?) */ - if (forceindex == FALSE) - camel_text_index_remove(lf->index_path); - forceindex = FALSE; - } - - folder->summary = (CamelFolderSummary *)CLOCALF_CLASS(lf)->create_summary(lf, lf->summary_path, lf->folder_path, lf->index); - if (camel_local_summary_load((CamelLocalSummary *)folder->summary, forceindex, NULL) == -1) { - /* ? */ - } - - /*if (camel_local_summary_check((CamelLocalSummary *)folder->summary, lf->changes, ex) == -1) {*/ - /* we sync here so that any hard work setting up the folder isn't lost */ - if (camel_local_summary_sync((CamelLocalSummary *)folder->summary, FALSE, lf->changes, ex) == -1) { - camel_object_unref (CAMEL_OBJECT (folder)); - return NULL; - } - - /* TODO: This probably shouldn't be here? */ - if ((flags & CAMEL_STORE_FOLDER_CREATE) != 0) { - url = camel_url_copy (((CamelService *) parent_store)->url); - camel_url_set_fragment (url, full_name); - - fi = g_new0 (CamelFolderInfo, 1); - fi->full_name = g_strdup (full_name); - fi->name = g_strdup (name); - fi->uri = camel_url_to_string (url, 0); - fi->unread = camel_folder_get_unread_message_count(folder); - fi->flags = CAMEL_FOLDER_NOCHILDREN; - - camel_url_free (url); - - camel_object_trigger_event(CAMEL_OBJECT (parent_store), "folder_created", fi); - camel_folder_info_free(fi); - } - - return lf; -} - -/* lock the folder, may be called repeatedly (with matching unlock calls), - with type the same or less than the first call */ -int camel_local_folder_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex) -{ - if (lf->locked > 0) { - /* lets be anal here - its important the code knows what its doing */ - g_assert(lf->locktype == type || lf->locktype == CAMEL_LOCK_WRITE); - } else { - if (CLOCALF_CLASS(lf)->lock(lf, type, ex) == -1) - return -1; - lf->locktype = type; - } - - lf->locked++; - - return 0; -} - -/* unlock folder */ -int camel_local_folder_unlock(CamelLocalFolder *lf) -{ - g_assert(lf->locked>0); - lf->locked--; - if (lf->locked == 0) - CLOCALF_CLASS(lf)->unlock(lf); - - return 0; -} - -static int -local_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args) -{ - CamelFolder *folder = (CamelFolder *)object; - int i; - guint32 tag; - - for (i=0;i<args->argc;i++) { - CamelArgGet *arg = &args->argv[i]; - - tag = arg->tag; - - switch (tag & CAMEL_ARG_TAG) { - case CAMEL_OBJECT_ARG_DESCRIPTION: - if (folder->description == NULL) { - char *tmp, *path; - - /* check some common prefixes to shorten the name */ - tmp = ((CamelService *)folder->parent_store)->url->path; - if (tmp == NULL) - goto skip; - - path = g_alloca (strlen (tmp) + strlen (folder->full_name) + 1); - sprintf (path, "%s/%s", tmp, folder->full_name); - - if ((tmp = getenv("HOME")) && strncmp(tmp, path, strlen(tmp)) == 0) - /* $HOME relative path + protocol string */ - folder->description = g_strdup_printf(_("~%s (%s)"), path+strlen(tmp), - ((CamelService *)folder->parent_store)->url->protocol); - else if ((tmp = "/var/spool/mail") && strncmp(tmp, path, strlen(tmp)) == 0) - /* /var/spool/mail relative path + protocol */ - folder->description = g_strdup_printf(_("mailbox:%s (%s)"), path+strlen(tmp), - ((CamelService *)folder->parent_store)->url->protocol); - else if ((tmp = "/var/mail") && strncmp(tmp, path, strlen(tmp)) == 0) - folder->description = g_strdup_printf(_("mailbox:%s (%s)"), path+strlen(tmp), - ((CamelService *)folder->parent_store)->url->protocol); - else - /* a full path + protocol */ - folder->description = g_strdup_printf(_("%s (%s)"), path, - ((CamelService *)folder->parent_store)->url->protocol); - } - *arg->ca_str = folder->description; - break; - - case CAMEL_OBJECT_ARG_PERSISTENT_PROPERTIES: - case CAMEL_FOLDER_ARG_PROPERTIES: { - CamelArgGetV props; - - props.argc = 1; - props.argv[0] = *arg; - ((CamelObjectClass *)parent_class)->getv(object, ex, &props); - *arg->ca_ptr = g_slist_concat(*arg->ca_ptr, g_slist_copy(local_folder_properties)); - - break; } - - case CAMEL_LOCAL_FOLDER_ARG_INDEX_BODY: - /* FIXME: remove this from sotre flags */ - *arg->ca_int = (((CamelLocalFolder *)folder)->flags & CAMEL_STORE_FOLDER_BODY_INDEX) != 0; - break; - - default: skip: - continue; - } - - arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE; - } - - return ((CamelObjectClass *)parent_class)->getv(object, ex, args); -} - -static int -local_setv(CamelObject *object, CamelException *ex, CamelArgV *args) -{ - int i; - guint32 tag; - - for (i=0;i<args->argc;i++) { - CamelArg *arg = &args->argv[i]; - - tag = arg->tag; - - switch (tag & CAMEL_ARG_TAG) { - case CAMEL_LOCAL_FOLDER_ARG_INDEX_BODY: - /* FIXME: implement */ - /* TODO: When turning on (off?) the index, we want to launch a task for it, - and make sure we dont have multiple tasks doing the same job */ - if (arg->ca_int) - ((CamelLocalFolder *)object)->flags |= CAMEL_STORE_FOLDER_BODY_INDEX; - else - ((CamelLocalFolder *)object)->flags &= ~CAMEL_STORE_FOLDER_BODY_INDEX; - break; - default: - continue; - } - - arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE; - } - - return ((CamelObjectClass *)parent_class)->setv(object, ex, args); -} - -static char * -local_get_full_path(CamelLocalFolder *lf, const char *toplevel_dir, const char *full_name) -{ - return g_strdup_printf("%s/%s", toplevel_dir, full_name); -} - -static char * -local_get_meta_path(CamelLocalFolder *lf, const char *toplevel_dir, const char *full_name, const char *ext) -{ - return g_strdup_printf("%s/%s%s", toplevel_dir, full_name, ext); -} - -static int -local_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex) -{ - return 0; -} - -static void -local_unlock(CamelLocalFolder *lf) -{ - /* nothing */ -} - -/* for auto-check to work */ -static void -local_refresh_info(CamelFolder *folder, CamelException *ex) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - - if (camel_local_summary_check((CamelLocalSummary *)folder->summary, lf->changes, ex) == -1) - return; - - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } -} - -static void -local_sync(CamelFolder *folder, gboolean expunge, CamelException *ex) -{ - CamelLocalFolder *lf = CAMEL_LOCAL_FOLDER(folder); - - d(printf("local sync '%s' , expunge=%s\n", folder->full_name, expunge?"true":"false")); - - if (camel_local_folder_lock(lf, CAMEL_LOCK_WRITE, ex) == -1) - return; - - camel_object_state_write(lf); - - /* if sync fails, we'll pass it up on exit through ex */ - camel_local_summary_sync((CamelLocalSummary *)folder->summary, expunge, lf->changes, ex); - camel_local_folder_unlock(lf); - - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event(CAMEL_OBJECT(folder), "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } -} - -static void -local_expunge(CamelFolder *folder, CamelException *ex) -{ - d(printf("expunge\n")); - - /* Just do a sync with expunge, serves the same purpose */ - /* call the callback directly, to avoid locking problems */ - CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(folder))->sync(folder, TRUE, ex); -} - -static void -local_delete(CamelFolder *folder) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - - if (lf->index) - camel_index_delete(lf->index); - - parent_class->delete(folder); -} - -static void -local_rename(CamelFolder *folder, const char *newname) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - char *statepath; - - d(printf("renaming local folder paths to '%s'\n", newname)); - - /* Sync? */ - - g_free(lf->folder_path); - g_free(lf->summary_path); - g_free(lf->index_path); - - lf->folder_path = CLOCALF_CLASS(lf)->get_full_path(lf, lf->base_path, newname); - lf->summary_path = CLOCALF_CLASS(lf)->get_meta_path(lf, lf->base_path, newname, ".ev-summary"); - lf->index_path = CLOCALF_CLASS(lf)->get_meta_path(lf, lf->base_path, newname, ".ibex"); - statepath = CLOCALF_CLASS(lf)->get_meta_path(lf, lf->base_path, newname, ".cmeta"); - camel_object_set(lf, NULL, CAMEL_OBJECT_STATE_FILE, statepath, NULL); - g_free(statepath); - - /* FIXME: Poke some internals, sigh */ - camel_folder_summary_set_filename(folder->summary, lf->summary_path); - g_free(((CamelLocalSummary *)folder->summary)->folder_path); - ((CamelLocalSummary *)folder->summary)->folder_path = g_strdup(lf->folder_path); - - parent_class->rename(folder, newname); -} - -static GPtrArray * -local_search_by_expression(CamelFolder *folder, const char *expression, CamelException *ex) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); - GPtrArray *matches; - - CAMEL_LOCAL_FOLDER_LOCK(folder, search_lock); - - if (local_folder->search == NULL) - local_folder->search = camel_folder_search_new(); - - camel_folder_search_set_folder(local_folder->search, folder); - camel_folder_search_set_body_index(local_folder->search, local_folder->index); - matches = camel_folder_search_search(local_folder->search, expression, NULL, ex); - - CAMEL_LOCAL_FOLDER_UNLOCK(folder, search_lock); - - return matches; -} - -static GPtrArray * -local_search_by_uids(CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); - GPtrArray *matches; - - if (uids->len == 0) - return g_ptr_array_new(); - - CAMEL_LOCAL_FOLDER_LOCK(folder, search_lock); - - if (local_folder->search == NULL) - local_folder->search = camel_folder_search_new(); - - camel_folder_search_set_folder(local_folder->search, folder); - camel_folder_search_set_body_index(local_folder->search, local_folder->index); - matches = camel_folder_search_search(local_folder->search, expression, uids, ex); - - CAMEL_LOCAL_FOLDER_UNLOCK(folder, search_lock); - - return matches; -} - -static void -local_search_free(CamelFolder *folder, GPtrArray * result) -{ - CamelLocalFolder *local_folder = CAMEL_LOCAL_FOLDER(folder); - - /* we need to lock this free because of the way search_free_result works */ - /* FIXME: put the lock inside search_free_result */ - CAMEL_LOCAL_FOLDER_LOCK(folder, search_lock); - - camel_folder_search_free_result(local_folder->search, result); - - CAMEL_LOCAL_FOLDER_UNLOCK(folder, search_lock); -} diff --git a/camel/providers/local/camel-local-folder.h b/camel/providers/local/camel-local-folder.h deleted file mode 100644 index 4aec420813..0000000000 --- a/camel/providers/local/camel-local-folder.h +++ /dev/null @@ -1,109 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Author: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999 Ximian (www.ximian.com/). - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_LOCAL_FOLDER_H -#define CAMEL_LOCAL_FOLDER_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include <camel/camel-folder.h> -#include <camel/camel-folder-search.h> -#include <camel/camel-index.h> -#include "camel-local-summary.h" -#include "camel-lock.h" - -/* #include "camel-store.h" */ - -#define CAMEL_LOCAL_FOLDER_TYPE (camel_local_folder_get_type ()) -#define CAMEL_LOCAL_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_LOCAL_FOLDER_TYPE, CamelLocalFolder)) -#define CAMEL_LOCAL_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_LOCAL_FOLDER_TYPE, CamelLocalFolderClass)) -#define CAMEL_IS_LOCAL_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_LOCAL_FOLDER_TYPE)) - -enum { - CAMEL_LOCAL_FOLDER_ARG_INDEX_BODY = CAMEL_FOLDER_ARG_LAST, - - CAMEL_LOCAL_FOLDER_ARG_LAST = CAMEL_FOLDER_ARG_LAST + 0x100 -}; - -enum { - CAMEL_LOCAL_FOLDER_INDEX_BODY = CAMEL_LOCAL_FOLDER_ARG_INDEX_BODY | CAMEL_ARG_BOO, -}; - -typedef struct { - CamelFolder parent_object; - struct _CamelLocalFolderPrivate *priv; - - guint32 flags; /* open mode flags */ - - int locked; /* lock counter */ - CamelLockType locktype; /* what type of lock we have */ - - char *base_path; /* base path of the local folder */ - char *folder_path; /* the path to the folder itself */ - char *summary_path; /* where the summary lives */ - char *index_path; /* where the index file lives */ - - CamelIndex *index; /* index for this folder */ - CamelFolderSearch *search; /* used to run searches, we just use the real thing (tm) */ - CamelFolderChangeInfo *changes; /* used to store changes to the folder during processing */ -} CamelLocalFolder; - -typedef struct { - CamelFolderClass parent_class; - - /* Virtual methods */ - - /* path construction, only used at init */ - char * (* get_full_path)(CamelLocalFolder *lf, const char *toplevel_dir, const char *full_name); - char * (* get_meta_path)(CamelLocalFolder *lf, const char *toplevel_dir, const char *full_name, const char *ext); - - /* summary factory, only used at init */ - CamelLocalSummary *(*create_summary)(CamelLocalFolder *lf, const char *path, const char *folder, CamelIndex *index); - - /* Lock the folder for my operations */ - int (*lock)(CamelLocalFolder *, CamelLockType type, CamelException *ex); - - /* Unlock the folder for my operations */ - void (*unlock)(CamelLocalFolder *); -} CamelLocalFolderClass; - - -/* public methods */ -/* flags are taken from CAMEL_STORE_FOLDER_* flags */ -CamelLocalFolder *camel_local_folder_construct(CamelLocalFolder *lf, CamelStore *parent_store, - const char *full_name, guint32 flags, CamelException *ex); - -/* Standard Camel function */ -CamelType camel_local_folder_get_type(void); - -/* Lock the folder for internal use. May be called repeatedly */ -/* UNIMPLEMENTED */ -int camel_local_folder_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex); -int camel_local_folder_unlock(CamelLocalFolder *lf); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_LOCAL_FOLDER_H */ diff --git a/camel/providers/local/camel-local-private.h b/camel/providers/local/camel-local-private.h deleted file mode 100644 index e8e5061fae..0000000000 --- a/camel/providers/local/camel-local-private.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright 1999-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef CAMEL_LOCAL_PRIVATE_H -#define CAMEL_LOCAL_PRIVATE_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -/* need a way to configure and save this data, if this header is to - be installed. For now, dont install it */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <pthread.h> - -struct _CamelLocalFolderPrivate { - GMutex *search_lock; /* for locking the search object */ -}; - -#define CAMEL_LOCAL_FOLDER_LOCK(f, l) (g_mutex_lock(((CamelLocalFolder *)f)->priv->l)) -#define CAMEL_LOCAL_FOLDER_UNLOCK(f, l) (g_mutex_unlock(((CamelLocalFolder *)f)->priv->l)) - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_LOCAL_PRIVATE_H */ - diff --git a/camel/providers/local/camel-local-provider.c b/camel/providers/local/camel-local-provider.c deleted file mode 100644 index 7411d8f639..0000000000 --- a/camel/providers/local/camel-local-provider.c +++ /dev/null @@ -1,234 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2000 Ximian (www.ximian.com). - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <string.h> - -#include "camel-provider.h" -#include "camel-session.h" -#include "camel-url.h" - -#include "camel-mh-store.h" -#include "camel-mbox-store.h" -#include "camel-maildir-store.h" -#include "camel-spool-store.h" -#include "camel-i18n.h" - -#define d(x) - -static CamelProviderConfEntry mh_conf_entries[] = { - CAMEL_PROVIDER_CONF_DEFAULT_PATH, - { CAMEL_PROVIDER_CONF_SECTION_START, "general", NULL, N_("Options") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "dotfolders", NULL, - N_("Use the `.folders' folder summary file (exmh)"), "0" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider mh_provider = { - "mh", - N_("MH-format mail directories"), - N_("For storing local mail in MH-like mail directories."), - "mail", - CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_IS_LOCAL, - CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE | CAMEL_URL_FRAGMENT_IS_PATH, - mh_conf_entries, - /* ... */ -}; - -static CamelProviderConfEntry mbox_conf_entries[] = { - CAMEL_PROVIDER_CONF_DEFAULT_PATH, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider mbox_provider = { - "mbox", - N_("Local delivery"), - N_("For retrieving (moving) local mail from standard mbox formated spools into folders managed by Evolution."), - "mail", - CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_IS_LOCAL, - CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE | CAMEL_URL_FRAGMENT_IS_PATH, - mbox_conf_entries, - /* ... */ -}; - -static CamelProviderConfEntry maildir_conf_entries[] = { - CAMEL_PROVIDER_CONF_DEFAULT_PATH, - { CAMEL_PROVIDER_CONF_SECTION_START, "general", NULL, N_("Options") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter", NULL, - N_("Apply filters to new messages in INBOX"), "0" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider maildir_provider = { - "maildir", - N_("Maildir-format mail directories"), - N_("For storing local mail in maildir directories."), - "mail", - CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_IS_LOCAL, - CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE | CAMEL_URL_FRAGMENT_IS_PATH, - maildir_conf_entries, - /* ... */ -}; - -static CamelProviderConfEntry spool_conf_entries[] = { - CAMEL_PROVIDER_CONF_DEFAULT_PATH, - { CAMEL_PROVIDER_CONF_SECTION_START, "general", NULL, N_("Options") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "filter", NULL, N_("Apply filters to new messages in INBOX"), "0" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "xstatus", NULL, N_("Store status headers in Elm/Pine/Mutt format"), "0" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider spool_provider = { - "spool", - N_("Standard Unix mbox spool or directory"), - N_("For reading and storing local mail in external standard mbox spool files.\nMay also be used to read a tree of Elm, Pine, or Mutt style folders."), - "mail", - CAMEL_PROVIDER_IS_SOURCE | CAMEL_PROVIDER_IS_STORAGE, - CAMEL_URL_NEED_PATH | CAMEL_URL_PATH_IS_ABSOLUTE | CAMEL_URL_FRAGMENT_IS_PATH, - spool_conf_entries, - /* ... */ -}; - -/* build a canonical 'path' */ -static char * -make_can_path(char *p, char *o) -{ - char c, last, *start = o; - - d(printf("canonical '%s' = ", p)); - - last = 0; - while ((c = *p++)) { - if (c!='/' - || (c=='/' && last != '/')) - *o++ = c; - last = c; - } - if (o>start && o[-1] == '/') - o[-1] = 0; - else - *o = 0; - - d(printf("'%s'\n", start)); - - return start; -} - -/* 'helper' function for it */ -#define get_can_path(p) ((p == NULL) ? NULL : (make_can_path ((p), g_alloca (strlen (p) + 1)))) - -static guint -local_url_hash (const void *v) -{ - const CamelURL *u = v; - guint hash = 0; - -#define ADD_HASH(s) if (s) hash ^= g_str_hash (s); - - ADD_HASH (u->protocol); - ADD_HASH (u->user); - ADD_HASH (u->authmech); - ADD_HASH (u->host); - if (u->path) - hash ^= g_str_hash(get_can_path(u->path)); - ADD_HASH (u->path); - ADD_HASH (u->query); - hash ^= u->port; - - return hash; -} - -static int -check_equal (char *s1, char *s2) -{ - if (s1 == NULL) { - if (s2 == NULL) - return TRUE; - else - return FALSE; - } - - if (s2 == NULL) - return FALSE; - - return strcmp (s1, s2) == 0; -} - -static int -local_url_equal(const void *v, const void *v2) -{ - const CamelURL *u1 = v, *u2 = v2; - char *p1, *p2; - - p1 = get_can_path(u1->path); - p2 = get_can_path(u2->path); - return check_equal(p1, p2) - && check_equal(u1->protocol, u2->protocol) - && check_equal(u1->user, u2->user) - && check_equal(u1->authmech, u2->authmech) - && check_equal(u1->host, u2->host) - && check_equal(u1->query, u2->query) - && u1->port == u2->port; -} - -void camel_provider_module_init(void) -{ - char *path; - static int init = 0; - - if (init) - abort(); - init = 1; - - mh_conf_entries[0].value = ""; /* default path */ - mh_provider.object_types[CAMEL_PROVIDER_STORE] = camel_mh_store_get_type (); - mh_provider.url_hash = local_url_hash; - mh_provider.url_equal = local_url_equal; - camel_provider_register(&mh_provider); - - if (!(path = getenv ("MAIL"))) - path = g_strdup_printf (SYSTEM_MAIL_DIR "/%s", g_get_user_name ()); - mbox_conf_entries[0].value = path; /* default path */ - mbox_provider.object_types[CAMEL_PROVIDER_STORE] = camel_mbox_store_get_type (); - mbox_provider.url_hash = local_url_hash; - mbox_provider.url_equal = local_url_equal; - camel_provider_register(&mbox_provider); - - spool_conf_entries[0].value = path; /* default path - same as mbox */ - spool_provider.object_types[CAMEL_PROVIDER_STORE] = camel_spool_store_get_type (); - spool_provider.url_hash = local_url_hash; - spool_provider.url_equal = local_url_equal; - camel_provider_register(&spool_provider); - - path = getenv("MAILDIR"); - maildir_conf_entries[0].value = path ? path : ""; /* default path */ - maildir_provider.object_types[CAMEL_PROVIDER_STORE] = camel_maildir_store_get_type (); - maildir_provider.url_hash = local_url_hash; - maildir_provider.url_equal = local_url_equal; - camel_provider_register(&maildir_provider); -} diff --git a/camel/providers/local/camel-local-store.c b/camel/providers/local/camel-local-store.c deleted file mode 100644 index a89fee16c5..0000000000 --- a/camel/providers/local/camel-local-store.c +++ /dev/null @@ -1,477 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2000 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/stat.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> -#include <stdio.h> - -#include <glib.h> - -#include "camel-private.h" - -#include "camel-local-store.h" -#include "camel-exception.h" -#include "camel-url.h" -#include "camel-i18n.h" - -#include "camel-local-folder.h" -#include <camel/camel-text-index.h> -#include <camel/camel-file-utils.h> - -#define d(x) - -/* Returns the class for a CamelLocalStore */ -#define CLOCALS_CLASS(so) CAMEL_LOCAL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static void construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex); -static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex); -static char *get_name(CamelService *service, gboolean brief); -static CamelFolder *local_get_inbox (CamelStore *store, CamelException *ex); -static CamelFolder *local_get_junk(CamelStore *store, CamelException *ex); -static CamelFolder *local_get_trash(CamelStore *store, CamelException *ex); -static CamelFolderInfo *get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex); -static void delete_folder(CamelStore *store, const char *folder_name, CamelException *ex); -static void rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex); -static CamelFolderInfo *create_folder(CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex); - -static CamelStoreClass *parent_class = NULL; - -static void -camel_local_store_class_init (CamelLocalStoreClass *camel_local_store_class) -{ - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_local_store_class); - CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS (camel_local_store_class); - - parent_class = CAMEL_STORE_CLASS (camel_type_get_global_classfuncs (camel_store_get_type ())); - - /* virtual method overload */ - camel_service_class->construct = construct; - camel_service_class->get_name = get_name; - camel_store_class->get_folder = get_folder; - camel_store_class->get_inbox = local_get_inbox; - camel_store_class->get_trash = local_get_trash; - camel_store_class->get_junk = local_get_junk; - camel_store_class->get_folder_info = get_folder_info; - camel_store_class->free_folder_info = camel_store_free_folder_info_full; - - camel_store_class->create_folder = create_folder; - camel_store_class->delete_folder = delete_folder; - camel_store_class->rename_folder = rename_folder; -} - -static void -camel_local_store_finalize (CamelLocalStore *local_store) -{ - if (local_store->toplevel_dir) - g_free (local_store->toplevel_dir); -} - -CamelType -camel_local_store_get_type (void) -{ - static CamelType camel_local_store_type = CAMEL_INVALID_TYPE; - - if (camel_local_store_type == CAMEL_INVALID_TYPE) { - camel_local_store_type = camel_type_register (CAMEL_STORE_TYPE, "CamelLocalStore", - sizeof (CamelLocalStore), - sizeof (CamelLocalStoreClass), - (CamelObjectClassInitFunc) camel_local_store_class_init, - NULL, - NULL, - (CamelObjectFinalizeFunc) camel_local_store_finalize); - } - - return camel_local_store_type; -} - -static void -construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex) -{ - CamelLocalStore *local_store = CAMEL_LOCAL_STORE (service); - int len; - - CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); - if (camel_exception_is_set (ex)) - return; - - len = strlen (service->url->path); - if (service->url->path[len - 1] != '/') - local_store->toplevel_dir = g_strdup_printf ("%s/", service->url->path); - else - local_store->toplevel_dir = g_strdup (service->url->path); -} - -const char * -camel_local_store_get_toplevel_dir (CamelLocalStore *store) -{ - return store->toplevel_dir; -} - -static CamelFolder * -get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex) -{ - char *path = ((CamelLocalStore *)store)->toplevel_dir; - struct stat st; - - if (path[0] != '/') { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Store root %s is not an absolute path"), path); - return NULL; - } - - if (stat(path, &st) == 0) { - if (!S_ISDIR(st.st_mode)) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Store root %s is not a regular directory"), path); - return NULL; - } - return (CamelFolder *) 0xdeadbeef; - } - - if (errno != ENOENT - || (flags & CAMEL_STORE_FOLDER_CREATE) == 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot get folder: %s: %s"), - path, g_strerror (errno)); - return NULL; - } - - /* need to create the dir heirarchy */ - if (camel_mkdir (path, 0777) == -1 && errno != EEXIST) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot get folder: %s: %s"), - path, g_strerror (errno)); - return NULL; - } - - return (CamelFolder *) 0xdeadbeef; -} - -static CamelFolder * -local_get_inbox(CamelStore *store, CamelException *ex) -{ - camel_exception_set(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Local stores do not have an inbox")); - return NULL; -} - -static CamelFolder * -local_get_trash(CamelStore *store, CamelException *ex) -{ - CamelFolder *folder = CAMEL_STORE_CLASS(parent_class)->get_trash(store, ex); - - if (folder) { - char *state = g_build_filename(((CamelLocalStore *)store)->toplevel_dir, ".Trash.cmeta", NULL); - - camel_object_set(folder, NULL, CAMEL_OBJECT_STATE_FILE, state, NULL); - g_free(state); - /* no defaults? */ - camel_object_state_read(folder); - } - - return folder; -} - -static CamelFolder * -local_get_junk(CamelStore *store, CamelException *ex) -{ - CamelFolder *folder = CAMEL_STORE_CLASS(parent_class)->get_junk(store, ex); - - if (folder) { - char *state = g_build_filename(((CamelLocalStore *)store)->toplevel_dir, ".Junk.cmeta", NULL); - - camel_object_set(folder, NULL, CAMEL_OBJECT_STATE_FILE, state, NULL); - g_free(state); - /* no defaults? */ - camel_object_state_read(folder); - } - - return folder; -} - -static char * -get_name (CamelService *service, gboolean brief) -{ - char *dir = ((CamelLocalStore*)service)->toplevel_dir; - - if (brief) - return g_strdup (dir); - else - return g_strdup_printf (_("Local mail file %s"), dir); -} - -static CamelFolderInfo * -get_folder_info (CamelStore *store, const char *top, - guint32 flags, CamelException *ex) -{ - /* FIXME: This is broken, but it corresponds to what was - * there before. - */ - - d(printf("-- LOCAL STORE -- get folder info: %s\n", top)); - - return NULL; -} - -static CamelFolderInfo * -create_folder(CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex) -{ - char *path = ((CamelLocalStore *)store)->toplevel_dir; - char *name; - CamelFolder *folder; - CamelFolderInfo *info = NULL; - struct stat st; - - /* This is a pretty hacky version of create folder, but should basically work */ - - if (path[0] != '/') { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Store root %s is not an absolute path"), path); - return NULL; - } - - if (parent_name) - name = g_strdup_printf("%s/%s/%s", path, parent_name, folder_name); - else - name = g_strdup_printf("%s/%s", path, folder_name); - - if (stat(name, &st) == 0 || errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot get folder: %s: %s"), - name, g_strerror (errno)); - g_free(name); - return NULL; - } - - g_free(name); - - if (parent_name) - name = g_strdup_printf("%s/%s", parent_name, folder_name); - else - name = g_strdup_printf("%s", folder_name); - - folder = ((CamelStoreClass *)((CamelObject *)store)->klass)->get_folder(store, name, CAMEL_STORE_FOLDER_CREATE, ex); - if (folder) { - camel_object_unref((CamelObject *)folder); - info = ((CamelStoreClass *)((CamelObject *)store)->klass)->get_folder_info(store, name, 0, ex); - - /* get_folder(CREATE) will emit a folder_created event for us */ - /*if (info) - camel_object_trigger_event((CamelObject *)store, "folder_created", info);*/ - } - - g_free(name); - - return info; -} - -static int xrename(const char *oldp, const char *newp, const char *prefix, const char *suffix, int missingok, CamelException *ex) -{ - struct stat st; - char *old = g_strconcat(prefix, oldp, suffix, 0); - char *new = g_strconcat(prefix, newp, suffix, 0); - int ret = -1; - int err = 0; - - d(printf("renaming %s%s to %s%s\n", oldp, suffix, newp, suffix)); - - if (stat(old, &st) == -1) { - if (missingok && errno == ENOENT) { - ret = 0; - } else { - err = errno; - ret = -1; - } - } else if (S_ISDIR(st.st_mode)) { /* use rename for dirs */ - if (rename(old, new) == 0 - || stat(new, &st) == 0) { - ret = 0; - } else { - err = errno; - ret = -1; - } - } else if (link(old, new) == 0 /* and link for files */ - || (stat(new, &st) == 0 && st.st_nlink == 2)) { - if (unlink(old) == 0) { - ret = 0; - } else { - err = errno; - unlink(new); - ret = -1; - } - } else { - err = errno; - ret = -1; - } - - if (ret == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not rename folder %s to %s: %s"), - old, new, g_strerror (err)); - } - - g_free(old); - g_free(new); - return ret; -} - -/* default implementation, rename all */ -static void -rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex) -{ - char *path = CAMEL_LOCAL_STORE (store)->toplevel_dir; - CamelLocalFolder *folder = NULL; - char *newibex = g_strdup_printf("%s%s.ibex", path, new); - char *oldibex = g_strdup_printf("%s%s.ibex", path, old); - - /* try to rollback failures, has obvious races */ - - d(printf("local rename folder '%s' '%s'\n", old, new)); - - folder = camel_object_bag_get(store->folders, old); - if (folder && folder->index) { - if (camel_index_rename(folder->index, newibex) == -1) - goto ibex_failed; - } else { - /* TODO: camel_text_index_rename should find out if we have an active index itself? */ - if (camel_text_index_rename(oldibex, newibex) == -1) - goto ibex_failed; - } - - if (xrename(old, new, path, ".ev-summary", TRUE, ex)) - goto summary_failed; - - if (xrename(old, new, path, ".cmeta", TRUE, ex)) - goto cmeta_failed; - - if (xrename(old, new, path, "", FALSE, ex)) - goto base_failed; - - g_free(newibex); - g_free(oldibex); - - if (folder) - camel_object_unref(folder); - - return; - - /* The (f)utility of this recovery effort is quesitonable */ - -base_failed: - xrename(new, old, path, ".cmeta", TRUE, ex); - -cmeta_failed: - xrename(new, old, path, ".ev-summary", TRUE, ex); - -summary_failed: - if (folder) { - if (folder->index) - camel_index_rename(folder->index, oldibex); - } else - camel_text_index_rename(newibex, oldibex); -ibex_failed: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not rename '%s': %s"), - old, g_strerror (errno)); - - g_free(newibex); - g_free(oldibex); - - if (folder) - camel_object_unref(folder); -} - -/* default implementation, only delete metadata */ -static void -delete_folder(CamelStore *store, const char *folder_name, CamelException *ex) -{ - CamelFolderInfo *fi; - CamelException lex; - CamelFolder *lf; - char *name; - char *str; - - /* remove metadata only */ - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - str = g_strdup_printf("%s.ev-summary", name); - if (unlink(str) == -1 && errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder summary file `%s': %s"), - str, g_strerror (errno)); - g_free(str); - g_free (name); - return; - } - g_free(str); - str = g_strdup_printf("%s.ibex", name); - if (camel_text_index_remove(str) == -1 && errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder index file `%s': %s"), - str, g_strerror (errno)); - g_free(str); - g_free (name); - return; - } - g_free(str); - - str = NULL; - camel_exception_init (&lex); - if ((lf = camel_store_get_folder (store, folder_name, 0, &lex))) { - camel_object_get (lf, NULL, CAMEL_OBJECT_STATE_FILE, &str, NULL); - camel_object_set (lf, NULL, CAMEL_OBJECT_STATE_FILE, NULL, NULL); - camel_object_unref (lf); - } else { - camel_exception_clear (&lex); - } - - if (str == NULL) - str = g_strdup_printf ("%s.cmeta", name); - - if (unlink (str) == -1 && errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder meta file `%s': %s"), - str, g_strerror (errno)); - g_free (name); - g_free (str); - return; - } - - g_free (str); - g_free (name); - - fi = g_new0 (CamelFolderInfo, 1); - fi->full_name = g_strdup (folder_name); - fi->name = g_path_get_basename (folder_name); - fi->uri = g_strdup_printf ("%s:%s#%s", ((CamelService *) store)->url->protocol, - CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - fi->unread = -1; - - camel_object_trigger_event (store, "folder_deleted", fi); - - camel_folder_info_free (fi); -} diff --git a/camel/providers/local/camel-local-store.h b/camel/providers/local/camel-local-store.h deleted file mode 100644 index 21d854c562..0000000000 --- a/camel/providers/local/camel-local-store.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-mbox-store.h : class for an mbox store */ - -/* - * - * Copyright (C) 2000 Ximian, Inc. <bertrand@helixcode.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_LOCAL_STORE_H -#define CAMEL_LOCAL_STORE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-store.h" - -#define CAMEL_LOCAL_STORE_TYPE (camel_local_store_get_type ()) -#define CAMEL_LOCAL_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_LOCAL_STORE_TYPE, CamelLocalStore)) -#define CAMEL_LOCAL_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_LOCAL_STORE_TYPE, CamelLocalStoreClass)) -#define CAMEL_IS_LOCAL_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_LOCAL_STORE_TYPE)) - - -typedef struct { - CamelStore parent_object; - char *toplevel_dir; - -} CamelLocalStore; - - - -typedef struct { - CamelStoreClass parent_class; - -} CamelLocalStoreClass; - - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_local_store_get_type (void); - -const gchar *camel_local_store_get_toplevel_dir (CamelLocalStore *store); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_LOCAL_STORE_H */ - - diff --git a/camel/providers/local/camel-local-summary.c b/camel/providers/local/camel-local-summary.c deleted file mode 100644 index 0a4f96b552..0000000000 --- a/camel/providers/local/camel-local-summary.c +++ /dev/null @@ -1,652 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <ctype.h> -#include <sys/stat.h> -#include <sys/uio.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> - -#include "camel-local-summary.h" -#include "camel/camel-mime-message.h" -#include "camel/camel-stream-null.h" -#include "camel/camel-file-utils.h" -#include "camel/camel-i18n.h" - -#define w(x) -#define io(x) -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -#define CAMEL_LOCAL_SUMMARY_VERSION (1) - -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 int local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelLocalMessageInfo *mi); -static char *local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelLocalMessageInfo *mi); - -static int local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex); -static int local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static int local_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static CamelMessageInfo *local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); - -static void camel_local_summary_class_init (CamelLocalSummaryClass *klass); -static void camel_local_summary_init (CamelLocalSummary *obj); -static void camel_local_summary_finalise (CamelObject *obj); -static CamelFolderSummaryClass *camel_local_summary_parent; - -CamelType -camel_local_summary_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_folder_summary_get_type(), "CamelLocalSummary", - sizeof (CamelLocalSummary), - sizeof (CamelLocalSummaryClass), - (CamelObjectClassInitFunc) camel_local_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_local_summary_init, - (CamelObjectFinalizeFunc) camel_local_summary_finalise); - } - - return type; -} - -static void -camel_local_summary_class_init(CamelLocalSummaryClass *klass) -{ - CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *) klass; - - camel_local_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS(camel_type_get_global_classfuncs(camel_folder_summary_get_type())); - - sklass->summary_header_load = summary_header_load; - sklass->summary_header_save = summary_header_save; - - sklass->message_info_new_from_header = message_info_new_from_header; - - klass->load = local_summary_load; - klass->check = local_summary_check; - klass->sync = local_summary_sync; - klass->add = local_summary_add; - - klass->encode_x_evolution = local_summary_encode_x_evolution; - klass->decode_x_evolution = local_summary_decode_x_evolution; -} - -static void -camel_local_summary_init(CamelLocalSummary *obj) -{ - struct _CamelFolderSummary *s = (CamelFolderSummary *)obj; - - /* subclasses need to set the right instance data sizes */ - s->message_info_size = sizeof(CamelLocalMessageInfo); - s->content_info_size = sizeof(CamelMessageContentInfo); - - /* and a unique file version */ - s->version += CAMEL_LOCAL_SUMMARY_VERSION; -} - -static void -camel_local_summary_finalise(CamelObject *obj) -{ - CamelLocalSummary *mbs = CAMEL_LOCAL_SUMMARY(obj); - - if (mbs->index) - camel_object_unref((CamelObject *)mbs->index); - g_free(mbs->folder_path); -} - -void -camel_local_summary_construct(CamelLocalSummary *new, const char *filename, const char *local_name, CamelIndex *index) -{ - camel_folder_summary_set_build_content(CAMEL_FOLDER_SUMMARY(new), FALSE); - camel_folder_summary_set_filename(CAMEL_FOLDER_SUMMARY(new), filename); - new->folder_path = g_strdup(local_name); - new->index = index; - if (index) - camel_object_ref((CamelObject *)index); -} - -static int -local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex) -{ - return camel_folder_summary_load((CamelFolderSummary *)cls); -} - -/* load/check the summary */ -int -camel_local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex) -{ - struct stat st; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - - d(printf("Loading summary ...\n")); - - if (forceindex - || stat(s->summary_path, &st) == -1 - || ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->load(cls, forceindex, ex) == -1) { - w(g_warning("Could not load summary: flags may be reset")); - camel_folder_summary_clear((CamelFolderSummary *)cls); - return -1; - } - - return 0; -} - -void camel_local_summary_check_force(CamelLocalSummary *cls) -{ - cls->check_force = 1; -} - -char * -camel_local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelLocalMessageInfo *info) -{ - return ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->encode_x_evolution(cls, info); -} - -int -camel_local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelLocalMessageInfo *info) -{ - return ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->decode_x_evolution(cls, xev, info); -} - -/*#define DOSTATS*/ -#ifdef DOSTATS -struct _stat_info { - int mitotal; - int micount; - int citotal; - int cicount; - int msgid; - int msgcount; -}; - -static void -do_stat_ci(CamelLocalSummary *cls, struct _stat_info *info, CamelMessageContentInfo *ci) -{ - info->cicount++; - info->citotal += ((CamelFolderSummary *)cls)->content_info_size /*+ 4 memchunks are 1/4 byte overhead per mi */; - if (ci->id) - info->citotal += strlen(ci->id) + 4; - if (ci->description) - info->citotal += strlen(ci->description) + 4; - if (ci->encoding) - info->citotal += strlen(ci->encoding) + 4; - if (ci->type) { - CamelContentType *ct = ci->type; - struct _camel_header_param *param; - - info->citotal += sizeof(*ct) + 4; - if (ct->type) - info->citotal += strlen(ct->type) + 4; - if (ct->subtype) - info->citotal += strlen(ct->subtype) + 4; - param = ct->params; - while (param) { - info->citotal += sizeof(*param) + 4; - if (param->name) - info->citotal += strlen(param->name)+4; - if (param->value) - info->citotal += strlen(param->value)+4; - param = param->next; - } - } - ci = ci->childs; - while (ci) { - do_stat_ci(cls, info, ci); - ci = ci->next; - } -} - -static void -do_stat_mi(CamelLocalSummary *cls, struct _stat_info *info, CamelMessageInfo *mi) -{ - info->micount++; - info->mitotal += ((CamelFolderSummary *)cls)->content_info_size /*+ 4*/; - - if (mi->subject) - info->mitotal += strlen(mi->subject) + 4; - if (mi->to) - info->mitotal += strlen(mi->to) + 4; - if (mi->from) - info->mitotal += strlen(mi->from) + 4; - if (mi->cc) - info->mitotal += strlen(mi->cc) + 4; - if (mi->uid) - info->mitotal += strlen(mi->uid) + 4; - - if (mi->references) { - info->mitotal += (mi->references->size-1) * sizeof(CamelSummaryMessageID) + sizeof(CamelSummaryReferences) + 4; - info->msgid += (mi->references->size) * sizeof(CamelSummaryMessageID); - info->msgcount += mi->references->size; - } - - /* dont have any user flags yet */ - - if (mi->content) { - do_stat_ci(cls, info, mi->content); - } -} - -#endif - -int -camel_local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - int ret; - - ret = ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->check(cls, changeinfo, ex); - -#ifdef DOSTATS - if (ret != -1) { - int i; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - struct _stat_info stats = { 0 }; - - for (i=0;i<camel_folder_summary_count(s);i++) { - CamelMessageInfo *info = camel_folder_summary_index(s, i); - do_stat_mi(cls, &stats, info); - camel_message_info_free(info); - } - - printf("\nMemory used by summary:\n\n"); - printf("Total of %d messages\n", camel_folder_summary_count(s)); - printf("Total: %d bytes (ave %f)\n", stats.citotal + stats.mitotal, - (double)(stats.citotal+stats.mitotal)/(double)camel_folder_summary_count(s)); - printf("Message Info: %d (ave %f)\n", stats.mitotal, (double)stats.mitotal/(double)stats.micount); - printf("Content Info; %d (ave %f) count %d\n", stats.citotal, (double)stats.citotal/(double)stats.cicount, stats.cicount); - printf("message id's: %d (ave %f) count %d\n", stats.msgid, (double)stats.msgid/(double)stats.msgcount, stats.msgcount); - } -#endif - return ret; -} - -int -camel_local_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - return ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->sync(cls, expunge, changeinfo, ex); -} - -CamelMessageInfo * -camel_local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *ci, CamelException *ex) -{ - return ((CamelLocalSummaryClass *)(CAMEL_OBJECT_GET_CLASS(cls)))->add(cls, msg, info, ci, ex); -} - -/** - * camel_local_summary_write_headers: - * @fd: - * @header: - * @xevline: - * @status: - * @xstatus: - * - * Write a bunch of headers to the file @fd. IF xevline is non NULL, then - * an X-Evolution header line is created at the end of all of the headers. - * If @status is non NULL, then a Status header line is also written. - * The headers written are termianted with a blank line. - * - * Return value: -1 on error, otherwise the number of bytes written. - **/ -int -camel_local_summary_write_headers(int fd, struct _camel_header_raw *header, const char *xevline, const char *status, const char *xstatus) -{ - int outlen = 0, len; - int newfd; - FILE *out; - - /* dum de dum, maybe the whole sync function should just use stdio for output */ - newfd = dup(fd); - if (newfd == -1) - return -1; - - out = fdopen(newfd, "w"); - if (out == NULL) { - close(newfd); - errno = EINVAL; - return -1; - } - - while (header) { - if (strcmp(header->name, "X-Evolution") != 0 - && (status == NULL || strcmp(header->name, "Status") != 0) - && (xstatus == NULL || strcmp(header->name, "X-Status") != 0)) { - len = fprintf(out, "%s:%s\n", header->name, header->value); - if (len == -1) { - fclose(out); - return -1; - } - outlen += len; - } - header = header->next; - } - - if (status) { - len = fprintf(out, "Status: %s\n", status); - if (len == -1) { - fclose(out); - return -1; - } - outlen += len; - } - - if (xstatus) { - len = fprintf(out, "X-Status: %s\n", xstatus); - if (len == -1) { - fclose(out); - return -1; - } - outlen += len; - } - - if (xevline) { - len = fprintf(out, "X-Evolution: %s\n", xevline); - if (len == -1) { - fclose(out); - return -1; - } - outlen += len; - } - - len = fprintf(out, "\n"); - if (len == -1) { - fclose(out); - return -1; - } - outlen += len; - - if (fclose(out) == -1) - return -1; - - return outlen; -} - -static int -local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - /* FIXME: sync index here ? */ - return 0; -} - -static int -local_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - int ret = 0; - - ret = camel_folder_summary_save((CamelFolderSummary *)cls); - if (ret == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not save summary: %s: %s"), - cls->folder_path, g_strerror (errno)); - - g_warning ("Could not save summary for %s: %s", cls->folder_path, strerror (errno)); - } - - if (cls->index && camel_index_sync(cls->index) == -1) - g_warning ("Could not sync index for %s: %s", cls->folder_path, strerror (errno)); - - return ret; -} - -static CamelMessageInfo * -local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *ci, CamelException *ex) -{ - CamelLocalMessageInfo *mi; - char *xev; - - d(printf("Adding message to summary\n")); - - mi = (CamelLocalMessageInfo *)camel_folder_summary_add_from_message((CamelFolderSummary *)cls, msg); - if (mi) { - d(printf("Added, uid = %s\n", mi->uid)); - if (info) { - const CamelTag *tag = camel_message_info_user_tags(info); - const CamelFlag *flag = camel_message_info_user_flags(info); - - while (flag) { - camel_message_info_set_user_flag((CamelMessageInfo *)mi, flag->name, TRUE); - flag = flag->next; - } - - while (tag) { - camel_message_info_set_user_tag((CamelMessageInfo *)mi, tag->name, tag->value); - tag = tag->next; - } - - mi->info.flags |= (camel_message_info_flags(info) & 0xffff); - mi->info.size = camel_message_info_size(info); - } - - /* we need to calculate the size ourselves */ - if (mi->info.size == 0) { - CamelStreamNull *sn = (CamelStreamNull *)camel_stream_null_new(); - - camel_data_wrapper_write_to_stream((CamelDataWrapper *)msg, (CamelStream *)sn); - mi->info.size = sn->written; - camel_object_unref((CamelObject *)sn); - } - - mi->info.flags &= ~(CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_FLAGGED); - xev = camel_local_summary_encode_x_evolution(cls, mi); - camel_medium_set_header((CamelMedium *)msg, "X-Evolution", xev); - g_free(xev); - camel_folder_change_info_add_uid(ci, camel_message_info_uid(mi)); - } else { - d(printf("Failed!\n")); - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Unable to add message to summary: unknown reason")); - } - return (CamelMessageInfo *)mi; -} - -static char * -local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelLocalMessageInfo *mi) -{ - GString *out = g_string_new(""); - struct _camel_header_param *params = NULL; - GString *val = g_string_new(""); - CamelFlag *flag = mi->info.user_flags; - CamelTag *tag = mi->info.user_tags; - char *ret; - const char *p, *uidstr; - guint32 uid; - - /* FIXME: work out what to do with uid's that aren't stored here? */ - /* FIXME: perhaps make that a mbox folder only issue?? */ - p = uidstr = camel_message_info_uid(mi); - while (*p && isdigit(*p)) - p++; - if (*p == 0 && sscanf (uidstr, "%u", &uid) == 1) { - g_string_printf (out, "%08x-%04x", uid, mi->info.flags & 0xffff); - } else { - g_string_printf (out, "%s-%04x", uidstr, mi->info.flags & 0xffff); - } - - if (flag || tag) { - val = g_string_new (""); - - if (flag) { - while (flag) { - g_string_append (val, flag->name); - if (flag->next) - g_string_append_c (val, ','); - flag = flag->next; - } - camel_header_set_param (¶ms, "flags", val->str); - g_string_truncate (val, 0); - } - if (tag) { - while (tag) { - g_string_append (val, tag->name); - g_string_append_c (val, '='); - g_string_append (val, tag->value); - if (tag->next) - g_string_append_c (val, ','); - tag = tag->next; - } - camel_header_set_param (¶ms, "tags", val->str); - } - g_string_free (val, TRUE); - camel_header_param_list_format_append (out, params); - camel_header_param_list_free (params); - } - ret = out->str; - g_string_free (out, FALSE); - - return ret; -} - -static int -local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelLocalMessageInfo *mi) -{ - struct _camel_header_param *params, *scan; - guint32 uid, flags; - char *header; - int i; - char uidstr[20]; - - uidstr[0] = 0; - - /* check for uid/flags */ - header = camel_header_token_decode(xev); - if (header && strlen(header) == strlen("00000000-0000") - && sscanf(header, "%08x-%04x", &uid, &flags) == 2) { - if (mi) - sprintf(uidstr, "%u", uid); - } else { - g_free(header); - return -1; - } - g_free(header); - - if (mi == NULL) - return 0; - - /* check for additional data */ - header = strchr(xev, ';'); - if (header) { - params = camel_header_param_list_decode(header+1); - scan = params; - while (scan) { - if (!strcasecmp(scan->name, "flags")) { - char **flagv = g_strsplit(scan->value, ",", 1000); - - for (i=0;flagv[i];i++) - camel_message_info_set_user_flag((CamelMessageInfo *)mi, flagv[i], TRUE); - g_strfreev(flagv); - } else if (!strcasecmp(scan->name, "tags")) { - char **tagv = g_strsplit(scan->value, ",", 10000); - char *val; - - for (i=0;tagv[i];i++) { - val = strchr(tagv[i], '='); - if (val) { - *val++ = 0; - camel_message_info_set_user_tag((CamelMessageInfo *)mi, tagv[i], val); - val[-1]='='; - } - } - g_strfreev(tagv); - } - scan = scan->next; - } - camel_header_param_list_free(params); - } - - mi->info.uid = g_strdup(uidstr); - mi->info.flags = flags; - - return 0; -} - -static int -summary_header_load(CamelFolderSummary *s, FILE *in) -{ - CamelLocalSummary *cls = (CamelLocalSummary *)s; - - /* We dont actually add our own headers, but version that we don't anyway */ - - if (((CamelFolderSummaryClass *)camel_local_summary_parent)->summary_header_load(s, in) == -1) - return -1; - - /* Legacy version, version is in summary only */ - if ((s->version & 0xfff) == 0x20c) - return 0; - - /* otherwise load the version number */ - return camel_file_util_decode_fixed_int32(in, &cls->version); -} - -static int -summary_header_save(CamelFolderSummary *s, FILE *out) -{ - /*CamelLocalSummary *cls = (CamelLocalSummary *)s;*/ - - if (((CamelFolderSummaryClass *)camel_local_summary_parent)->summary_header_save(s, out) == -1) - return -1; - - return camel_file_util_encode_fixed_int32(out, CAMEL_LOCAL_SUMMARY_VERSION); -} - -static CamelMessageInfo * -message_info_new_from_header(CamelFolderSummary *s, struct _camel_header_raw *h) -{ - CamelLocalMessageInfo *mi; - CamelLocalSummary *cls = (CamelLocalSummary *)s; - - mi = (CamelLocalMessageInfo *)((CamelFolderSummaryClass *)camel_local_summary_parent)->message_info_new_from_header(s, h); - if (mi) { - const char *xev; - int doindex = FALSE; - - xev = camel_header_raw_find(&h, "X-Evolution", NULL); - if (xev==NULL || camel_local_summary_decode_x_evolution(cls, xev, mi) == -1) { - /* to indicate it has no xev header */ - mi->info.flags |= CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV; - mi->info.uid = camel_folder_summary_next_uid_string(s); - - /* shortcut, no need to look it up in the index library */ - doindex = TRUE; - } - - if (cls->index - && (doindex - || cls->index_force - || !camel_index_has_name(cls->index, camel_message_info_uid(mi)))) { - d(printf("Am indexing message %s\n", camel_message_info_uid(mi))); - camel_folder_summary_set_index(s, cls->index); - } else { - d(printf("Not indexing message %s\n", camel_message_info_uid(mi))); - camel_folder_summary_set_index(s, NULL); - } - } - - return (CamelMessageInfo *)mi; -} diff --git a/camel/providers/local/camel-local-summary.h b/camel/providers/local/camel-local-summary.h deleted file mode 100644 index cc7dc3eb2d..0000000000 --- a/camel/providers/local/camel-local-summary.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_LOCAL_SUMMARY_H -#define _CAMEL_LOCAL_SUMMARY_H - -#include <camel/camel-folder-summary.h> -#include <camel/camel-folder.h> -#include <camel/camel-exception.h> -#include <camel/camel-index.h> - -#define CAMEL_LOCAL_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_local_summary_get_type (), CamelLocalSummary) -#define CAMEL_LOCAL_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_local_summary_get_type (), CamelLocalSummaryClass) -#define CAMEL_IS_LOCAL_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_local_summary_get_type ()) - -typedef struct _CamelLocalSummary CamelLocalSummary; -typedef struct _CamelLocalSummaryClass CamelLocalSummaryClass; - -/* extra summary flags */ -enum { - CAMEL_MESSAGE_FOLDER_NOXEV = 1<<17, - CAMEL_MESSAGE_FOLDER_XEVCHANGE = 1<<18, - CAMEL_MESSAGE_FOLDER_NOTSEEN = 1<<19, /* have we seen this in processing this loop? */ -}; - -typedef struct _CamelLocalMessageInfo CamelLocalMessageInfo; - -struct _CamelLocalMessageInfo { - CamelMessageInfoBase info; -}; - -struct _CamelLocalSummary { - CamelFolderSummary parent; - - guint32 version; /* file version being loaded */ - - char *folder_path; /* name of matching folder */ - - CamelIndex *index; - unsigned int index_force:1; /* do we force index during creation? */ - unsigned int check_force:1; /* does a check force a full check? */ -}; - -struct _CamelLocalSummaryClass { - CamelFolderSummaryClass parent_class; - - int (*load)(CamelLocalSummary *cls, int forceindex, CamelException *ex); - int (*check)(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); - int (*sync)(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); - CamelMessageInfo *(*add)(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); - - char *(*encode_x_evolution)(CamelLocalSummary *cls, const CamelLocalMessageInfo *info); - int (*decode_x_evolution)(CamelLocalSummary *cls, const char *xev, CamelLocalMessageInfo *info); -}; - -CamelType camel_local_summary_get_type (void); -void camel_local_summary_construct (CamelLocalSummary *new, const char *filename, const char *local_name, CamelIndex *index); - -/* load/check the summary */ -int camel_local_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex); -/* check for new/removed messages */ -int camel_local_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *, CamelException *ex); -/* perform a folder sync or expunge, if needed */ -int camel_local_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *, CamelException *ex); -/* add a new message to the summary */ -CamelMessageInfo *camel_local_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); - -/* force the next check to be a full check/rebuild */ -void camel_local_summary_check_force(CamelLocalSummary *cls); - -/* generate an X-Evolution header line */ -char *camel_local_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelLocalMessageInfo *info); -int camel_local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelLocalMessageInfo *info); - -/* utility functions - write headers to a file with optional X-Evolution header and/or status header */ -int camel_local_summary_write_headers(int fd, struct _camel_header_raw *header, const char *xevline, const char *status, const char *xstatus); - -#endif /* ! _CAMEL_LOCAL_SUMMARY_H */ - diff --git a/camel/providers/local/camel-maildir-folder.c b/camel/providers/local/camel-maildir-folder.c deleted file mode 100644 index b74f6e5ace..0000000000 --- a/camel/providers/local/camel-maildir-folder.c +++ /dev/null @@ -1,279 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999, 2003 Ximian Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <sys/types.h> -#include <dirent.h> -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <fcntl.h> - -#include "camel-maildir-folder.h" -#include "camel-maildir-store.h" -#include "camel-stream-fs.h" -#include "camel-maildir-summary.h" -#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))*/ - -static CamelLocalFolderClass *parent_class = NULL; - -/* Returns the class for a CamelMaildirFolder */ -#define CMAILDIRF_CLASS(so) CAMEL_MAILDIR_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CMAILDIRS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static CamelLocalSummary *maildir_create_summary(CamelLocalFolder *lf, const char *path, const char *folder, CamelIndex *index); - -static void maildir_append_message(CamelFolder * folder, CamelMimeMessage * message, const CamelMessageInfo *info, char **appended_uid, CamelException * ex); -static CamelMimeMessage *maildir_get_message(CamelFolder * folder, const gchar * uid, CamelException * ex); - -static void maildir_finalize(CamelObject * object); - -static int -maildir_folder_getv(CamelObject *object, CamelException *ex, CamelArgGetV *args) -{ - CamelFolder *folder = (CamelFolder *)object; - int i; - guint32 tag; - - for (i=0;i<args->argc;i++) { - CamelArgGet *arg = &args->argv[i]; - - tag = arg->tag; - - switch (tag & CAMEL_ARG_TAG) { - case CAMEL_FOLDER_ARG_NAME: - if (!strcmp(folder->full_name, ".")) - *arg->ca_str = _("Inbox"); - else - *arg->ca_str = folder->name; - break; - default: - continue; - } - - arg->tag = (tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE; - } - - return ((CamelObjectClass *)parent_class)->getv(object, ex, args); -} - -static void camel_maildir_folder_class_init(CamelObjectClass * camel_maildir_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_maildir_folder_class); - CamelLocalFolderClass *lclass = (CamelLocalFolderClass *)camel_maildir_folder_class; - - parent_class = CAMEL_LOCAL_FOLDER_CLASS (camel_type_get_global_classfuncs(camel_local_folder_get_type())); - - /* virtual method definition */ - - /* virtual method overload */ - ((CamelObjectClass *)camel_folder_class)->getv = maildir_folder_getv; - - camel_folder_class->append_message = maildir_append_message; - camel_folder_class->get_message = maildir_get_message; - - lclass->create_summary = maildir_create_summary; -} - -static void maildir_init(gpointer object, gpointer klass) -{ - /*CamelFolder *folder = object; - CamelMaildirFolder *maildir_folder = object;*/ -} - -static void maildir_finalize(CamelObject * object) -{ - /*CamelMaildirFolder *maildir_folder = CAMEL_MAILDIR_FOLDER(object);*/ -} - -CamelType camel_maildir_folder_get_type(void) -{ - static CamelType camel_maildir_folder_type = CAMEL_INVALID_TYPE; - - if (camel_maildir_folder_type == CAMEL_INVALID_TYPE) { - camel_maildir_folder_type = camel_type_register(CAMEL_LOCAL_FOLDER_TYPE, "CamelMaildirFolder", - sizeof(CamelMaildirFolder), - sizeof(CamelMaildirFolderClass), - (CamelObjectClassInitFunc) camel_maildir_folder_class_init, - NULL, - (CamelObjectInitFunc) maildir_init, - (CamelObjectFinalizeFunc) maildir_finalize); - } - - return camel_maildir_folder_type; -} - -CamelFolder * -camel_maildir_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex) -{ - CamelFolder *folder; - - d(printf("Creating maildir folder: %s\n", full_name)); - - folder = (CamelFolder *)camel_object_new(CAMEL_MAILDIR_FOLDER_TYPE); - - if (parent_store->flags & CAMEL_STORE_FILTER_INBOX - && strcmp(full_name, ".") == 0) - folder->folder_flags |= CAMEL_FOLDER_FILTER_RECENT; - - folder = (CamelFolder *)camel_local_folder_construct((CamelLocalFolder *)folder, - parent_store, full_name, flags, ex); - - return folder; -} - -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); -} - -static void -maildir_append_message (CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, char **appended_uid, CamelException *ex) -{ - CamelMaildirFolder *maildir_folder = (CamelMaildirFolder *)folder; - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelStream *output_stream; - CamelMessageInfo *mi; - CamelMaildirMessageInfo *mdi; - char *name, *dest = NULL; - - d(printf("Appending message\n")); - - /* add it to the summary/assign the uid, etc */ - mi = camel_local_summary_add((CamelLocalSummary *)folder->summary, message, info, lf->changes, ex); - if (camel_exception_is_set (ex)) - return; - - mdi = (CamelMaildirMessageInfo *)mi; - - d(printf("Appending message: uid is %s filename is %s\n", camel_message_info_uid(mi), mdi->filename)); - - /* write it out to tmp, use the uid we got from the summary */ - name = g_strdup_printf ("%s/tmp/%s", lf->folder_path, camel_message_info_uid(mi)); - output_stream = camel_stream_fs_new_with_name (name, O_WRONLY|O_CREAT, 0600); - if (output_stream == NULL) - goto fail_write; - - if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *)message, output_stream) == -1 - || camel_stream_close (output_stream) == -1) - goto fail_write; - - /* now move from tmp to cur (bypass new, does it matter?) */ - dest = g_strdup_printf("%s/cur/%s", lf->folder_path, camel_maildir_info_filename (mdi)); - if (rename (name, dest) == 1) - goto fail_write; - - g_free (dest); - g_free (name); - - camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", - ((CamelLocalFolder *)maildir_folder)->changes); - camel_folder_change_info_clear (((CamelLocalFolder *)maildir_folder)->changes); - - if (appended_uid) - *appended_uid = g_strdup(camel_message_info_uid(mi)); - - return; - - fail_write: - - /* remove the summary info so we are not out-of-sync with the mh folder */ - camel_folder_summary_remove_uid (CAMEL_FOLDER_SUMMARY (folder->summary), - camel_message_info_uid (mi)); - - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Maildir append message cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message to maildir folder: %s: %s"), - name, g_strerror (errno)); - - if (output_stream) { - camel_object_unref (CAMEL_OBJECT (output_stream)); - unlink (name); - } - - g_free (name); - g_free (dest); -} - -static CamelMimeMessage *maildir_get_message(CamelFolder * folder, const gchar * uid, CamelException * ex) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelStream *message_stream = NULL; - CamelMimeMessage *message = NULL; - CamelMessageInfo *info; - char *name; - CamelMaildirMessageInfo *mdi; - - d(printf("getting message: %s\n", uid)); - - /* get the message summary info */ - if ((info = camel_folder_summary_uid(folder->summary, uid)) == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s from folder %s\n %s"), - uid, lf->folder_path, _("No such message")); - return NULL; - } - - mdi = (CamelMaildirMessageInfo *)info; - - /* 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); - - if ((message_stream = camel_stream_fs_new_with_name(name, O_RDONLY, 0)) == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get message: %s from folder %s\n %s"), - uid, lf->folder_path, g_strerror(errno)); - g_free(name); - return NULL; - } - - message = camel_mime_message_new(); - if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)message, message_stream) == -1) { - camel_exception_setv(ex, (errno==EINTR)?CAMEL_EXCEPTION_USER_CANCEL:CAMEL_EXCEPTION_SYSTEM, - _("Cannot get message: %s from folder %s\n %s"), - uid, lf->folder_path, _("Invalid message contents")); - g_free(name); - camel_object_unref((CamelObject *)message_stream); - camel_object_unref((CamelObject *)message); - return NULL; - - } - camel_object_unref((CamelObject *)message_stream); - g_free(name); - - return message; -} diff --git a/camel/providers/local/camel-maildir-folder.h b/camel/providers/local/camel-maildir-folder.h deleted file mode 100644 index c495d9b14d..0000000000 --- a/camel/providers/local/camel-maildir-folder.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999 Ximian Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_MAILDIR_FOLDER_H -#define CAMEL_MAILDIR_FOLDER_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus } */ -#include "camel-local-folder.h" - -#define CAMEL_MAILDIR_FOLDER_TYPE (camel_maildir_folder_get_type ()) -#define CAMEL_MAILDIR_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MAILDIR_FOLDER_TYPE, CamelMaildirFolder)) -#define CAMEL_MAILDIR_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MAILDIR_FOLDER_TYPE, CamelMaildirFolderClass)) -#define CAMEL_IS_MAILDIR_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_MAILDIR_FOLDER_TYPE)) - -typedef struct { - CamelLocalFolder parent_object; - -} CamelMaildirFolder; - -typedef struct { - CamelLocalFolderClass parent_class; - - /* Virtual methods */ - -} CamelMaildirFolderClass; - -/* public methods */ -CamelFolder *camel_maildir_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex); - -/* Standard Camel function */ -CamelType camel_maildir_folder_get_type(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* CAMEL_MAILDIR_FOLDER_H */ diff --git a/camel/providers/local/camel-maildir-store.c b/camel/providers/local/camel-maildir-store.c deleted file mode 100644 index eac22d23c6..0000000000 --- a/camel/providers/local/camel-maildir-store.c +++ /dev/null @@ -1,449 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2000 Ximian, Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> - -#include <dirent.h> - -#include "camel-maildir-store.h" -#include "camel-maildir-folder.h" -#include "camel-exception.h" -#include "camel-url.h" -#include "camel-private.h" -#include "camel-maildir-summary.h" -#include "camel-i18n.h" - -#define d(x) - -static CamelLocalStoreClass *parent_class = NULL; - -/* Returns the class for a CamelMaildirStore */ -#define CMAILDIRS_CLASS(so) CAMEL_MAILDIR_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CMAILDIRF_CLASS(so) CAMEL_MAILDIR_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex); -static CamelFolder *get_inbox (CamelStore *store, CamelException *ex); -static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex); -static void maildir_rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex); - -static CamelFolderInfo * get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex); - -static void camel_maildir_store_class_init(CamelObjectClass * camel_maildir_store_class) -{ - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS(camel_maildir_store_class); - /*CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS(camel_maildir_store_class);*/ - - parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_local_store_get_type()); - - /* virtual method overload, use defaults for most */ - camel_store_class->get_folder = get_folder; - camel_store_class->get_inbox = get_inbox; - camel_store_class->delete_folder = delete_folder; - camel_store_class->rename_folder = maildir_rename_folder; - - camel_store_class->get_folder_info = get_folder_info; - camel_store_class->free_folder_info = camel_store_free_folder_info_full; -} - -CamelType camel_maildir_store_get_type(void) -{ - static CamelType camel_maildir_store_type = CAMEL_INVALID_TYPE; - - if (camel_maildir_store_type == CAMEL_INVALID_TYPE) { - camel_maildir_store_type = camel_type_register(CAMEL_LOCAL_STORE_TYPE, "CamelMaildirStore", - sizeof(CamelMaildirStore), - sizeof(CamelMaildirStoreClass), - (CamelObjectClassInitFunc) camel_maildir_store_class_init, - NULL, - NULL, - NULL); - } - - return camel_maildir_store_type; -} - -static CamelFolder * -get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex) -{ - char *name, *tmp, *cur, *new; - struct stat st; - CamelFolder *folder = NULL; - - if (!((CamelStoreClass *)parent_class)->get_folder(store, folder_name, flags, ex)) - return NULL; - - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - tmp = g_strdup_printf("%s/tmp", name); - cur = g_strdup_printf("%s/cur", name); - new = g_strdup_printf("%s/new", name); - - if (stat(name, &st) == -1) { - if (errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get folder `%s': %s"), - folder_name, g_strerror (errno)); - } else if ((flags & CAMEL_STORE_FOLDER_CREATE) == 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot get folder `%s': folder does not exist."), - folder_name); - } else { - if (mkdir(name, 0700) != 0 - || mkdir(tmp, 0700) != 0 - || mkdir(cur, 0700) != 0 - || mkdir(new, 0700) != 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create folder `%s': %s"), - folder_name, g_strerror (errno)); - rmdir(tmp); - rmdir(cur); - rmdir(new); - rmdir(name); - } else { - folder = camel_maildir_folder_new(store, folder_name, flags, ex); - } - } - } else if (!S_ISDIR(st.st_mode) - || stat(tmp, &st) != 0 || !S_ISDIR(st.st_mode) - || stat(cur, &st) != 0 || !S_ISDIR(st.st_mode) - || stat(new, &st) != 0 || !S_ISDIR(st.st_mode)) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get folder `%s': not a maildir directory."), name); - } else if (flags & CAMEL_STORE_FOLDER_EXCL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create folder `%s': folder exists."), - folder_name); - } else { - folder = camel_maildir_folder_new(store, folder_name, flags, ex); - } - - g_free(name); - g_free(tmp); - g_free(cur); - g_free(new); - - return folder; -} - -static CamelFolder * -get_inbox (CamelStore *store, CamelException *ex) -{ - return get_folder (store, ".", 0, ex); -} - -static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex) -{ - char *name, *tmp, *cur, *new; - struct stat st; - - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - - tmp = g_strdup_printf("%s/tmp", name); - cur = g_strdup_printf("%s/cur", name); - new = g_strdup_printf("%s/new", name); - - if (stat(name, &st) == -1 || !S_ISDIR(st.st_mode) - || stat(tmp, &st) == -1 || !S_ISDIR(st.st_mode) - || stat(cur, &st) == -1 || !S_ISDIR(st.st_mode) - || stat(new, &st) == -1 || !S_ISDIR(st.st_mode)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder `%s': %s"), - folder_name, errno ? g_strerror (errno) : - _("not a maildir directory")); - } else { - int err = 0; - - /* remove subdirs first - will fail if not empty */ - if (rmdir(cur) == -1 || rmdir(new) == -1) { - err = errno; - } else { - DIR *dir; - struct dirent *d; - - /* for tmp (only), its contents is irrelevant */ - dir = opendir(tmp); - if (dir) { - while ( (d=readdir(dir)) ) { - char *name = d->d_name, *file; - - if (!strcmp(name, ".") || !strcmp(name, "..")) - continue; - file = g_strdup_printf("%s/%s", tmp, name); - unlink(file); - g_free(file); - } - closedir(dir); - } - if (rmdir(tmp) == -1 || rmdir(name) == -1) - err = errno; - } - - if (err != 0) { - /* easier just to mkdir all (and let them fail), than remember what we got to */ - mkdir(name, 0700); - mkdir(cur, 0700); - mkdir(new, 0700); - mkdir(tmp, 0700); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder `%s': %s"), - folder_name, g_strerror (err)); - } else { - /* and remove metadata */ - ((CamelStoreClass *)parent_class)->delete_folder(store, folder_name, ex); - } - } - - g_free(name); - g_free(tmp); - g_free(cur); - g_free(new); -} - -static void -maildir_rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex) -{ - if (strcmp(old, ".") == 0) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot rename folder: %s: Invalid operation"), _("Inbox")); - return; - } - - ((CamelStoreClass *)parent_class)->rename_folder(store, old, new, ex); -} - -static CamelFolderInfo *camel_folder_info_new(CamelURL *url, const char *full, const char *name) -{ - CamelFolderInfo *fi; - - fi = g_malloc0(sizeof(*fi)); - fi->uri = camel_url_to_string(url, 0); - fi->full_name = g_strdup(full); - if (!strcmp(full, ".")) { - fi->flags |= CAMEL_FOLDER_SYSTEM; - fi->name = g_strdup(_("Inbox")); - } else - fi->name = g_strdup(name); - fi->unread = -1; - fi->total = -1; - - d(printf("Adding maildir info: '%s' '%s' '%s' '%s'\n", fi->path, fi->name, fi->full_name, fi->url)); - - return fi; -} - -static void -fill_fi(CamelStore *store, CamelFolderInfo *fi, guint32 flags) -{ - CamelFolder *folder; - - folder = camel_object_bag_get(store->folders, fi->full_name); - - if (folder == NULL - && (flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0) - folder = camel_store_get_folder(store, fi->full_name, 0, NULL); - - if (folder) { - if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0) - camel_folder_refresh_info(folder, NULL); - fi->unread = camel_folder_get_unread_message_count(folder); - fi->total = camel_folder_get_message_count(folder); - camel_object_unref(folder); - } else { - char *path, *folderpath; - CamelFolderSummary *s; - const char *root; - - /* This should be fast enough not to have to test for INFO_FAST */ - root = camel_local_store_get_toplevel_dir((CamelLocalStore *)store); - path = g_strdup_printf("%s/%s.ev-summary", root, fi->full_name); - folderpath = g_strdup_printf("%s/%s", root, fi->full_name); - s = (CamelFolderSummary *)camel_maildir_summary_new(NULL, path, folderpath, NULL); - if (camel_folder_summary_header_load(s) != -1) { - fi->unread = s->unread_count; - fi->total = s->saved_count; - } - camel_object_unref(s); - g_free(folderpath); - g_free(path); - } -} - -/* used to find out where we've visited already */ -struct _inode { - dev_t dnode; - ino_t inode; -}; - -/* returns number of records found at or below this level */ -static int scan_dir(CamelStore *store, GHashTable *visited, CamelURL *url, const char *path, guint32 flags, CamelFolderInfo *parent, CamelFolderInfo **fip, CamelException *ex) -{ - DIR *dir; - struct dirent *d; - char *name, *tmp, *cur, *new; - const char *base, *root = ((CamelService *)store)->url->path; - CamelFolderInfo *fi = NULL; - struct stat st; - - /* look for folders matching the right structure, recursively */ - name = g_strdup_printf("%s/%s", root, path); - - d(printf("checking dir '%s' part '%s' for maildir content\n", root, path)); - - tmp = g_strdup_printf("%s/tmp", name); - cur = g_strdup_printf("%s/cur", name); - new = g_strdup_printf("%s/new", name); - - base = strrchr(path, '/'); - if (base) - base++; - else - base = path; - - camel_url_set_fragment(url, path); - - fi = camel_folder_info_new(url, path, base); - fill_fi(store, fi, flags); - - if (!(stat(tmp, &st) == 0 && S_ISDIR(st.st_mode) - && stat(cur, &st) == 0 && S_ISDIR(st.st_mode) - && stat(new, &st) == 0 && S_ISDIR(st.st_mode))) - fi->flags |= CAMEL_FOLDER_NOSELECT; - - d(printf("found! uri = %s\n", fi->uri)); - d(printf(" full_name = %s\n name = '%s'\n", fi->full_name, fi->name)); - - fi->parent = parent; - fi->next = *fip; - *fip = fi; - - g_free(tmp); - g_free(cur); - g_free(new); - - /* always look further if asked */ - if (((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) || parent == NULL)) { - int children = 0; - - dir = opendir(name); - if (dir == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not scan folder `%s': %s"), - root, g_strerror (errno)); - g_free(name); - return -1; - } - - while ( (d = readdir(dir)) ) { - if (strcmp(d->d_name, "tmp") == 0 - || strcmp(d->d_name, "cur") == 0 - || strcmp(d->d_name, "new") == 0 - || strcmp(d->d_name, ".") == 0 - || strcmp(d->d_name, "..") == 0) - continue; - - tmp = g_strdup_printf("%s/%s", name, d->d_name); - if (stat(tmp, &st) == 0 && S_ISDIR(st.st_mode)) { - struct _inode in = { st.st_dev, st.st_ino }; - - /* see if we've visited already */ - if (g_hash_table_lookup(visited, &in) == NULL) { - struct _inode *inew = g_malloc(sizeof(*inew)); - - children++; - - *inew = in; - g_hash_table_insert(visited, inew, inew); - new = g_strdup_printf("%s/%s", path, d->d_name); - if (scan_dir(store, visited, url, new, flags, fi, &fi->child, ex) == -1) { - g_free(tmp); - g_free(new); - closedir(dir); - return -1; - } - g_free(new); - } - } - g_free(tmp); - } - closedir(dir); - - if (children) - fi->flags |= CAMEL_FOLDER_CHILDREN; - else - fi->flags |= CAMEL_FOLDER_NOCHILDREN; - } - - g_free(name); - - return 0; -} - -static guint inode_hash(const void *d) -{ - const struct _inode *v = d; - - return v->inode ^ v->dnode; -} - -static gboolean inode_equal(const void *a, const void *b) -{ - const struct _inode *v1 = a, *v2 = b; - - return v1->inode == v2->inode && v1->dnode == v2->dnode; -} - -static void inode_free(void *k, void *v, void *d) -{ - g_free(k); -} - -static CamelFolderInfo * -get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - CamelFolderInfo *fi = NULL; - CamelLocalStore *local_store = (CamelLocalStore *)store; - GHashTable *visited; - CamelURL *url; - - visited = g_hash_table_new(inode_hash, inode_equal); - - url = camel_url_new("maildir:", NULL); - camel_url_set_path(url, ((CamelService *)local_store)->url->path); - - if (scan_dir(store, visited, url, top == NULL || top[0] == 0?".":top, flags, NULL, &fi, ex) == -1 && fi != NULL) { - camel_store_free_folder_info_full(store, fi); - fi = NULL; - } - - camel_url_free(url); - g_hash_table_foreach(visited, inode_free, NULL); - g_hash_table_destroy(visited); - - return fi; -} diff --git a/camel/providers/local/camel-maildir-store.h b/camel/providers/local/camel-maildir-store.h deleted file mode 100644 index f7725bc189..0000000000 --- a/camel/providers/local/camel-maildir-store.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2000 Ximian, Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_MAILDIR_STORE_H -#define CAMEL_MAILDIR_STORE_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus } */ - -#include "camel-local-store.h" - -#define CAMEL_MAILDIR_STORE_TYPE (camel_maildir_store_get_type ()) -#define CAMEL_MAILDIR_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MAILDIR_STORE_TYPE, CamelMaildirStore)) -#define CAMEL_MAILDIR_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MAILDIR_STORE_TYPE, CamelMaildirStoreClass)) -#define CAMEL_IS_MAILDIR_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_MAILDIR_STORE_TYPE)) - -typedef struct { - CamelLocalStore parent_object; - -} CamelMaildirStore; - -typedef struct { - CamelLocalStoreClass parent_class; - -} CamelMaildirStoreClass; - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_maildir_store_get_type(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* CAMEL_MAILDIR_STORE_H */ diff --git a/camel/providers/local/camel-maildir-summary.c b/camel/providers/local/camel-maildir-summary.c deleted file mode 100644 index 95b8bdc8c8..0000000000 --- a/camel/providers/local/camel-maildir-summary.c +++ /dev/null @@ -1,815 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Not Zed <notzed@lostzed.mmc.com.au> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/uio.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> - -#include <sys/types.h> -#include <dirent.h> - -#include <ctype.h> - -#include "camel-maildir-summary.h" -#include <camel/camel-mime-message.h> -#include <camel/camel-operation.h> - -#include "camel-private.h" -#include "libedataserver/e-memory.h" -#include "camel-i18n.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -#define CAMEL_MAILDIR_SUMMARY_VERSION (0x2000) - -static CamelMessageInfo *message_info_load(CamelFolderSummary *s, FILE *in); -static CamelMessageInfo *message_info_new_from_header(CamelFolderSummary *, struct _camel_header_raw *); -static void message_info_free(CamelFolderSummary *, CamelMessageInfo *mi); - -static int maildir_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex); -static int maildir_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static int maildir_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static CamelMessageInfo *maildir_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); - -static char *maildir_summary_next_uid_string(CamelFolderSummary *s); -static int maildir_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelLocalMessageInfo *mi); -static char *maildir_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelLocalMessageInfo *mi); - -static void camel_maildir_summary_class_init (CamelMaildirSummaryClass *class); -static void camel_maildir_summary_init (CamelMaildirSummary *gspaper); -static void camel_maildir_summary_finalise (CamelObject *obj); - -#define _PRIVATE(x) (((CamelMaildirSummary *)(x))->priv) - -struct _CamelMaildirSummaryPrivate { - char *current_file; - char *hostname; - - GHashTable *load_map; -}; - -static CamelLocalSummaryClass *parent_class; - -CamelType -camel_maildir_summary_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_local_summary_get_type (), "CamelMaildirSummary", - sizeof(CamelMaildirSummary), - sizeof(CamelMaildirSummaryClass), - (CamelObjectClassInitFunc)camel_maildir_summary_class_init, - NULL, - (CamelObjectInitFunc)camel_maildir_summary_init, - (CamelObjectFinalizeFunc)camel_maildir_summary_finalise); - } - - return type; -} - -static void -camel_maildir_summary_class_init (CamelMaildirSummaryClass *class) -{ - CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *) class; - CamelLocalSummaryClass *lklass = (CamelLocalSummaryClass *)class; - - parent_class = (CamelLocalSummaryClass *)camel_type_get_global_classfuncs(camel_local_summary_get_type ()); - - /* override methods */ - sklass->message_info_load = message_info_load; - sklass->message_info_new_from_header = message_info_new_from_header; - sklass->message_info_free = message_info_free; - sklass->next_uid_string = maildir_summary_next_uid_string; - - lklass->load = maildir_summary_load; - lklass->check = maildir_summary_check; - lklass->sync = maildir_summary_sync; - lklass->add = maildir_summary_add; - lklass->encode_x_evolution = maildir_summary_encode_x_evolution; - lklass->decode_x_evolution = maildir_summary_decode_x_evolution; -} - -static void -camel_maildir_summary_init (CamelMaildirSummary *o) -{ - struct _CamelFolderSummary *s = (CamelFolderSummary *) o; - char hostname[256]; - - o->priv = g_malloc0(sizeof(*o->priv)); - /* set unique file version */ - s->version += CAMEL_MAILDIR_SUMMARY_VERSION; - - s->message_info_size = sizeof(CamelMaildirMessageInfo); - s->content_info_size = sizeof(CamelMaildirMessageContentInfo); - -#if defined (DOEPOOLV) || defined (DOESTRV) - s->message_info_strings = CAMEL_MAILDIR_INFO_LAST; -#endif - - if (gethostname(hostname, 256) == 0) { - o->priv->hostname = g_strdup(hostname); - } else { - o->priv->hostname = g_strdup("localhost"); - } -} - -static void -camel_maildir_summary_finalise(CamelObject *obj) -{ - CamelMaildirSummary *o = (CamelMaildirSummary *)obj; - - g_free(o->priv->hostname); - g_free(o->priv); -} - -/** - * camel_maildir_summary_new: - * @folder: parent folder. - * @filename: Path to root of this maildir directory (containing new/tmp/cur directories). - * @index: Index if one is reqiured. - * - * Create a new CamelMaildirSummary object. - * - * Return value: A new #CamelMaildirSummary object. - **/ -CamelMaildirSummary *camel_maildir_summary_new(struct _CamelFolder *folder, const char *filename, const char *maildirdir, CamelIndex *index) -{ - CamelMaildirSummary *o = (CamelMaildirSummary *)camel_object_new(camel_maildir_summary_get_type ()); - - ((CamelFolderSummary *)o)->folder = folder; - - camel_local_summary_construct((CamelLocalSummary *)o, filename, maildirdir, index); - return o; -} - -/* the 'standard' maildir flags. should be defined in sorted order. */ -static struct { - char flag; - guint32 flagbit; -} flagbits[] = { - { 'D', CAMEL_MESSAGE_DRAFT }, - { 'F', CAMEL_MESSAGE_FLAGGED }, - /*{ 'P', CAMEL_MESSAGE_FORWARDED },*/ - { 'R', CAMEL_MESSAGE_ANSWERED }, - { 'S', CAMEL_MESSAGE_SEEN }, - { 'T', CAMEL_MESSAGE_DELETED }, -}; - -/* convert the uid + flags into a unique:info maildir format */ -char *camel_maildir_summary_info_to_name(const CamelMaildirMessageInfo *info) -{ - const char *uid; - char *p, *buf; - int i; - - uid = camel_message_info_uid (info); - buf = g_alloca (strlen (uid) + strlen (":2,") + (sizeof (flagbits) / sizeof (flagbits[0])) + 1); - p = buf + sprintf (buf, "%s:2,", uid); - for (i = 0; i < sizeof (flagbits) / sizeof (flagbits[0]); i++) { - if (info->info.info.flags & flagbits[i].flagbit) - *p++ = flagbits[i].flag; - } - *p = 0; - - return g_strdup(buf); -} - -/* returns 0 if the info matches (or there was none), otherwise we changed it */ -int camel_maildir_summary_name_to_info(CamelMaildirMessageInfo *info, const char *name) -{ - char *p, c; - guint32 set = 0; /* what we set */ - /*guint32 all = 0;*/ /* all flags */ - int i; - - p = strstr(name, ":2,"); - if (p) { - p+=3; - while ((c = *p++)) { - /* we could assume that the flags are in order, but its just as easy not to require */ - for (i=0;i<sizeof(flagbits)/sizeof(flagbits[0]);i++) { - if (flagbits[i].flag == c && (info->info.info.flags & flagbits[i].flagbit) == 0) { - set |= flagbits[i].flagbit; - } - /*all |= flagbits[i].flagbit;*/ - } - } - - /* changed? */ - /*if ((info->flags & all) != set) {*/ - if ((info->info.info.flags & set) != set) { - /* ok, they did change, only add the new flags ('merge flags'?) */ - /*info->flags &= all; if we wanted to set only the new flags, which we probably dont */ - info->info.info.flags |= set; - return 1; - } - } - - return 0; -} - -/* for maildir, x-evolution isn't used, so dont try and get anything out of it */ -static int maildir_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelLocalMessageInfo *mi) -{ - return -1; -} - -static char *maildir_summary_encode_x_evolution(CamelLocalSummary *cls, const CamelLocalMessageInfo *mi) -{ - return NULL; -} - -/* FIXME: - both 'new' and 'add' will try and set the filename, this is not ideal ... -*/ -static CamelMessageInfo *maildir_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *changes, CamelException *ex) -{ - CamelMaildirMessageInfo *mi; - - mi = (CamelMaildirMessageInfo *)((CamelLocalSummaryClass *) parent_class)->add(cls, msg, info, changes, ex); - if (mi) { - if (info) { - camel_maildir_info_set_filename(mi, camel_maildir_summary_info_to_name(mi)); - d(printf("Setting filename to %s\n", camel_maildir_info_filename(mi))); - } - } - - return (CamelMessageInfo *)mi; -} - -static CamelMessageInfo *message_info_new_from_header(CamelFolderSummary * s, struct _camel_header_raw *h) -{ - CamelMessageInfo *mi, *info; - CamelMaildirSummary *mds = (CamelMaildirSummary *)s; - CamelMaildirMessageInfo *mdi; - const char *uid; - - mi = ((CamelFolderSummaryClass *) parent_class)->message_info_new_from_header(s, h); - /* assign the uid and new filename */ - if (mi) { - mdi = (CamelMaildirMessageInfo *)mi; - - uid = camel_message_info_uid(mi); - if (uid==NULL || uid[0] == 0) - mdi->info.info.uid = camel_folder_summary_next_uid_string(s); - - /* handle 'duplicates' */ - info = camel_folder_summary_uid(s, uid); - if (info) { - d(printf("already seen uid '%s', just summarising instead\n", uid)); - camel_message_info_free(mi); - mdi = (CamelMaildirMessageInfo *)(mi = info); - } - - /* with maildir we know the real received date, from the filename */ - mdi->info.info.date_received = strtoul(camel_message_info_uid(mi), NULL, 10); - - if (mds->priv->current_file) { -#if 0 - char *p1, *p2, *p3; - unsigned long uid; -#endif - /* if setting from a file, grab the flags from it */ - camel_maildir_info_set_filename(mi, g_strdup(mds->priv->current_file)); - camel_maildir_summary_name_to_info(mdi, mds->priv->current_file); - -#if 0 - /* Actually, I dont think all this effort is worth it at all ... */ - - /* also, see if we can extract the next-id from tne name, and safe-if-fy ourselves against collisions */ - /* we check for something.something_number.something */ - p1 = strchr(mdi->filename, '.'); - if (p1) { - p2 = strchr(p1+1, '.'); - p3 = strchr(p1+1, '_'); - if (p2 && p3 && p3<p2) { - uid = strtoul(p3+1, &p1, 10); - if (p1 == p2 && uid>0) - camel_folder_summary_set_uid(s, uid); - } - } -#endif - } else { - /* if creating a file, set its name from the flags we have */ - camel_maildir_info_set_filename(mdi, camel_maildir_summary_info_to_name(mdi)); - d(printf("Setting filename to %s\n", camel_maildir_info_filename(mi))); - } - } - - return mi; -} - - -static void message_info_free(CamelFolderSummary *s, CamelMessageInfo *mi) -{ -#if !defined (DOEPOOLV) && !defined (DOESTRV) - CamelMaildirMessageInfo *mdi = (CamelMaildirMessageInfo *)mi; - - g_free(mdi->filename); -#endif - ((CamelFolderSummaryClass *) parent_class)->message_info_free(s, mi); -} - - -static char *maildir_summary_next_uid_string(CamelFolderSummary *s) -{ - CamelMaildirSummary *mds = (CamelMaildirSummary *)s; - - d(printf("next uid string called?\n")); - - /* if we have a current file, then use that to get the uid */ - if (mds->priv->current_file) { - char *cln; - - cln = strchr(mds->priv->current_file, ':'); - if (cln) - return g_strndup(mds->priv->current_file, cln-mds->priv->current_file); - else - return g_strdup(mds->priv->current_file); - } else { - /* the first would probably work, but just to be safe, check for collisions */ -#if 0 - return g_strdup_printf("%ld.%d_%u.%s", time(0), getpid(), camel_folder_summary_next_uid(s), mds->priv->hostname); -#else - CamelLocalSummary *cls = (CamelLocalSummary *)s; - char *name = NULL, *uid = NULL; - struct stat st; - int retry = 0; - guint32 nextuid = camel_folder_summary_next_uid(s); - - /* we use time.pid_count.hostname */ - do { - if (retry > 0) { - g_free(name); - g_free(uid); - sleep(2); - } - uid = g_strdup_printf("%ld.%d_%u.%s", time(0), getpid(), nextuid, mds->priv->hostname); - name = g_strdup_printf("%s/tmp/%s", cls->folder_path, uid); - retry++; - } while (stat(name, &st) == 0 && retry<3); - - /* I dont know what we're supposed to do if it fails to find a unique name?? */ - - g_free(name); - return uid; -#endif - } -} - -static CamelMessageInfo * -message_info_load(CamelFolderSummary *s, FILE *in) -{ - CamelMessageInfo *mi; - CamelMaildirSummary *mds = (CamelMaildirSummary *)s; - - mi = ((CamelFolderSummaryClass *) parent_class)->message_info_load(s, in); - if (mi) { - char *name; - - if (mds->priv->load_map - && (name = g_hash_table_lookup(mds->priv->load_map, camel_message_info_uid(mi)))) { - d(printf("Setting filename of %s to %s\n", camel_message_info_uid(mi), name)); - camel_maildir_info_set_filename(mi, g_strdup(name)); - camel_maildir_summary_name_to_info((CamelMaildirMessageInfo *)mi, name); - } - } - - return mi; -} - -static int maildir_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex) -{ - char *cur; - DIR *dir; - struct dirent *d; - CamelMaildirSummary *mds = (CamelMaildirSummary *)cls; - char *uid; - EMemPool *pool; - int ret; - - cur = g_strdup_printf("%s/cur", cls->folder_path); - - d(printf("pre-loading uid <> filename map\n")); - - dir = opendir(cur); - if (dir == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot open maildir directory path: %s: %s"), - cls->folder_path, g_strerror (errno)); - g_free(cur); - return -1; - } - - mds->priv->load_map = g_hash_table_new(g_str_hash, g_str_equal); - pool = e_mempool_new(1024, 512, E_MEMPOOL_ALIGN_BYTE); - - while ( (d = readdir(dir)) ) { - if (d->d_name[0] == '.') - continue; - - /* map the filename -> uid */ - uid = strchr(d->d_name, ':'); - if (uid) { - int len = uid-d->d_name; - uid = e_mempool_alloc(pool, len+1); - memcpy(uid, d->d_name, len); - uid[len] = 0; - g_hash_table_insert(mds->priv->load_map, uid, e_mempool_strdup(pool, d->d_name)); - } else { - uid = e_mempool_strdup(pool, d->d_name); - g_hash_table_insert(mds->priv->load_map, uid, uid); - } - } - closedir(dir); - g_free(cur); - - ret = ((CamelLocalSummaryClass *) parent_class)->load(cls, forceindex, ex); - - g_hash_table_destroy(mds->priv->load_map); - mds->priv->load_map = NULL; - e_mempool_destroy(pool); - - return ret; -} - -static int camel_maildir_summary_add(CamelLocalSummary *cls, const char *name, int forceindex) -{ - CamelMaildirSummary *maildirs = (CamelMaildirSummary *)cls; - char *filename = g_strdup_printf("%s/cur/%s", cls->folder_path, name); - int fd; - CamelMimeParser *mp; - - d(printf("summarising: %s\n", name)); - - fd = open(filename, O_RDONLY); - if (fd == -1) { - g_warning ("Cannot summarise/index: %s: %s", filename, strerror (errno)); - g_free(filename); - return -1; - } - mp = camel_mime_parser_new(); - camel_mime_parser_scan_from(mp, FALSE); - camel_mime_parser_init_with_fd(mp, fd); - if (cls->index && (forceindex || !camel_index_has_name(cls->index, name))) { - d(printf("forcing indexing of message content\n")); - camel_folder_summary_set_index((CamelFolderSummary *)maildirs, cls->index); - } else { - camel_folder_summary_set_index((CamelFolderSummary *)maildirs, NULL); - } - maildirs->priv->current_file = (char *)name; - camel_folder_summary_add_from_parser((CamelFolderSummary *)maildirs, mp); - camel_object_unref((CamelObject *)mp); - maildirs->priv->current_file = NULL; - camel_folder_summary_set_index((CamelFolderSummary *)maildirs, NULL); - g_free(filename); - return 0; -} - -struct _remove_data { - CamelLocalSummary *cls; - CamelFolderChangeInfo *changes; -}; - -static void -remove_summary(char *key, CamelMessageInfo *info, struct _remove_data *rd) -{ - d(printf("removing message %s from summary\n", key)); - if (rd->cls->index) - camel_index_delete_name(rd->cls->index, camel_message_info_uid(info)); - if (rd->changes) - camel_folder_change_info_remove_uid(rd->changes, key); - camel_folder_summary_remove((CamelFolderSummary *)rd->cls, info); - camel_message_info_free(info); -} - -static int -sort_receive_cmp(const void *ap, const void *bp) -{ - const CamelMaildirMessageInfo - *a = *((CamelMaildirMessageInfo **)ap), - *b = *((CamelMaildirMessageInfo **)bp); - - if (a->info.info.date_received < b->info.info.date_received) - return -1; - else if (a->info.info.date_received > b->info.info.date_received) - return 1; - - return 0; -} - -static int -maildir_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changes, CamelException *ex) -{ - DIR *dir; - struct dirent *d; - char *p; - CamelMessageInfo *info; - CamelMaildirMessageInfo *mdi; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - GHashTable *left; - int i, count, total; - int forceindex; - char *new, *cur; - char *uid; - struct _remove_data rd = { cls, changes }; - - new = g_strdup_printf("%s/new", cls->folder_path); - cur = g_strdup_printf("%s/cur", cls->folder_path); - - d(printf("checking summary ...\n")); - - camel_operation_start(NULL, _("Checking folder consistency")); - - /* scan the directory, check for mail files not in the index, or index entries that - no longer exist */ - dir = opendir(cur); - if (dir == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot open maildir directory path: %s: %s"), - cls->folder_path, g_strerror (errno)); - g_free(cur); - g_free(new); - camel_operation_end(NULL); - return -1; - } - - /* keeps track of all uid's that have not been processed */ - left = g_hash_table_new(g_str_hash, g_str_equal); - count = camel_folder_summary_count((CamelFolderSummary *)cls); - forceindex = count == 0; - for (i=0;i<count;i++) { - info = camel_folder_summary_index((CamelFolderSummary *)cls, i); - if (info) { - g_hash_table_insert(left, (char *)camel_message_info_uid(info), info); - } - } - - /* joy, use this to pre-count the total, so we can report progress meaningfully */ - total = 0; - count = 0; - while ( (d = readdir(dir)) ) - total++; - rewinddir(dir); - - while ( (d = readdir(dir)) ) { - int pc = count * 100 / total; - - camel_operation_progress(NULL, pc); - count++; - - /* FIXME: also run stat to check for regular file */ - p = d->d_name; - if (p[0] == '.') - continue; - - /* map the filename -> uid */ - uid = strchr(d->d_name, ':'); - if (uid) - uid = g_strndup(d->d_name, uid-d->d_name); - else - uid = g_strdup(d->d_name); - - info = g_hash_table_lookup(left, uid); - if (info) { - camel_message_info_free(info); - g_hash_table_remove(left, uid); - } - - info = camel_folder_summary_uid((CamelFolderSummary *)cls, uid); - if (info == NULL) { - /* must be a message incorporated by another client, this is not a 'recent' uid */ - if (camel_maildir_summary_add(cls, d->d_name, forceindex) == 0) - if (changes) - camel_folder_change_info_add_uid(changes, uid); - } else { - const char *filename; - - if (cls->index && (!camel_index_has_name(cls->index, uid))) { - /* message_info_new will handle duplicates */ - camel_maildir_summary_add(cls, d->d_name, forceindex); - } - - mdi = (CamelMaildirMessageInfo *)info; - filename = camel_maildir_info_filename(mdi); - /* TODO: only store the extension in the mdi->filename struct, not the whole lot */ - if (filename == NULL || strcmp(filename, d->d_name) != 0) { -#ifdef DOESTRV -#warning "cannot modify the estrv after its been setup, for mt-safe code" - CAMEL_SUMMARY_LOCK(s, summary_lock); - /* need to update the summary hash ref */ - g_hash_table_remove(s->messages_uid, camel_message_info_uid(info)); - info->strings = e_strv_set_ref(info->strings, CAMEL_MAILDIR_INFO_FILENAME, d->d_name); - info->strings = e_strv_pack(info->strings); - g_hash_table_insert(s->messages_uid, (char *)camel_message_info_uid(info), info); - CAMEL_SUMMARY_UNLOCK(s, summary_lock); -#else -# ifdef DOEPOOLV - info->strings = e_poolv_set(info->strings, CAMEL_MAILDIR_INFO_FILENAME, d->d_name, FALSE); -# else - g_free(mdi->filename); - mdi->filename = g_strdup(d->d_name); -# endif -#endif - } - camel_message_info_free(info); - } - g_free(uid); - } - closedir(dir); - g_hash_table_foreach(left, (GHFunc)remove_summary, &rd); - g_hash_table_destroy(left); - - camel_operation_end(NULL); - - camel_operation_start(NULL, _("Checking for new messages")); - - /* now, scan new for new messages, and copy them to cur, and so forth */ - dir = opendir(new); - if (dir != NULL) { - total = 0; - count = 0; - while ( (d = readdir(dir)) ) - total++; - rewinddir(dir); - - while ( (d = readdir(dir)) ) { - char *name, *newname, *destname, *destfilename; - char *src, *dest; - int pc = count * 100 / total; - - camel_operation_progress(NULL, pc); - count++; - - name = d->d_name; - if (name[0] == '.') - continue; - - /* already in summary? shouldn't happen, but just incase ... */ - if ((info = camel_folder_summary_uid((CamelFolderSummary *)cls, name))) { - camel_message_info_free(info); - newname = destname = camel_folder_summary_next_uid_string(s); - } else { - newname = NULL; - destname = name; - } - - /* copy this to the destination folder, use 'standard' semantics for maildir info field */ - src = g_strdup_printf("%s/%s", new, name); - destfilename = g_strdup_printf("%s:2,", destname); - dest = g_strdup_printf("%s/%s", cur, destfilename); - - /* FIXME: This should probably use link/unlink */ - - if (rename(src, dest) == 0) { - camel_maildir_summary_add(cls, destfilename, forceindex); - if (changes) { - camel_folder_change_info_add_uid(changes, destname); - camel_folder_change_info_recent_uid(changes, destname); - } - } else { - /* else? we should probably care about failures, but wont */ - g_warning("Failed to move new maildir message %s to cur %s", src, dest); - } - - /* c strings are painful to work with ... */ - g_free(destfilename); - g_free(newname); - g_free(src); - g_free(dest); - } - camel_operation_end(NULL); - } - closedir(dir); - - g_free(new); - g_free(cur); - - /* sort the summary based on receive time, since the directory order is not useful */ - CAMEL_SUMMARY_LOCK(s, summary_lock); - qsort(s->messages->pdata, s->messages->len, sizeof(CamelMessageInfo *), sort_receive_cmp); - CAMEL_SUMMARY_UNLOCK(s, summary_lock); - - return 0; -} - -/* sync the summary with the ondisk files. */ -static int -maildir_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changes, CamelException *ex) -{ - int count, i; - CamelMessageInfo *info; - CamelMaildirMessageInfo *mdi; -#ifdef DOESTRV - CamelFolderSummary *s = (CamelFolderSummary *)cls; -#endif - char *name; - struct stat st; - - d(printf("summary_sync(expunge=%s)\n", expunge?"true":"false")); - - if (camel_local_summary_check(cls, changes, ex) == -1) - return -1; - - camel_operation_start(NULL, _("Storing folder")); - - count = camel_folder_summary_count((CamelFolderSummary *)cls); - for (i=count-1;i>=0;i--) { - camel_operation_progress(NULL, (count-i)*100/count); - - info = camel_folder_summary_index((CamelFolderSummary *)cls, i); - mdi = (CamelMaildirMessageInfo *)info; - if (mdi && (mdi->info.info.flags & CAMEL_MESSAGE_DELETED) && expunge) { - name = g_strdup_printf("%s/cur/%s", cls->folder_path, camel_maildir_info_filename(mdi)); - d(printf("deleting %s\n", name)); - if (unlink(name) == 0 || errno==ENOENT) { - - /* FIXME: put this in folder_summary::remove()? */ - if (cls->index) - camel_index_delete_name(cls->index, camel_message_info_uid(info)); - - camel_folder_change_info_remove_uid(changes, camel_message_info_uid(info)); - camel_folder_summary_remove((CamelFolderSummary *)cls, info); - } - g_free(name); - } else if (mdi && (mdi->info.info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) { - char *newname = camel_maildir_summary_info_to_name(mdi); - char *dest; - - /* do we care about additional metainfo stored inside the message? */ - /* probably should all go in the filename? */ - - /* have our flags/ i.e. name changed? */ - if (strcmp(newname, camel_maildir_info_filename(mdi))) { - name = g_strdup_printf("%s/cur/%s", cls->folder_path, camel_maildir_info_filename(mdi)); - dest = g_strdup_printf("%s/cur/%s", cls->folder_path, newname); - rename(name, dest); - if (stat(dest, &st) == -1) { - /* we'll assume it didn't work, but dont change anything else */ - g_free(newname); - } else { - /* TODO: If this is made mt-safe, then this code could be a problem, since - the estrv is being modified. - Sigh, this may mean the maildir name has to be cached another way */ -#ifdef DOESTRV -#warning "cannot modify the estrv after its been setup, for mt-safe code" - CAMEL_SUMMARY_LOCK(s, summary_lock); - /* need to update the summary hash ref */ - g_hash_table_remove(s->messages_uid, camel_message_info_uid(info)); - info->strings = e_strv_set_ref_free(info->strings, CAMEL_MAILDIR_INFO_FILENAME, newname); - info->strings = e_strv_pack(info->strings); - g_hash_table_insert(s->messages_uid, (char *)camel_message_info_uid(info), info); - CAMEL_SUMMARY_UNLOCK(s, summary_lock); -#else -# ifdef DOEPOOLV - info->strings = e_poolv_set(info->strings, CAMEL_MAILDIR_INFO_FILENAME, newname, TRUE); -# else - g_free(mdi->filename); - mdi->filename = newname; -# endif -#endif - } - g_free(name); - g_free(dest); - } else { - g_free(newname); - } - - /* strip FOLDER_MESSAGE_FLAGED, etc */ - mdi->info.info.flags &= 0xffff; - } - camel_message_info_free(info); - } - - camel_operation_end(NULL); - - return ((CamelLocalSummaryClass *)parent_class)->sync(cls, expunge, changes, ex); -} - diff --git a/camel/providers/local/camel-maildir-summary.h b/camel/providers/local/camel-maildir-summary.h deleted file mode 100644 index 4ecaf368f5..0000000000 --- a/camel/providers/local/camel-maildir-summary.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Not Zed <notzed@lostzed.mmc.com.au> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_MAILDIR_SUMMARY_H -#define _CAMEL_MAILDIR_SUMMARY_H - -#include "camel-local-summary.h" -#include <camel/camel-folder.h> -#include <camel/camel-exception.h> -#include <camel/camel-index.h> - -#define CAMEL_MAILDIR_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_maildir_summary_get_type (), CamelMaildirSummary) -#define CAMEL_MAILDIR_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_maildir_summary_get_type (), CamelMaildirSummaryClass) -#define CAMEL_IS_MAILDIR_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_maildir_summary_get_type ()) - -typedef struct _CamelMaildirSummary CamelMaildirSummary; -typedef struct _CamelMaildirSummaryClass CamelMaildirSummaryClass; - -typedef struct _CamelMaildirMessageContentInfo { - CamelMessageContentInfo info; -} CamelMaildirMessageContentInfo; - -enum { - CAMEL_MAILDIR_INFO_FILENAME = CAMEL_MESSAGE_INFO_LAST, - CAMEL_MAILDIR_INFO_LAST, -}; - -typedef struct _CamelMaildirMessageInfo { - CamelLocalMessageInfo info; - - char *filename; /* maildir has this annoying status shit on the end of the filename, use this to get the real message id */ -} CamelMaildirMessageInfo; - -struct _CamelMaildirSummary { - CamelLocalSummary parent; - struct _CamelMaildirSummaryPrivate *priv; -}; - -struct _CamelMaildirSummaryClass { - CamelLocalSummaryClass parent_class; - - /* virtual methods */ - - /* signals */ -}; - -CamelType camel_maildir_summary_get_type (void); -CamelMaildirSummary *camel_maildir_summary_new (struct _CamelFolder *folder, const char *filename, const char *maildirdir, CamelIndex *index); - -/* convert some info->flags to/from the messageinfo */ -char *camel_maildir_summary_info_to_name(const CamelMaildirMessageInfo *info); -int camel_maildir_summary_name_to_info(CamelMaildirMessageInfo *info, const char *name); - -/* TODO: could proably use get_string stuff */ -#define camel_maildir_info_filename(x) (((CamelMaildirMessageInfo *)x)->filename) -#define camel_maildir_info_set_filename(x, s) (g_free(((CamelMaildirMessageInfo *)x)->filename),((CamelMaildirMessageInfo *)x)->filename = s) - -#endif /* ! _CAMEL_MAILDIR_SUMMARY_H */ - diff --git a/camel/providers/local/camel-mbox-folder.c b/camel/providers/local/camel-mbox-folder.c deleted file mode 100644 index d213b444fc..0000000000 --- a/camel/providers/local/camel-mbox-folder.c +++ /dev/null @@ -1,482 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * Jeffrey Stedfast <fejj@ximian.com> - * - * Copyright (C) 1999, 2003 Ximian Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <sys/types.h> -#include <dirent.h> -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <fcntl.h> - -#include "camel-mbox-folder.h" -#include "camel-mbox-store.h" -#include "camel-stream-fs.h" -#include "camel-mbox-summary.h" -#include "camel-data-wrapper.h" -#include "camel-mime-message.h" -#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))*/ - -static CamelLocalFolderClass *parent_class = NULL; - -/* Returns the class for a CamelMboxFolder */ -#define CMBOXF_CLASS(so) CAMEL_MBOX_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CMBOXS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static int mbox_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex); -static void mbox_unlock(CamelLocalFolder *lf); - -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); - -static void mbox_finalise(CamelObject * object); - -static void -camel_mbox_folder_class_init(CamelMboxFolderClass * camel_mbox_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_mbox_folder_class); - CamelLocalFolderClass *lclass = (CamelLocalFolderClass *)camel_mbox_folder_class; - - parent_class = (CamelLocalFolderClass *)camel_type_get_global_classfuncs(camel_local_folder_get_type()); - - /* virtual method definition */ - - /* virtual method overload */ - camel_folder_class->append_message = mbox_append_message; - camel_folder_class->get_message = mbox_get_message; - - 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; - lclass->lock = mbox_lock; - lclass->unlock = mbox_unlock; -} - -static void -mbox_init(gpointer object, gpointer klass) -{ - /*CamelFolder *folder = object;*/ - CamelMboxFolder *mbox_folder = object; - - mbox_folder->lockfd = -1; -} - -static void -mbox_finalise(CamelObject * object) -{ - CamelMboxFolder *mbox_folder = (CamelMboxFolder *)object; - - g_assert(mbox_folder->lockfd == -1); -} - -CamelType camel_mbox_folder_get_type(void) -{ - static CamelType camel_mbox_folder_type = CAMEL_INVALID_TYPE; - - if (camel_mbox_folder_type == CAMEL_INVALID_TYPE) { - camel_mbox_folder_type = camel_type_register(CAMEL_LOCAL_FOLDER_TYPE, "CamelMboxFolder", - sizeof(CamelMboxFolder), - sizeof(CamelMboxFolderClass), - (CamelObjectClassInitFunc) camel_mbox_folder_class_init, - NULL, - (CamelObjectInitFunc) mbox_init, - (CamelObjectFinalizeFunc) mbox_finalise); - } - - return camel_mbox_folder_type; -} - -CamelFolder * -camel_mbox_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex) -{ - CamelFolder *folder; - - d(printf("Creating mbox folder: %s in %s\n", full_name, camel_local_store_get_toplevel_dir((CamelLocalStore *)parent_store))); - - folder = (CamelFolder *)camel_object_new(CAMEL_MBOX_FOLDER_TYPE); - folder = (CamelFolder *)camel_local_folder_construct((CamelLocalFolder *)folder, - parent_store, full_name, flags, ex); - - return folder; -} - -char * -camel_mbox_folder_get_full_path (CamelLocalFolder *lf, const char *toplevel_dir, const char *full_name) -{ - const char *inptr = full_name; - int subdirs = 0; - char *path, *p; - - while (*inptr != '\0') { - if (*inptr == '/') - subdirs++; - inptr++; - } - - path = g_malloc (strlen (toplevel_dir) + (inptr - full_name) + (4 * subdirs) + 1); - p = g_stpcpy (path, toplevel_dir); - - inptr = full_name; - while (*inptr != '\0') { - while (*inptr != '/' && *inptr != '\0') - *p++ = *inptr++; - - if (*inptr == '/') { - p = g_stpcpy (p, ".sbd/"); - inptr++; - - /* strip extranaeous '/'s */ - while (*inptr == '/') - inptr++; - } - } - - *p = '\0'; - - return path; -} - -char * -camel_mbox_folder_get_meta_path (CamelLocalFolder *lf, const char *toplevel_dir, const char *full_name, const char *ext) -{ -/*#define USE_HIDDEN_META_FILES*/ -#ifdef USE_HIDDEN_META_FILES - char *name, *slash; - - name = g_alloca (strlen (full_name) + strlen (ext) + 2); - if ((slash = strrchr (full_name, '/'))) - sprintf (name, "%.*s.%s%s", slash - full_name + 1, full_name, slash + 1, ext); - else - sprintf (name, ".%s%s", full_name, ext); - - return camel_mbox_folder_get_full_path (lf, toplevel_dir, name); -#else - char *full_path, *path; - - full_path = camel_mbox_folder_get_full_path (lf, toplevel_dir, full_name); - path = g_strdup_printf ("%s%s", full_path, ext); - g_free (full_path); - - return path; -#endif -} - -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); -} - -static int mbox_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex) -{ - CamelMboxFolder *mf = (CamelMboxFolder *)lf; - - /* make sure we have matching unlocks for locks, camel-local-folder class should enforce this */ - g_assert(mf->lockfd == -1); - - mf->lockfd = open(lf->folder_path, O_RDWR, 0); - if (mf->lockfd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create folder lock on %s: %s"), - lf->folder_path, g_strerror (errno)); - return -1; - } - - if (camel_lock_folder(lf->folder_path, mf->lockfd, type, ex) == -1) { - close(mf->lockfd); - mf->lockfd = -1; - return -1; - } - - return 0; -} - -static void mbox_unlock(CamelLocalFolder *lf) -{ - CamelMboxFolder *mf = (CamelMboxFolder *)lf; - - g_assert(mf->lockfd != -1); - camel_unlock_folder(lf->folder_path, mf->lockfd); - close(mf->lockfd); - mf->lockfd = -1; -} - -static void -mbox_append_message(CamelFolder *folder, CamelMimeMessage * message, const CamelMessageInfo * info, char **appended_uid, CamelException *ex) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelStream *output_stream = NULL, *filter_stream = NULL; - CamelMimeFilter *filter_from = NULL; - CamelMboxSummary *mbs = (CamelMboxSummary *)folder->summary; - CamelMessageInfo *mi; - char *fromline = NULL; - int fd, retval; - struct stat st; -#if 0 - char *xev; -#endif - /* If we can't lock, dont do anything */ - if (camel_local_folder_lock(lf, CAMEL_LOCK_WRITE, ex) == -1) - return; - - d(printf("Appending message\n")); - - /* first, check the summary is correct (updates folder_size too) */ - retval = camel_local_summary_check ((CamelLocalSummary *)folder->summary, lf->changes, ex); - if (retval == -1) - goto fail; - - /* add it to the summary/assign the uid, etc */ - mi = camel_local_summary_add((CamelLocalSummary *)folder->summary, message, info, lf->changes, ex); - if (mi == NULL) - goto fail; - - d(printf("Appending message: uid is %s\n", camel_message_info_uid(mi))); - - output_stream = camel_stream_fs_new_with_name(lf->folder_path, O_WRONLY|O_APPEND, 0600); - if (output_stream == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot open mailbox: %s: %s\n"), - lf->folder_path, g_strerror (errno)); - goto fail; - } - - /* and we need to set the frompos/XEV explicitly */ - ((CamelMboxMessageInfo *)mi)->frompos = mbs->folder_size; -#if 0 - xev = camel_local_summary_encode_x_evolution((CamelLocalSummary *)folder->summary, mi); - if (xev) { - /* the x-ev header should match the 'current' flags, no problem, so store as much */ - camel_medium_set_header((CamelMedium *)message, "X-Evolution", xev); - mi->flags &= ~ CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_FLAGGED; - g_free(xev); - } -#endif - - /* we must write this to the non-filtered stream ... */ - fromline = camel_mime_message_build_mbox_from(message); - if (camel_stream_write(output_stream, fromline, strlen(fromline)) == -1) - goto fail_write; - - /* and write the content to the filtering stream, that translates '\nFrom' into '\n>From' */ - filter_stream = (CamelStream *) camel_stream_filter_new_with_stream(output_stream); - filter_from = (CamelMimeFilter *) camel_mime_filter_from_new(); - camel_stream_filter_add((CamelStreamFilter *) filter_stream, filter_from); - if (camel_data_wrapper_write_to_stream((CamelDataWrapper *)message, filter_stream) == -1 - || camel_stream_write(filter_stream, "\n", 1) == -1 - || camel_stream_close(filter_stream) == -1) - goto fail_write; - - /* filter stream ref's the output stream itself, so we need to unref it too */ - camel_object_unref((CamelObject *)filter_from); - camel_object_unref((CamelObject *)filter_stream); - camel_object_unref((CamelObject *)output_stream); - g_free(fromline); - - /* now we 'fudge' the summary to tell it its uptodate, because its idea of uptodate has just changed */ - /* the stat really shouldn't fail, we just wrote to it */ - if (stat(lf->folder_path, &st) == 0) { - mbs->folder_size = st.st_size; - ((CamelFolderSummary *)mbs)->time = st.st_mtime; - } - - /* unlock as soon as we can */ - camel_local_folder_unlock(lf); - - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } - - if (appended_uid) - *appended_uid = g_strdup(camel_message_info_uid(mi)); - - return; - -fail_write: - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Mail append cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message to mbox file: %s: %s"), - lf->folder_path, g_strerror (errno)); - - if (filter_stream) - camel_object_unref(CAMEL_OBJECT(filter_stream)); - - if (output_stream) - camel_object_unref(CAMEL_OBJECT(output_stream)); - - if (filter_from) - camel_object_unref(CAMEL_OBJECT(filter_from)); - - g_free(fromline); - - /* reset the file to original size */ - fd = open(lf->folder_path, O_WRONLY, 0600); - if (fd != -1) { - ftruncate(fd, mbs->folder_size); - close(fd); - } - - /* remove the summary info so we are not out-of-sync with the mbox */ - camel_folder_summary_remove_uid (CAMEL_FOLDER_SUMMARY (mbs), camel_message_info_uid (mi)); - - /* and tell the summary its uptodate */ - if (stat(lf->folder_path, &st) == 0) { - mbs->folder_size = st.st_size; - ((CamelFolderSummary *)mbs)->time = st.st_mtime; - } - -fail: - /* make sure we unlock the folder - before we start triggering events into appland */ - camel_local_folder_unlock(lf); - - /* cascade the changes through, anyway, if there are any outstanding */ - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } -} - -static CamelMimeMessage * -mbox_get_message(CamelFolder *folder, const gchar * uid, CamelException *ex) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelMimeMessage *message = NULL; - CamelMboxMessageInfo *info; - CamelMimeParser *parser = NULL; - int fd, retval; - int retried = FALSE; - off_t frompos; - - d(printf("Getting message %s\n", uid)); - - /* lock the folder first, burn if we can't, need write lock for summary check */ - if (camel_local_folder_lock(lf, CAMEL_LOCK_WRITE, ex) == -1) - return NULL; - - /* check for new messages always */ - if (camel_local_summary_check((CamelLocalSummary *)folder->summary, lf->changes, ex) == -1) { - camel_local_folder_unlock(lf); - return NULL; - } - -retry: - /* get the message summary info */ - info = (CamelMboxMessageInfo *) camel_folder_summary_uid(folder->summary, uid); - - if (info == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s from folder %s\n %s"), - uid, lf->folder_path, _("No such message")); - goto fail; - } - - /* no frompos, its an error in the library (and we can't do anything with it) */ - g_assert(info->frompos != -1); - - frompos = info->frompos; - camel_message_info_free((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 - with no stream). This means we dont have to lock the mbox for the life of the message, but only - while it is being created. */ - - fd = open(lf->folder_path, O_RDONLY); - if (fd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get message: %s from folder %s\n %s"), - uid, lf->folder_path, g_strerror (errno)); - goto fail; - } - - /* we use a parser to verify the message is correct, and in the correct position */ - parser = camel_mime_parser_new(); - camel_mime_parser_init_with_fd(parser, fd); - camel_mime_parser_scan_from(parser, TRUE); - - camel_mime_parser_seek(parser, frompos, SEEK_SET); - if (camel_mime_parser_step(parser, NULL, NULL) != CAMEL_MIME_PARSER_STATE_FROM - || camel_mime_parser_tell_start_from(parser) != frompos) { - - g_warning("Summary doesn't match the folder contents! eek!\n" - " expecting offset %ld got %ld, state = %d", (long int)frompos, - (long int)camel_mime_parser_tell_start_from(parser), - camel_mime_parser_state(parser)); - - camel_object_unref((CamelObject *)parser); - parser = NULL; - - if (!retried) { - retried = TRUE; - camel_local_summary_check_force((CamelLocalSummary *)folder->summary); - retval = camel_local_summary_check((CamelLocalSummary *)folder->summary, lf->changes, ex); - if (retval != -1) - goto retry; - } - - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID, - _("Cannot get message: %s from folder %s\n %s"), uid, lf->folder_path, - _("The folder appears to be irrecoverably corrupted.")); - goto fail; - } - - message = camel_mime_message_new(); - if (camel_mime_part_construct_from_parser((CamelMimePart *)message, parser) == -1) { - camel_exception_setv(ex, errno==EINTR?CAMEL_EXCEPTION_USER_CANCEL:CAMEL_EXCEPTION_SYSTEM, - _("Cannot get message: %s from folder %s\n %s"), uid, lf->folder_path, - _("Message construction failed.")); - camel_object_unref((CamelObject *)message); - message = NULL; - goto fail; - } - - camel_medium_remove_header((CamelMedium *)message, "X-Evolution"); -fail: - /* and unlock now we're finished with it */ - camel_local_folder_unlock(lf); - - if (parser) - camel_object_unref((CamelObject *)parser); - - /* use the opportunity to notify of changes (particularly if we had a rebuild) */ - if (camel_folder_change_info_changed(lf->changes)) { - camel_object_trigger_event((CamelObject *)folder, "folder_changed", lf->changes); - camel_folder_change_info_clear(lf->changes); - } - - return message; -} diff --git a/camel/providers/local/camel-mbox-folder.h b/camel/providers/local/camel-mbox-folder.h deleted file mode 100644 index fa76001849..0000000000 --- a/camel/providers/local/camel-mbox-folder.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999 Ximian . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_MBOX_FOLDER_H -#define CAMEL_MBOX_FOLDER_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-local-folder.h" -#include "camel-mbox-summary.h" - -#define CAMEL_MBOX_FOLDER_TYPE (camel_mbox_folder_get_type ()) -#define CAMEL_MBOX_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MBOX_FOLDER_TYPE, CamelMboxFolder)) -#define CAMEL_MBOX_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MBOX_FOLDER_TYPE, CamelMboxFolderClass)) -#define CAMEL_IS_MBOX_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_MBOX_FOLDER_TYPE)) - -typedef struct { - CamelLocalFolder parent_object; - - int lockfd; /* for when we have a lock on the folder */ -} CamelMboxFolder; - -typedef struct { - CamelLocalFolderClass parent_class; - - /* Virtual methods */ - -} CamelMboxFolderClass; - -/* public methods */ -/* flags are taken from CAMEL_STORE_FOLDER_* flags */ -CamelFolder *camel_mbox_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex); - -/* Standard Camel function */ -CamelType camel_mbox_folder_get_type(void); - -/* utilities */ -char *camel_mbox_folder_get_full_path (CamelLocalFolder *lf, const char *toplevel_dir, const char *full_name); -char *camel_mbox_folder_get_meta_path (CamelLocalFolder *lf, const char *toplevel_dir, const char *full_name, const char *ext); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_MBOX_FOLDER_H */ diff --git a/camel/providers/local/camel-mbox-store.c b/camel/providers/local/camel-mbox-store.c deleted file mode 100644 index a9e581cdd7..0000000000 --- a/camel/providers/local/camel-mbox-store.c +++ /dev/null @@ -1,838 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright(C) 2000 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <dirent.h> -#include <fcntl.h> -#include <errno.h> - -#include "camel-mbox-store.h" -#include "camel-mbox-folder.h" -#include "camel-file-utils.h" -#include "camel-text-index.h" -#include "camel-exception.h" -#include "camel-url.h" -#include "camel-i18n.h" - -#define d(x) - -static CamelLocalStoreClass *parent_class = NULL; - -/* Returns the class for a CamelMboxStore */ -#define CMBOXS_CLASS(so) CAMEL_MBOX_STORE_CLASS(CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS(CAMEL_OBJECT_GET_CLASS(so)) -#define CMBOXF_CLASS(so) CAMEL_MBOX_FOLDER_CLASS(CAMEL_OBJECT_GET_CLASS(so)) - -static CamelFolder *get_folder(CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex); -static void delete_folder(CamelStore *store, const char *folder_name, CamelException *ex); -static void rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex); -static CamelFolderInfo *create_folder(CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex); -static CamelFolderInfo *get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelException *ex); - -static void -camel_mbox_store_class_init(CamelMboxStoreClass *camel_mbox_store_class) -{ - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS(camel_mbox_store_class); - - parent_class =(CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_local_store_get_type()); - - /* virtual method overload */ - camel_store_class->get_folder = get_folder; - camel_store_class->delete_folder = delete_folder; - camel_store_class->rename_folder = rename_folder; - camel_store_class->create_folder = create_folder; - - camel_store_class->get_folder_info = get_folder_info; - camel_store_class->free_folder_info = camel_store_free_folder_info_full; -} - -CamelType -camel_mbox_store_get_type(void) -{ - static CamelType camel_mbox_store_type = CAMEL_INVALID_TYPE; - - if (camel_mbox_store_type == CAMEL_INVALID_TYPE) { - camel_mbox_store_type = camel_type_register(CAMEL_LOCAL_STORE_TYPE, "CamelMboxStore", - sizeof(CamelMboxStore), - sizeof(CamelMboxStoreClass), - (CamelObjectClassInitFunc) camel_mbox_store_class_init, - NULL, - NULL, - NULL); - } - - return camel_mbox_store_type; -} - -static char * -mbox_folder_name_to_path(CamelStore *store, const char *folder_name) -{ - const char *toplevel_dir = CAMEL_LOCAL_STORE(store)->toplevel_dir; - - return camel_mbox_folder_get_full_path(NULL, toplevel_dir, folder_name); -} - -static char * -mbox_folder_name_to_meta_path(CamelStore *store, const char *folder_name, const char *ext) -{ - const char *toplevel_dir = CAMEL_LOCAL_STORE(store)->toplevel_dir; - - return camel_mbox_folder_get_meta_path(NULL, toplevel_dir, folder_name, ext); -} - -static char *extensions[] = { - ".msf", ".ev-summary", ".ibex.index", ".ibex.index.data", ".cmeta", ".lock" -}; - -static gboolean -ignore_file(const char *filename, gboolean sbd) -{ - int flen, len, i; - - /* TODO: Should probably just be 1 regex */ - flen = strlen(filename); - if (flen > 0 && filename[flen-1] == '~') - return TRUE; - - for (i = 0; i <(sizeof(extensions) / sizeof(extensions[0])); i++) { - len = strlen(extensions[i]); - if (len < flen && !strcmp(filename + flen - len, extensions[i])) - return TRUE; - } - - if (sbd && flen > 4 && !strcmp(filename + flen - 4, ".sbd")) - return TRUE; - - return FALSE; -} - -static CamelFolder * -get_folder(CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex) -{ - struct stat st; - char *name; - - if (!((CamelStoreClass *) parent_class)->get_folder(store, folder_name, flags, ex)) - return NULL; - - name = mbox_folder_name_to_path(store, folder_name); - - if (stat(name, &st) == -1) { - const char *basename; - char *dirname; - int fd; - - if (errno != ENOENT) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get folder `%s': %s"), - folder_name, g_strerror (errno)); - g_free(name); - return NULL; - } - - if ((flags & CAMEL_STORE_FOLDER_CREATE) == 0) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot get folder `%s': folder does not exist."), - folder_name); - g_free(name); - return NULL; - } - - /* sanity check the folder name */ - if (!(basename = strrchr (folder_name, '/'))) - basename = folder_name; - else - basename++; - - if (basename[0] == '.' || ignore_file (basename, TRUE)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create a folder by this name.")); - g_free (name); - return NULL; - } - - dirname = g_path_get_dirname(name); - if (camel_mkdir(dirname, 0777) == -1 && errno != EEXIST) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create folder `%s': %s"), - folder_name, g_strerror (errno)); - g_free(dirname); - g_free(name); - return NULL; - } - - g_free(dirname); - - fd = open(name, O_WRONLY | O_CREAT | O_APPEND, 0666); - if (fd == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create folder `%s': %s"), - folder_name, g_strerror (errno)); - g_free(name); - return NULL; - } - - g_free(name); - close(fd); - } else if (!S_ISREG(st.st_mode)) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get folder `%s': not a regular file."), - folder_name); - g_free(name); - return NULL; - } else if (flags & CAMEL_STORE_FOLDER_EXCL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create folder `%s': folder exists."), - folder_name); - g_free (name); - return NULL; - } else - g_free(name); - - return camel_mbox_folder_new(store, folder_name, flags, ex); -} - -static void -delete_folder(CamelStore *store, const char *folder_name, CamelException *ex) -{ - CamelFolderInfo *fi; - CamelException lex; - CamelFolder *lf; - char *name, *path; - struct stat st; - - name = mbox_folder_name_to_path(store, folder_name); - path = g_strdup_printf("%s.sbd", name); - - if (rmdir(path) == -1 && errno != ENOENT) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder `%s':\n%s"), - folder_name, g_strerror(errno)); - g_free(path); - g_free(name); - return; - } - - g_free(path); - - if (stat(name, &st) == -1) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder `%s':\n%s"), - folder_name, g_strerror(errno)); - g_free(name); - return; - } - - if (!S_ISREG(st.st_mode)) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("`%s' is not a regular file."), name); - g_free(name); - return; - } - - if (st.st_size != 0) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_NON_EMPTY, - _("Folder `%s' is not empty. Not deleted."), - folder_name); - g_free(name); - return; - } - - if (unlink(name) == -1 && errno != ENOENT) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder `%s':\n%s"), - name, g_strerror(errno)); - g_free(name); - return; - } - - /* FIXME: we have to do our own meta cleanup here rather than - * calling our parent class' delete_folder() method since our - * naming convention is different. Need to find a way for - * CamelLocalStore to be able to construct the folder & meta - * paths itself */ - path = mbox_folder_name_to_meta_path(store, folder_name, ".ev-summary"); - if (unlink(path) == -1 && errno != ENOENT) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder summary file `%s': %s"), - path, g_strerror(errno)); - g_free(path); - g_free(name); - return; - } - - g_free(path); - - path = mbox_folder_name_to_meta_path(store, folder_name, ".ibex"); - if (camel_text_index_remove(path) == -1 && errno != ENOENT) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder index file `%s': %s"), - path, g_strerror(errno)); - g_free(path); - g_free(name); - return; - } - - g_free(path); - - path = NULL; - camel_exception_init(&lex); - if ((lf = camel_store_get_folder(store, folder_name, 0, &lex))) { - camel_object_get(lf, NULL, CAMEL_OBJECT_STATE_FILE, &path, NULL); - camel_object_set(lf, NULL, CAMEL_OBJECT_STATE_FILE, NULL, NULL); - camel_object_unref(lf); - } else { - camel_exception_clear(&lex); - } - - if (path == NULL) - path = mbox_folder_name_to_meta_path(store, folder_name, ".cmeta"); - - if (unlink(path) == -1 && errno != ENOENT) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder meta file `%s': %s"), - path, g_strerror(errno)); - - g_free(path); - g_free(name); - return; - } - - g_free(path); - g_free(name); - - fi = g_new0(CamelFolderInfo, 1); - fi->full_name = g_strdup(folder_name); - fi->name = g_path_get_basename(folder_name); - fi->uri = g_strdup_printf("mbox:%s#%s",((CamelService *) store)->url->path, folder_name); - fi->unread = -1; - - camel_object_trigger_event(store, "folder_deleted", fi); - - camel_folder_info_free(fi); -} - -static CamelFolderInfo * -create_folder(CamelStore *store, const char *parent_name, const char *folder_name, CamelException *ex) -{ - /* FIXME: this is almost an exact copy of CamelLocalStore::create_folder() except that we use - * different path schemes... need to find a way to share parent's code? */ - const char *toplevel_dir =((CamelLocalStore *) store)->toplevel_dir; - CamelFolderInfo *info = NULL; - char *path, *name, *dir; - CamelFolder *folder; - struct stat st; - - if (toplevel_dir[0] != '/') { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Store root %s is not an absolute path"), toplevel_dir); - return NULL; - } - - if (folder_name[0] == '.' || ignore_file(folder_name, TRUE)) { - camel_exception_set(ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create a folder by this name.")); - return NULL; - } - - if (parent_name && *parent_name) - name = g_strdup_printf("%s/%s", parent_name, folder_name); - else - name = g_strdup(folder_name); - - path = mbox_folder_name_to_path(store, name); - - dir = g_path_get_dirname(path); - if (camel_mkdir(dir, 0777) == -1 && errno != EEXIST) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create directory `%s': %s."), - dir, g_strerror(errno)); - - g_free(path); - g_free(name); - g_free(dir); - - return NULL; - } - - g_free(dir); - - if (stat(path, &st) == 0 || errno != ENOENT) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot create folder: %s: %s"), - path, errno ? g_strerror(errno) : - _("Folder already exists")); - - g_free(path); - g_free(name); - - return NULL; - } - - g_free(path); - - folder =((CamelStoreClass *)((CamelObject *) store)->klass)->get_folder(store, name, CAMEL_STORE_FOLDER_CREATE, ex); - if (folder) { - camel_object_unref(folder); - info =((CamelStoreClass *)((CamelObject *) store)->klass)->get_folder_info(store, name, 0, ex); - } - - g_free(name); - - return info; -} - -static int -xrename(CamelStore *store, const char *old_name, const char *new_name, const char *ext, gboolean missingok) -{ - const char *toplevel_dir =((CamelLocalStore *) store)->toplevel_dir; - char *oldpath, *newpath; - struct stat st; - int ret = -1; - int err = 0; - - if (ext != NULL) { - oldpath = camel_mbox_folder_get_meta_path(NULL, toplevel_dir, old_name, ext); - newpath = camel_mbox_folder_get_meta_path(NULL, toplevel_dir, new_name, ext); - } else { - oldpath = camel_mbox_folder_get_full_path(NULL, toplevel_dir, old_name); - newpath = camel_mbox_folder_get_full_path(NULL, toplevel_dir, new_name); - } - - if (stat(oldpath, &st) == -1) { - if (missingok && errno == ENOENT) { - ret = 0; - } else { - err = errno; - ret = -1; - } - } else if (S_ISDIR(st.st_mode)) { - /* use rename for dirs */ - if (rename(oldpath, newpath) == 0 || stat(newpath, &st) == 0) { - ret = 0; - } else { - err = errno; - ret = -1; - } - } else if (link(oldpath, newpath) == 0 /* and link for files */ - ||(stat(newpath, &st) == 0 && st.st_nlink == 2)) { - if (unlink(oldpath) == 0) { - ret = 0; - } else { - err = errno; - unlink(newpath); - ret = -1; - } - } else { - err = errno; - ret = -1; - } - - g_free(oldpath); - g_free(newpath); - - return ret; -} - -static void -rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex) -{ - CamelLocalFolder *folder = NULL; - char *oldibex, *newibex, *newdir; - int errnosav; - - if (new[0] == '.' || ignore_file(new, TRUE)) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("The new folder name is illegal.")); - return; - } - - /* try to rollback failures, has obvious races */ - - oldibex = mbox_folder_name_to_meta_path(store, old, ".ibex"); - newibex = mbox_folder_name_to_meta_path(store, new, ".ibex"); - - newdir = g_path_get_dirname(newibex); - if (camel_mkdir(newdir, 0777) == -1) { - if (errno != EEXIST) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not rename `%s': `%s': %s"), - old, new, g_strerror(errno)); - g_free(oldibex); - g_free(newibex); - g_free(newdir); - - return; - } - - g_free(newdir); - newdir = NULL; - } - - folder = camel_object_bag_get(store->folders, old); - if (folder && folder->index) { - if (camel_index_rename(folder->index, newibex) == -1 && errno != ENOENT) { - errnosav = errno; - goto ibex_failed; - } - } else { - /* TODO: camel_text_index_rename should find out if we have an active index itself? */ - if (camel_text_index_rename(oldibex, newibex) == -1 && errno != ENOENT) { - errnosav = errno; - goto ibex_failed; - } - } - - if (xrename(store, old, new, ".ev-summary", TRUE) == -1) { - errnosav = errno; - goto summary_failed; - } - - if (xrename(store, old, new, ".cmeta", TRUE) == -1) { - errnosav = errno; - goto cmeta_failed; - } - - if (xrename(store, old, new, ".sbd", TRUE) == -1) { - errnosav = errno; - goto subdir_failed; - } - - if (xrename(store, old, new, NULL, FALSE) == -1) { - errnosav = errno; - goto base_failed; - } - - g_free(oldibex); - g_free(newibex); - - if (folder) - camel_object_unref(folder); - - return; - -base_failed: - xrename(store, new, old, ".sbd", TRUE); -subdir_failed: - xrename(store, new, old, ".cmeta", TRUE); -cmeta_failed: - xrename(store, new, old, ".ev-summary", TRUE); -summary_failed: - if (folder) { - if (folder->index) - camel_index_rename(folder->index, oldibex); - } else - camel_text_index_rename(newibex, oldibex); -ibex_failed: - if (newdir) { - /* newdir is only non-NULL if we needed to mkdir */ - rmdir(newdir); - g_free(newdir); - } - - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not rename '%s' to %s: %s"), - old, new, g_strerror(errnosav)); - - g_free(newibex); - g_free(oldibex); - - if (folder) - camel_object_unref(folder); -} - -/* used to find out where we've visited already */ -struct _inode { - dev_t dnode; - ino_t inode; -}; - -static guint -inode_hash(const void *d) -{ - const struct _inode *v = d; - - return v->inode ^ v->dnode; -} - -static gboolean -inode_equal(const void *a, const void *b) -{ - const struct _inode *v1 = a, *v2 = b; - - return v1->inode == v2->inode && v1->dnode == v2->dnode; -} - -static void -inode_free(void *k, void *v, void *d) -{ - g_free(k); -} - -/* NB: duplicated in maildir store */ -static void -fill_fi(CamelStore *store, CamelFolderInfo *fi, guint32 flags) -{ - CamelFolder *folder; - - fi->unread = -1; - fi->total = -1; - folder = camel_object_bag_get(store->folders, fi->full_name); - if (folder) { - if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0) - camel_folder_refresh_info(folder, NULL); - fi->unread = camel_folder_get_unread_message_count(folder); - fi->total = camel_folder_get_message_count(folder); - camel_object_unref(folder); - } else { - char *path, *folderpath; - CamelMboxSummary *mbs; - const char *root; - - /* This should be fast enough not to have to test for INFO_FAST */ - root = camel_local_store_get_toplevel_dir((CamelLocalStore *)store); - 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); - if (camel_folder_summary_header_load((CamelFolderSummary *)mbs) != -1) { - fi->unread = ((CamelFolderSummary *)mbs)->unread_count; - fi->total = ((CamelFolderSummary *)mbs)->saved_count; - } - - camel_object_unref(mbs); - g_free(folderpath); - g_free(path); - } -} - -static CamelFolderInfo * -scan_dir(CamelStore *store, CamelURL *url, GHashTable *visited, CamelFolderInfo *parent, const char *root, - const char *name, guint32 flags, CamelException *ex) -{ - CamelFolderInfo *folders, *tail, *fi; - GHashTable *folder_hash; - struct dirent *dent; - DIR *dir; - - tail = folders = NULL; - - if (!(dir = opendir(root))) - return NULL; - - folder_hash = g_hash_table_new(g_str_hash, g_str_equal); - - /* FIXME: it would be better if we queue'd up the recursive - * scans till the end so that we can limit the number of - * directory descriptors open at any given time... */ - - while ((dent = readdir(dir))) { - char *short_name, *full_name, *path, *ext; - struct stat st; - - if (dent->d_name[0] == '.') - continue; - - if (ignore_file(dent->d_name, FALSE)) - continue; - - path = g_strdup_printf("%s/%s", root, dent->d_name); - if (stat(path, &st) == -1) { - g_free(path); - continue; - } - - if (S_ISDIR(st.st_mode)) { - struct _inode in = { st.st_dev, st.st_ino }; - - if (g_hash_table_lookup(visited, &in)) { - g_free(path); - continue; - } - } - - short_name = g_strdup(dent->d_name); - if ((ext = strrchr(short_name, '.')) && !strcmp(ext, ".sbd")) - *ext = '\0'; - - if (name != NULL) - full_name = g_strdup_printf("%s/%s", name, short_name); - else - full_name = g_strdup(short_name); - - if ((fi = g_hash_table_lookup(folder_hash, short_name)) != NULL) { - g_free(short_name); - g_free(full_name); - - if (S_ISDIR(st.st_mode)) { - fi->flags =(fi->flags & ~CAMEL_FOLDER_NOCHILDREN) | CAMEL_FOLDER_CHILDREN; - } else { - fi->flags &= ~CAMEL_FOLDER_NOSELECT; - } - } else { - fi = g_new0(CamelFolderInfo, 1); - fi->parent = parent; - - camel_url_set_fragment (url, full_name); - - fi->uri = camel_url_to_string (url, 0); - fi->name = short_name; - fi->full_name = full_name; - fi->unread = -1; - fi->total = -1; - - if (S_ISDIR(st.st_mode)) - fi->flags = CAMEL_FOLDER_NOSELECT; - else - fi->flags = CAMEL_FOLDER_NOCHILDREN; - - if (tail == NULL) - folders = fi; - else - tail->next = fi; - - tail = fi; - - g_hash_table_insert(folder_hash, fi->name, fi); - } - - if (!S_ISDIR(st.st_mode)) { - fill_fi(store, fi, flags); - } else if ((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE)) { - struct _inode in = { st.st_dev, st.st_ino }; - - if (g_hash_table_lookup(visited, &in) == NULL) { - struct _inode *inew = g_new(struct _inode, 1); - - *inew = in; - - g_hash_table_insert(visited, inew, inew); - - if ((fi->child = scan_dir (store, url, visited, fi, path, fi->full_name, flags, ex))) - fi->flags |= CAMEL_FOLDER_CHILDREN; - else - fi->flags =(fi->flags & ~CAMEL_FOLDER_CHILDREN) | CAMEL_FOLDER_NOCHILDREN; - } - } - - g_free(path); - } - - closedir(dir); - - g_hash_table_destroy(folder_hash); - - return folders; -} - -static CamelFolderInfo * -get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - GHashTable *visited; - struct _inode *inode; - char *path, *subdir; - CamelFolderInfo *fi; - const char *base; - struct stat st; - CamelURL *url; - - top = top ? top : ""; - path = mbox_folder_name_to_path(store, top); - - if (*top == '\0') { - /* requesting root dir scan */ - if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) { - g_free(path); - return NULL; - } - - visited = g_hash_table_new(inode_hash, inode_equal); - - inode = g_malloc0(sizeof(*inode)); - inode->dnode = st.st_dev; - inode->inode = st.st_ino; - - g_hash_table_insert(visited, inode, inode); - - url = camel_url_copy (((CamelService *) store)->url); - fi = scan_dir (store, url, visited, NULL, path, NULL, flags, ex); - g_hash_table_foreach(visited, inode_free, NULL); - g_hash_table_destroy(visited); - camel_url_free (url); - g_free (path); - - return fi; - } - - /* requesting scan of specific folder */ - if (stat(path, &st) == -1 || !S_ISREG(st.st_mode)) { - g_free(path); - return NULL; - } - - visited = g_hash_table_new(inode_hash, inode_equal); - - if (!(base = strrchr(top, '/'))) - base = top; - else - base++; - - url = camel_url_copy (((CamelService *) store)->url); - camel_url_set_fragment (url, top); - - fi = g_new0(CamelFolderInfo, 1); - fi->parent = NULL; - fi->uri = camel_url_to_string (url, 0); - fi->name = g_strdup(base); - fi->full_name = g_strdup(top); - fi->unread = -1; - fi->total = -1; - - subdir = g_strdup_printf("%s.sbd", path); - if (stat(subdir, &st) == 0) { - if (S_ISDIR(st.st_mode)) - fi->child = scan_dir (store, url, visited, fi, subdir, top, flags, ex); - else - fill_fi(store, fi, flags); - } else - fill_fi(store, fi, flags); - - camel_url_free (url); - - if (fi->child) - fi->flags |= CAMEL_FOLDER_CHILDREN; - else - fi->flags |= CAMEL_FOLDER_NOCHILDREN; - - g_free(subdir); - - g_hash_table_foreach(visited, inode_free, NULL); - g_hash_table_destroy(visited); - g_free(path); - - return fi; -} diff --git a/camel/providers/local/camel-mbox-store.h b/camel/providers/local/camel-mbox-store.h deleted file mode 100644 index 5b6fbdd926..0000000000 --- a/camel/providers/local/camel-mbox-store.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2000 Ximian, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_MBOX_STORE_H -#define CAMEL_MBOX_STORE_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-local-store.h" - -#define CAMEL_MBOX_STORE_TYPE (camel_mbox_store_get_type ()) -#define CAMEL_MBOX_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MBOX_STORE_TYPE, CamelMboxStore)) -#define CAMEL_MBOX_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MBOX_STORE_TYPE, CamelMboxStoreClass)) -#define CAMEL_IS_MBOX_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_MBOX_STORE_TYPE)) - -typedef struct { - CamelLocalStore parent_object; - -} CamelMboxStore; - -typedef struct { - CamelLocalStoreClass parent_class; - -} CamelMboxStoreClass; - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_mbox_store_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_MBOX_STORE_H */ - - diff --git a/camel/providers/local/camel-mbox-summary.c b/camel/providers/local/camel-mbox-summary.c deleted file mode 100644 index 9dcee0a9c8..0000000000 --- a/camel/providers/local/camel-mbox-summary.c +++ /dev/null @@ -1,1109 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Copyright (C) 2000 Ximian Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "camel-mbox-summary.h" -#include "camel/camel-mime-message.h" -#include "camel/camel-operation.h" - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/uio.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> -#include <ctype.h> - -#include "camel-mbox-summary.h" -#include "camel/camel-file-utils.h" -#include "camel/camel-mime-message.h" -#include "camel/camel-operation.h" -#include "camel-i18n.h" - -#define io(x) -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -#define CAMEL_MBOX_SUMMARY_VERSION (1) - -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_from_parser(CamelFolderSummary *, CamelMimeParser *); -static CamelMessageInfo * message_info_load (CamelFolderSummary *, FILE *); -static int message_info_save (CamelFolderSummary *, FILE *, CamelMessageInfo *); -/*static void message_info_free (CamelFolderSummary *, CamelMessageInfo *);*/ - -static char *mbox_summary_encode_x_evolution (CamelLocalSummary *cls, const CamelLocalMessageInfo *mi); - -static int mbox_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static int mbox_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); -#ifdef STATUS_PINE -static CamelMessageInfo *mbox_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *ci, CamelException *ex); -#endif - -static int mbox_summary_sync_quick(CamelMboxSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static int mbox_summary_sync_full(CamelMboxSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); - -static void camel_mbox_summary_class_init (CamelMboxSummaryClass *klass); -static void camel_mbox_summary_init (CamelMboxSummary *obj); -static void camel_mbox_summary_finalise (CamelObject *obj); - -#ifdef STATUS_PINE -/* Which status flags are stored in each separate header */ -#define STATUS_XSTATUS (CAMEL_MESSAGE_FLAGGED|CAMEL_MESSAGE_ANSWERED|CAMEL_MESSAGE_DELETED) -#define STATUS_STATUS (CAMEL_MESSAGE_SEEN) - -static void encode_status(guint32 flags, char status[8]); -static guint32 decode_status(const char *status); -#endif - -static CamelLocalSummaryClass *camel_mbox_summary_parent; - -CamelType -camel_mbox_summary_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_local_summary_get_type(), "CamelMboxSummary", - sizeof (CamelMboxSummary), - sizeof (CamelMboxSummaryClass), - (CamelObjectClassInitFunc) camel_mbox_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_mbox_summary_init, - (CamelObjectFinalizeFunc) camel_mbox_summary_finalise); - } - - return type; -} -static gboolean -mbox_info_set_user_flag(CamelMessageInfo *mi, const char *name, gboolean value) -{ - int res; - - res = ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->info_set_user_flag(mi, name, value); - if (res) - ((CamelLocalMessageInfo *)mi)->info.flags |= CAMEL_MESSAGE_FOLDER_FLAGGED|CAMEL_MESSAGE_FOLDER_XEVCHANGE; - - return res; -} - -static gboolean -mbox_info_set_user_tag(CamelMessageInfo *mi, const char *name, const char *value) -{ - int res; - - res = ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->info_set_user_tag(mi, name, value); - if (res) - ((CamelLocalMessageInfo *)mi)->info.flags |= CAMEL_MESSAGE_FOLDER_FLAGGED|CAMEL_MESSAGE_FOLDER_XEVCHANGE; - - return res; -} - -#ifdef STATUS_PINE -static gboolean -mbox_info_set_flags(CamelMessageInfo *mi, guint32 flags, guint32 set) -{ - /* Basically, if anything could change the Status line, presume it does */ - if (((CamelMboxSummary *)mi->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 ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->info_set_flags(mi, flags, set); -} -#endif - -static void -camel_mbox_summary_class_init(CamelMboxSummaryClass *klass) -{ - CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *)klass; - CamelLocalSummaryClass *lklass = (CamelLocalSummaryClass *)klass; - - camel_mbox_summary_parent = (CamelLocalSummaryClass *)camel_type_get_global_classfuncs(camel_local_summary_get_type()); - - sklass->summary_header_load = summary_header_load; - sklass->summary_header_save = summary_header_save; - - sklass->message_info_new_from_header = message_info_new_from_header; - sklass->message_info_new_from_parser = message_info_new_from_parser; - sklass->message_info_load = message_info_load; - sklass->message_info_save = message_info_save; - /*sklass->message_info_free = message_info_free;*/ - - sklass->info_set_user_flag = mbox_info_set_user_flag; - sklass->info_set_user_tag = mbox_info_set_user_tag; -#ifdef STATUS_PINE - sklass->info_set_flags = mbox_info_set_flags; -#endif - - lklass->encode_x_evolution = mbox_summary_encode_x_evolution; - lklass->check = mbox_summary_check; - lklass->sync = mbox_summary_sync; -#ifdef STATUS_PINE - lklass->add = mbox_summary_add; -#endif - - klass->sync_quick = mbox_summary_sync_quick; - klass->sync_full = mbox_summary_sync_full; -} - -static void -camel_mbox_summary_init(CamelMboxSummary *obj) -{ - struct _CamelFolderSummary *s = (CamelFolderSummary *)obj; - - /* subclasses need to set the right instance data sizes */ - s->message_info_size = sizeof(CamelMboxMessageInfo); - s->content_info_size = sizeof(CamelMboxMessageContentInfo); - - /* and a unique file version */ - s->version += CAMEL_MBOX_SUMMARY_VERSION; -} - -static void -camel_mbox_summary_finalise(CamelObject *obj) -{ - /*CamelMboxSummary *mbs = CAMEL_MBOX_SUMMARY(obj);*/ -} - -/** - * camel_mbox_summary_new: - * - * Create a new CamelMboxSummary object. - * - * Return value: A new CamelMboxSummary widget. - **/ -CamelMboxSummary * -camel_mbox_summary_new(struct _CamelFolder *folder, const char *filename, const char *mbox_name, CamelIndex *index) -{ - CamelMboxSummary *new = (CamelMboxSummary *)camel_object_new(camel_mbox_summary_get_type()); - - ((CamelFolderSummary *)new)->folder = folder; - - camel_local_summary_construct((CamelLocalSummary *)new, filename, mbox_name, index); - return new; -} - -void camel_mbox_summary_xstatus(CamelMboxSummary *mbs, int state) -{ - mbs->xstatus = state; -} - -static char * -mbox_summary_encode_x_evolution (CamelLocalSummary *cls, const CamelLocalMessageInfo *mi) -{ - const char *p, *uidstr; - guint32 uid; - - /* This is busted, it is supposed to encode ALL DATA */ - p = uidstr = camel_message_info_uid(mi); - while (*p && isdigit(*p)) - p++; - - if (*p == 0 && sscanf(uidstr, "%u", &uid) == 1) { - return g_strdup_printf("%08x-%04x", uid, mi->info.flags & 0xffff); - } else { - return g_strdup_printf("%s-%04x", uidstr, mi->info.flags & 0xffff); - } -} - -static int -summary_header_load(CamelFolderSummary *s, FILE *in) -{ - CamelMboxSummary *mbs = CAMEL_MBOX_SUMMARY(s); - - if (((CamelFolderSummaryClass *)camel_mbox_summary_parent)->summary_header_load(s, in) == -1) - return -1; - - /* legacy version */ - if (s->version == 0x120c) - return camel_file_util_decode_uint32(in, (guint32 *) &mbs->folder_size); - - /* version 1 */ - if (camel_file_util_decode_fixed_int32(in, &mbs->version) == -1 - || camel_file_util_decode_size_t(in, &mbs->folder_size) == -1) - return -1; - - return 0; -} - -static int -summary_header_save(CamelFolderSummary *s, FILE *out) -{ - CamelMboxSummary *mbs = CAMEL_MBOX_SUMMARY(s); - - if (((CamelFolderSummaryClass *)camel_mbox_summary_parent)->summary_header_save(s, out) == -1) - return -1; - - camel_file_util_encode_fixed_int32(out, CAMEL_MBOX_SUMMARY_VERSION); - - return camel_file_util_encode_size_t(out, mbs->folder_size); -} - -static CamelMessageInfo * -message_info_new_from_header(CamelFolderSummary *s, struct _camel_header_raw *h) -{ - CamelMboxMessageInfo *mi; - CamelMboxSummary *mbs = (CamelMboxSummary *)s; - - mi = (CamelMboxMessageInfo *)((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_new_from_header(s, h); - if (mi) { - const char *xev, *uid; - CamelMboxMessageInfo *info = NULL; - int add = 0; /* bitmask of things to add, 1 assign uid, 2, just add as new, 4 = recent */ -#ifdef STATUS_PINE - const char *status = NULL, *xstatus = NULL; - guint32 flags = 0; - - if (mbs->xstatus) { - /* check for existance of status & x-status headers */ - status = camel_header_raw_find(&h, "Status", NULL); - if (status) - flags = decode_status(status); - xstatus = camel_header_raw_find(&h, "X-Status", NULL); - if (xstatus) - flags |= decode_status(xstatus); - } -#endif - /* if we have an xev header, use it, else assign a new one */ - xev = camel_header_raw_find(&h, "X-Evolution", NULL); - if (xev != NULL - && camel_local_summary_decode_x_evolution((CamelLocalSummary *)s, xev, &mi->info) == 0) { - uid = camel_message_info_uid(mi); - d(printf("found valid x-evolution: %s\n", uid)); - info = (CamelMboxMessageInfo *)camel_folder_summary_uid(s, uid); - if (info) { - if ((info->info.info.flags & CAMEL_MESSAGE_FOLDER_NOTSEEN)) { - info->info.info.flags &= ~CAMEL_MESSAGE_FOLDER_NOTSEEN; - camel_message_info_free(mi); - mi = info; - } else { - add = 7; - d(printf("seen '%s' before, adding anew\n", uid)); - camel_message_info_free(info); - } - } else { - add = 2; - d(printf("but isn't present in summary\n")); - } - } else { - d(printf("didn't find x-evolution\n")); - add = 7; - } - - if (add&1) { - mi->info.info.flags |= CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_NOXEV; - mi->info.info.uid = camel_folder_summary_next_uid_string(s); - } else { - camel_folder_summary_set_uid(s, strtoul(camel_message_info_uid(mi), NULL, 10)); - } -#ifdef STATUS_PINE - if (mbs->xstatus && add&2) { - /* use the status as the flags when we read it the first time */ - if (status) - mi->info.info.flags = (mi->info.info.flags & ~(STATUS_STATUS)) | (flags & STATUS_STATUS); - if (xstatus) - mi->info.info.flags = (mi->info.info.flags & ~(STATUS_XSTATUS)) | (flags & STATUS_XSTATUS); - } -#endif - if (mbs->changes) { - if (add&2) - camel_folder_change_info_add_uid(mbs->changes, camel_message_info_uid(mi)); - if ((add&4) && status == NULL) - camel_folder_change_info_recent_uid(mbs->changes, camel_message_info_uid(mi)); - } - - mi->frompos = -1; - } - - return (CamelMessageInfo *)mi; -} - -static CamelMessageInfo * -message_info_new_from_parser(CamelFolderSummary *s, CamelMimeParser *mp) -{ - CamelMessageInfo *mi; - - mi = ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_new_from_parser(s, mp); - if (mi) { - CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi; - - mbi->frompos = camel_mime_parser_tell_start_from(mp); - } - - return mi; -} - -static CamelMessageInfo * -message_info_load(CamelFolderSummary *s, FILE *in) -{ - CamelMessageInfo *mi; - - io(printf("loading mbox message info\n")); - - mi = ((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_load(s, in); - if (mi) { - CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi; - - if (camel_file_util_decode_off_t(in, &mbi->frompos) == -1) - goto error; - } - - return mi; -error: - camel_message_info_free(mi); - return NULL; -} - -static int -message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *mi) -{ - CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi; - - io(printf("saving mbox message info\n")); - - if (((CamelFolderSummaryClass *)camel_mbox_summary_parent)->message_info_save(s, out, mi) == -1 - || camel_file_util_encode_off_t(out, mbi->frompos) == -1) - return -1; - - return 0; -} - -/* like summary_rebuild, but also do changeinfo stuff (if supplied) */ -static int -summary_update(CamelLocalSummary *cls, off_t offset, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - int i, count; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - CamelMboxSummary *mbs = (CamelMboxSummary *)cls; - CamelMimeParser *mp; - CamelMboxMessageInfo *mi; - int fd; - int ok = 0; - struct stat st; - off_t size = 0; - - d(printf("Calling summary update, from pos %d\n", (int)offset)); - - cls->index_force = FALSE; - - camel_operation_start(NULL, _("Storing folder")); - - fd = open(cls->folder_path, O_RDONLY); - if (fd == -1) { - d(printf("%s failed to open: %s\n", cls->folder_path, strerror (errno))); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open folder: %s: %s"), - cls->folder_path, g_strerror (errno)); - camel_operation_end(NULL); - return -1; - } - - if (fstat(fd, &st) == 0) - size = st.st_size; - - mp = camel_mime_parser_new(); - camel_mime_parser_init_with_fd(mp, fd); - camel_mime_parser_scan_from(mp, TRUE); - camel_mime_parser_seek(mp, offset, SEEK_SET); - - if (offset > 0) { - if (camel_mime_parser_step(mp, NULL, NULL) == CAMEL_MIME_PARSER_STATE_FROM - && camel_mime_parser_tell_start_from(mp) == offset) { - camel_mime_parser_unstep(mp); - } else { - g_warning("The next message didn't start where I expected, building summary from start"); - camel_mime_parser_drop_step(mp); - offset = 0; - camel_mime_parser_seek(mp, offset, SEEK_SET); - } - } - - /* we mark messages as to whether we've seen them or not. - If we're not starting from the start, we must be starting - from the old end, so everything must be treated as new */ - count = camel_folder_summary_count(s); - for (i=0;i<count;i++) { - mi = (CamelMboxMessageInfo *)camel_folder_summary_index(s, i); - if (offset == 0) - mi->info.info.flags |= CAMEL_MESSAGE_FOLDER_NOTSEEN; - else - mi->info.info.flags &= ~CAMEL_MESSAGE_FOLDER_NOTSEEN; - camel_message_info_free(mi); - } - mbs->changes = changeinfo; - - while (camel_mime_parser_step(mp, NULL, NULL) == CAMEL_MIME_PARSER_STATE_FROM) { - CamelMessageInfo *info; - off_t pc = camel_mime_parser_tell_start_from (mp) + 1; - - camel_operation_progress (NULL, (int) (((float) pc / size) * 100)); - - info = camel_folder_summary_add_from_parser(s, mp); - if (info == NULL) { - camel_exception_setv(ex, 1, _("Fatal mail parser error near position %ld in folder %s"), - camel_mime_parser_tell(mp), cls->folder_path); - ok = -1; - break; - } - - g_assert(camel_mime_parser_step(mp, NULL, NULL) == CAMEL_MIME_PARSER_STATE_FROM_END); - } - - camel_object_unref(CAMEL_OBJECT (mp)); - - count = camel_folder_summary_count(s); - for (i=0;i<count;i++) { - mi = (CamelMboxMessageInfo *)camel_folder_summary_index(s, i); - /* must've dissapeared from the file? */ - if (mi->info.info.flags & CAMEL_MESSAGE_FOLDER_NOTSEEN) { - d(printf("uid '%s' vanished, removing", camel_message_info_uid(mi))); - if (changeinfo) - camel_folder_change_info_remove_uid(changeinfo, camel_message_info_uid(mi)); - camel_folder_summary_remove(s, (CamelMessageInfo *)mi); - count--; - i--; - } - camel_message_info_free(mi); - } - mbs->changes = NULL; - - /* update the file size/mtime in the summary */ - if (ok != -1) { - if (stat(cls->folder_path, &st) == 0) { - camel_folder_summary_touch(s); - mbs->folder_size = st.st_size; - s->time = st.st_mtime; - } - } - - camel_operation_end(NULL); - - return ok; -} - -static int -mbox_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changes, CamelException *ex) -{ - CamelMboxSummary *mbs = (CamelMboxSummary *)cls; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - struct stat st; - int ret = 0; - int i, count; - - d(printf("Checking summary\n")); - - /* check if the summary is up-to-date */ - if (stat(cls->folder_path, &st) == -1) { - camel_folder_summary_clear(s); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot check folder: %s: %s"), - cls->folder_path, g_strerror (errno)); - return -1; - } - - if (cls->check_force) - mbs->folder_size = 0; - cls->check_force = 0; - - if (st.st_size == 0) { - /* empty? No need to scan at all */ - d(printf("Empty mbox, clearing summary\n")); - count= camel_folder_summary_count(s); - for (i=0;i<count;i++) { - CamelMessageInfo *info = camel_folder_summary_index(s, i); - - if (info) { - camel_folder_change_info_remove_uid(changes, camel_message_info_uid(info)); - camel_message_info_free(info); - } - } - camel_folder_summary_clear(s); - ret = 0; - } else { - /* is the summary uptodate? */ - if (st.st_size != mbs->folder_size || st.st_mtime != s->time) { - if (mbs->folder_size < st.st_size) { - /* this will automatically rescan from 0 if there is a problem */ - d(printf("folder grew, attempting to rebuild from %d\n", mbs->folder_size)); - ret = summary_update(cls, mbs->folder_size, changes, ex); - } else { - d(printf("folder shrank! rebuilding from start\n")); - ret = summary_update(cls, 0, changes, ex); - } - } else { - d(printf("Folder unchanged, do nothing\n")); - } - } - - /* FIXME: move upstream? */ - - if (ret != -1) { - if (mbs->folder_size != st.st_size || s->time != st.st_mtime) { - mbs->folder_size = st.st_size; - s->time = st.st_mtime; - camel_folder_summary_touch(s); - } - } - - return ret; -} - -/* perform a full sync */ -static int -mbox_summary_sync_full(CamelMboxSummary *mbs, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - CamelLocalSummary *cls = (CamelLocalSummary *)mbs; - int fd = -1, fdout = -1; - char *tmpname = NULL; - guint32 flags = (expunge?1:0); - - d(printf("performing full summary/sync\n")); - - camel_operation_start(NULL, _("Storing folder")); - - fd = open(cls->folder_path, O_RDONLY); - if (fd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open file: %s: %s"), - cls->folder_path, g_strerror (errno)); - camel_operation_end(NULL); - return -1; - } - - tmpname = g_alloca (strlen (cls->folder_path) + 5); - sprintf (tmpname, "%s.tmp", cls->folder_path); - d(printf("Writing tmp file to %s\n", tmpname)); - fdout = open(tmpname, O_WRONLY|O_CREAT|O_TRUNC, 0600); - if (fdout == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot open temporary mailbox: %s"), - g_strerror (errno)); - goto error; - } - - if (camel_mbox_summary_sync_mbox((CamelMboxSummary *)cls, flags, changeinfo, fd, fdout, ex) == -1) - goto error; - - d(printf("Closing folders\n")); - - if (close(fd) == -1) { - g_warning("Cannot close source folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not close source folder %s: %s"), - cls->folder_path, g_strerror (errno)); - fd = -1; - goto error; - } - - if (close(fdout) == -1) { - g_warning("Cannot close tmp folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not close temp folder: %s"), - g_strerror (errno)); - fdout = -1; - goto error; - } - - /* this should probably either use unlink/link/unlink, or recopy over - the original mailbox, for various locking reasons/etc */ - if (rename(tmpname, cls->folder_path) == -1) { - g_warning("Cannot rename folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not rename folder: %s"), - g_strerror (errno)); - goto error; - } - tmpname = NULL; - - camel_operation_end(NULL); - - return 0; - error: - if (fd != -1) - close(fd); - - if (fdout != -1) - close(fdout); - - if (tmpname) - unlink(tmpname); - - camel_operation_end(NULL); - - return -1; -} - -/* perform a quick sync - only system flags have changed */ -static int -mbox_summary_sync_quick(CamelMboxSummary *mbs, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - CamelLocalSummary *cls = (CamelLocalSummary *)mbs; - CamelFolderSummary *s = (CamelFolderSummary *)mbs; - CamelMimeParser *mp = NULL; - int i, count; - CamelMboxMessageInfo *info = NULL; - int fd = -1; - char *xevnew, *xevtmp; - const char *xev; - int len; - off_t lastpos; - - d(printf("Performing quick summary sync\n")); - - camel_operation_start(NULL, _("Storing folder")); - - fd = open(cls->folder_path, O_RDWR); - if (fd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open file: %s: %s"), - cls->folder_path, g_strerror (errno)); - - camel_operation_end(NULL); - return -1; - } - - mp = camel_mime_parser_new(); - camel_mime_parser_scan_from(mp, TRUE); - camel_mime_parser_scan_pre_from(mp, TRUE); - camel_mime_parser_init_with_fd(mp, fd); - - count = camel_folder_summary_count(s); - for (i = 0; i < count; i++) { - int xevoffset; - int pc = (i+1)*100/count; - - camel_operation_progress(NULL, pc); - - info = (CamelMboxMessageInfo *)camel_folder_summary_index(s, i); - - g_assert(info); - - d(printf("Checking message %s %08x\n", camel_message_info_uid(info), info->info.flags)); - - if ((info->info.info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) == 0) { - camel_message_info_free((CamelMessageInfo *)info); - info = NULL; - continue; - } - - d(printf("Updating message %s\n", camel_message_info_uid(info))); - - camel_mime_parser_seek(mp, info->frompos, SEEK_SET); - - if (camel_mime_parser_step(mp, 0, 0) != CAMEL_MIME_PARSER_STATE_FROM) { - g_warning("Expected a From line here, didn't get it"); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Summary and folder mismatch, even after a sync")); - goto error; - } - - if (camel_mime_parser_tell_start_from(mp) != info->frompos) { - g_warning("Didn't get the next message where I expected (%d) got %d instead", - (int)info->frompos, (int)camel_mime_parser_tell_start_from(mp)); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Summary and folder mismatch, even after a sync")); - goto error; - } - - if (camel_mime_parser_step(mp, 0, 0) == CAMEL_MIME_PARSER_STATE_FROM_END) { - g_warning("camel_mime_parser_step failed (2)"); - goto error; - } - - xev = camel_mime_parser_header(mp, "X-Evolution", &xevoffset); - if (xev == NULL || camel_local_summary_decode_x_evolution(cls, xev, NULL) == -1) { - g_warning("We're supposed to have a valid x-ev header, but we dont"); - goto error; - } - xevnew = camel_local_summary_encode_x_evolution(cls, &info->info); - /* SIGH: encode_param_list is about the only function which folds headers by itself. - This should be fixed somehow differently (either parser doesn't fold headers, - or param_list doesn't, or something */ - xevtmp = camel_header_unfold(xevnew); - /* the raw header contains a leading ' ', so (dis)count that too */ - if (strlen(xev)-1 != strlen(xevtmp)) { - printf ("strlen(xev)-1 = %d; strlen(xevtmp) = %d\n", strlen(xev)-1, strlen(xevtmp)); - printf ("xev='%s'; xevtmp='%s'\n", xev, xevtmp); - g_free(xevnew); - g_free(xevtmp); - g_warning("Hmm, the xev headers shouldn't have changed size, but they did"); - goto error; - } - g_free(xevtmp); - - /* we write out the xevnew string, assuming its been folded identically to the original too! */ - - lastpos = lseek(fd, 0, SEEK_CUR); - lseek(fd, xevoffset+strlen("X-Evolution: "), SEEK_SET); - do { - len = write(fd, xevnew, strlen(xevnew)); - } while (len == -1 && errno == EINTR); - lseek(fd, lastpos, SEEK_SET); - g_free(xevnew); - - camel_mime_parser_drop_step(mp); - camel_mime_parser_drop_step(mp); - - info->info.info.flags &= 0xffff; - camel_message_info_free((CamelMessageInfo *)info); - } - - d(printf("Closing folders\n")); - - if (close(fd) == -1) { - g_warning ("Cannot close source folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not close source folder %s: %s"), - cls->folder_path, g_strerror (errno)); - fd = -1; - goto error; - } - - camel_object_unref((CamelObject *)mp); - - camel_operation_end(NULL); - - return 0; - error: - if (fd != -1) - close(fd); - if (mp) - camel_object_unref((CamelObject *)mp); - if (info) - camel_message_info_free((CamelMessageInfo *)info); - - camel_operation_end(NULL); - - return -1; -} - -static int -mbox_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - struct stat st; - CamelMboxSummary *mbs = (CamelMboxSummary *)cls; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - int i, count; - int quick = TRUE, work=FALSE; - int ret; - - /* first, sync ourselves up, just to make sure */ - if (camel_local_summary_check(cls, changeinfo, ex) == -1) - return -1; - - count = camel_folder_summary_count(s); - if (count == 0) - return 0; - - /* check what work we have to do, if any */ - for (i=0;quick && i<count; i++) { - CamelMboxMessageInfo *info = (CamelMboxMessageInfo *)camel_folder_summary_index(s, i); - - g_assert(info); - if ((expunge && (info->info.info.flags & CAMEL_MESSAGE_DELETED)) || - (info->info.info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_XEVCHANGE))) - quick = FALSE; - else - work |= (info->info.info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0; - camel_message_info_free(info); - } - - /* yuck i hate this logic, but its to simplify the 'all ok, update summary' and failover cases */ - ret = -1; - if (quick) { - if (work) { - ret = ((CamelMboxSummaryClass *)((CamelObject *)cls)->klass)->sync_quick(mbs, expunge, changeinfo, ex); - if (ret == -1) { - g_warning("failed a quick-sync, trying a full sync"); - camel_exception_clear(ex); - } - } else { - ret = 0; - } - } - - if (ret == -1) - ret = ((CamelMboxSummaryClass *)((CamelObject *)cls)->klass)->sync_full(mbs, expunge, changeinfo, ex); - if (ret == -1) - return -1; - - if (stat(cls->folder_path, &st) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Unknown error: %s"), g_strerror (errno)); - return -1; - } - - if (mbs->folder_size != st.st_size || s->time != st.st_mtime) { - s->time = st.st_mtime; - mbs->folder_size = st.st_size; - camel_folder_summary_touch(s); - } - - return ((CamelLocalSummaryClass *)camel_mbox_summary_parent)->sync(cls, expunge, changeinfo, ex); -} - -int -camel_mbox_summary_sync_mbox(CamelMboxSummary *cls, guint32 flags, CamelFolderChangeInfo *changeinfo, int fd, int fdout, CamelException *ex) -{ - CamelMboxSummary *mbs = (CamelMboxSummary *)cls; - CamelFolderSummary *s = (CamelFolderSummary *)mbs; - CamelMimeParser *mp = NULL; - int i, count; - CamelMboxMessageInfo *info = NULL; - char *buffer, *xevnew = NULL; - size_t len; - const char *fromline; - int lastdel = FALSE; -#ifdef STATUS_PINE - char statnew[8], xstatnew[8]; -#endif - - d(printf("performing full summary/sync\n")); - - /* need to dup this because the mime-parser owns the fd after we give it to it */ - fd = dup(fd); - if (fd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not store folder: %s"), - g_strerror (errno)); - return -1; - } - - mp = camel_mime_parser_new(); - camel_mime_parser_scan_from(mp, TRUE); - camel_mime_parser_scan_pre_from(mp, TRUE); - camel_mime_parser_init_with_fd(mp, fd); - - count = camel_folder_summary_count(s); - for (i = 0; i < count; i++) { - int pc = (i + 1) * 100 / count; - - camel_operation_progress(NULL, pc); - - info = (CamelMboxMessageInfo *)camel_folder_summary_index(s, i); - - g_assert(info); - - d(printf("Looking at message %s\n", camel_message_info_uid(info))); - - /* only need to seek past deleted messages, otherwise we should be at the right spot/state already */ - if (lastdel) { - d(printf("seeking to %d\n", (int)info->frompos)); - camel_mime_parser_seek(mp, info->frompos, SEEK_SET); - } - - if (camel_mime_parser_step(mp, &buffer, &len) != CAMEL_MIME_PARSER_STATE_FROM) { - g_warning("Expected a From line here, didn't get it"); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Summary and folder mismatch, even after a sync")); - goto error; - } - - if (camel_mime_parser_tell_start_from(mp) != info->frompos) { - g_warning("Didn't get the next message where I expected (%d) got %d instead", - (int)info->frompos, (int)camel_mime_parser_tell_start_from(mp)); - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Summary and folder mismatch, even after a sync")); - goto error; - } - - lastdel = FALSE; - if ((flags&1) && info->info.info.flags & CAMEL_MESSAGE_DELETED) { - const char *uid = camel_message_info_uid(info); - - d(printf("Deleting %s\n", uid)); - - if (((CamelLocalSummary *)cls)->index) - camel_index_delete_name(((CamelLocalSummary *)cls)->index, uid); - - /* remove it from the change list */ - camel_folder_change_info_remove_uid(changeinfo, uid); - camel_folder_summary_remove(s, (CamelMessageInfo *)info); - camel_message_info_free((CamelMessageInfo *)info); - count--; - i--; - info = NULL; - lastdel = TRUE; - } else { - /* otherwise, the message is staying, copy its From_ line across */ -#if 0 - if (i>0) - write(fdout, "\n", 1); -#endif - info->frompos = lseek(fdout, 0, SEEK_CUR); - fromline = camel_mime_parser_from_line(mp); - write(fdout, fromline, strlen(fromline)); - } - - if (info && info->info.info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_FLAGGED)) { - d(printf("Updating header for %s flags = %08x\n", camel_message_info_uid(info), info->info.flags)); - - if (camel_mime_parser_step(mp, &buffer, &len) == CAMEL_MIME_PARSER_STATE_FROM_END) { - g_warning("camel_mime_parser_step failed (2)"); - goto error; - } - - xevnew = camel_local_summary_encode_x_evolution((CamelLocalSummary *)cls, &info->info); -#ifdef STATUS_PINE - if (mbs->xstatus) { - encode_status(info->info.info.flags & STATUS_STATUS, statnew); - encode_status(info->info.info.flags & STATUS_XSTATUS, xstatnew); - len = camel_local_summary_write_headers(fdout, camel_mime_parser_headers_raw(mp), xevnew, statnew, xstatnew); - } else { -#endif - len = camel_local_summary_write_headers(fdout, camel_mime_parser_headers_raw(mp), xevnew, NULL, NULL); -#ifdef STATUS_PINE - } -#endif - if (len == -1) { - d(printf("Error writing to tmp mailbox\n")); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Error writing to temp mailbox: %s"), - g_strerror (errno)); - goto error; - } - info->info.info.flags &= 0xffff; - g_free(xevnew); - xevnew = NULL; - camel_mime_parser_drop_step(mp); - } - - camel_mime_parser_drop_step(mp); - if (info) { - d(printf("looking for message content to copy across from %d\n", (int)camel_mime_parser_tell(mp))); - while (camel_mime_parser_step(mp, &buffer, &len) == CAMEL_MIME_PARSER_STATE_PRE_FROM) { - /*d(printf("copying mbox contents to tmp: '%.*s'\n", len, buffer));*/ - if (write(fdout, buffer, len) != len) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Writing to tmp mailbox failed: %s: %s"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno)); - goto error; - } - } - - if (write(fdout, "\n", 1) != 1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Error writing to temp mailbox: %s"), - g_strerror (errno)); - goto error; - } - - d(printf("we are now at %d, from = %d\n", (int)camel_mime_parser_tell(mp), - (int)camel_mime_parser_tell_start_from(mp))); - camel_mime_parser_unstep(mp); - camel_message_info_free((CamelMessageInfo *)info); - info = NULL; - } - } - -#if 0 - /* if last was deleted, append the \n we removed */ - if (lastdel && count > 0) - write(fdout, "\n", 1); -#endif - - camel_object_unref((CamelObject *)mp); - - return 0; - error: - g_free(xevnew); - - if (mp) - camel_object_unref((CamelObject *)mp); - if (info) - camel_message_info_free((CamelMessageInfo *)info); - - return -1; -} - -#ifdef STATUS_PINE -static CamelMessageInfo * -mbox_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *ci, CamelException *ex) -{ - CamelMboxMessageInfo *mi; - - mi = (CamelMboxMessageInfo *)((CamelLocalSummaryClass *)camel_mbox_summary_parent)->add(cls, msg, info, ci, ex); - if (mi && ((CamelMboxSummary *)cls)->xstatus) { - char status[8]; - - /* we snoop and add status/x-status headers to suit */ - encode_status(mi->info.info.flags & STATUS_STATUS, status); - camel_medium_set_header((CamelMedium *)msg, "Status", status); - encode_status(mi->info.info.flags & STATUS_XSTATUS, status); - camel_medium_set_header((CamelMedium *)msg, "X-Status", status); - } - - return (CamelMessageInfo *)mi; -} - -static struct { - char tag; - guint32 flag; -} status_flags[] = { - { 'F', CAMEL_MESSAGE_FLAGGED }, - { 'A', CAMEL_MESSAGE_ANSWERED }, - { 'D', CAMEL_MESSAGE_DELETED }, - { 'R', CAMEL_MESSAGE_SEEN }, -}; - -static void -encode_status(guint32 flags, char status[8]) -{ - char *p; - int i; - - p = status; - for (i=0;i<sizeof(status_flags)/sizeof(status_flags[0]);i++) - if (status_flags[i].flag & flags) - *p++ = status_flags[i].tag; - *p++ = 'O'; - *p=0; -} - -static guint32 -decode_status(const char *status) -{ - const char *p; - char c; - guint32 flags = 0; - int i; - - p = status; - while ((c = *p++)) { - for (i=0;i<sizeof(status_flags)/sizeof(status_flags[0]);i++) - if (status_flags[i].tag == *p) - flags |= status_flags[i].flag; - } - - return flags; -} - -#endif /* STATUS_PINE */ diff --git a/camel/providers/local/camel-mbox-summary.h b/camel/providers/local/camel-mbox-summary.h deleted file mode 100644 index 9089fe7c8e..0000000000 --- a/camel/providers/local/camel-mbox-summary.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_MBOX_SUMMARY_H -#define _CAMEL_MBOX_SUMMARY_H - -#include "camel-local-summary.h" - -/* Enable the use of elm/pine style "Status" & "X-Status" headers */ -#define STATUS_PINE - -#define CAMEL_MBOX_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_mbox_summary_get_type (), CamelMboxSummary) -#define CAMEL_MBOX_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_mbox_summary_get_type (), CamelMboxSummaryClass) -#define CAMEL_IS_MBOX_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_mbox_summary_get_type ()) - -typedef struct _CamelMboxSummary CamelMboxSummary; -typedef struct _CamelMboxSummaryClass CamelMboxSummaryClass; - -typedef struct _CamelMboxMessageContentInfo { - CamelMessageContentInfo info; -} CamelMboxMessageContentInfo; - -typedef struct _CamelMboxMessageInfo { - CamelLocalMessageInfo info; - - off_t frompos; -} CamelMboxMessageInfo; - -struct _CamelMboxSummary { - CamelLocalSummary parent; - - CamelFolderChangeInfo *changes; /* used to build change sets */ - - guint32 version; - size_t folder_size; /* size of the mbox file, last sync */ - - unsigned int xstatus:1; /* do we store/honour xstatus/status headers */ -}; - -struct _CamelMboxSummaryClass { - CamelLocalSummaryClass parent_class; - - /* sync in-place */ - int (*sync_quick)(CamelMboxSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); - /* sync requires copy */ - int (*sync_full)(CamelMboxSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); -}; - -CamelType camel_mbox_summary_get_type (void); -CamelMboxSummary *camel_mbox_summary_new (struct _CamelFolder *, const char *filename, const char *mbox_name, CamelIndex *index); - -/* do we honour/use xstatus headers, etc */ -void camel_mbox_summary_xstatus(CamelMboxSummary *mbs, int state); - -/* build a new mbox from an existing mbox storing summary information */ -int camel_mbox_summary_sync_mbox(CamelMboxSummary *cls, guint32 flags, CamelFolderChangeInfo *changeinfo, int fd, int fdout, CamelException *ex); - -#endif /* ! _CAMEL_MBOX_SUMMARY_H */ - diff --git a/camel/providers/local/camel-mh-folder.c b/camel/providers/local/camel-mh-folder.c deleted file mode 100644 index 1b054a4547..0000000000 --- a/camel/providers/local/camel-mh-folder.c +++ /dev/null @@ -1,234 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999, 2003 Ximian Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <sys/types.h> -#include <dirent.h> -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <fcntl.h> - -#include "camel-mh-folder.h" -#include "camel-mh-store.h" -#include "camel-stream-fs.h" -#include "camel-mh-summary.h" -#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))*/ - -static CamelLocalFolderClass *parent_class = NULL; - -/* Returns the class for a CamelMhFolder */ -#define CMHF_CLASS(so) CAMEL_MH_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CMHS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static CamelLocalSummary *mh_create_summary(CamelLocalFolder *lf, const char *path, const char *folder, CamelIndex *index); - -static void mh_append_message(CamelFolder * folder, CamelMimeMessage * message, const CamelMessageInfo *info, char **appended_uid, CamelException * ex); -static CamelMimeMessage *mh_get_message(CamelFolder * folder, const gchar * uid, CamelException * ex); - -static void mh_finalize(CamelObject * object); - -static void camel_mh_folder_class_init(CamelObjectClass * camel_mh_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_mh_folder_class); - CamelLocalFolderClass *lclass = (CamelLocalFolderClass *)camel_mh_folder_class; - - parent_class = CAMEL_LOCAL_FOLDER_CLASS (camel_type_get_global_classfuncs(camel_local_folder_get_type())); - - /* virtual method definition */ - - /* virtual method overload */ - camel_folder_class->append_message = mh_append_message; - camel_folder_class->get_message = mh_get_message; - - lclass->create_summary = mh_create_summary; -} - -static void mh_init(gpointer object, gpointer klass) -{ - /*CamelFolder *folder = object; - CamelMhFolder *mh_folder = object;*/ -} - -static void mh_finalize(CamelObject * object) -{ - /*CamelMhFolder *mh_folder = CAMEL_MH_FOLDER(object);*/ -} - -CamelType camel_mh_folder_get_type(void) -{ - static CamelType camel_mh_folder_type = CAMEL_INVALID_TYPE; - - if (camel_mh_folder_type == CAMEL_INVALID_TYPE) { - camel_mh_folder_type = camel_type_register(CAMEL_LOCAL_FOLDER_TYPE, "CamelMhFolder", - sizeof(CamelMhFolder), - sizeof(CamelMhFolderClass), - (CamelObjectClassInitFunc) camel_mh_folder_class_init, - NULL, - (CamelObjectInitFunc) mh_init, - (CamelObjectFinalizeFunc) mh_finalize); - } - - return camel_mh_folder_type; -} - -CamelFolder * -camel_mh_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex) -{ - CamelFolder *folder; - - d(printf("Creating mh folder: %s\n", full_name)); - - folder = (CamelFolder *)camel_object_new(CAMEL_MH_FOLDER_TYPE); - folder = (CamelFolder *)camel_local_folder_construct((CamelLocalFolder *)folder, - parent_store, full_name, flags, ex); - - return folder; -} - -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); -} - -static void -mh_append_message (CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, char **appended_uid, CamelException *ex) -{ - CamelMhFolder *mh_folder = (CamelMhFolder *)folder; - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelStream *output_stream; - CamelMessageInfo *mi; - char *name; - - /* FIXME: probably needs additional locking (although mh doesn't appear do do it) */ - - d(printf("Appending message\n")); - - /* add it to the summary/assign the uid, etc */ - mi = camel_local_summary_add((CamelLocalSummary *)folder->summary, message, info, lf->changes, ex); - if (camel_exception_is_set (ex)) - return; - - d(printf("Appending message: uid is %s\n", camel_message_info_uid(mi))); - - /* write it out, use the uid we got from the summary */ - name = g_strdup_printf("%s/%s", lf->folder_path, camel_message_info_uid(mi)); - output_stream = camel_stream_fs_new_with_name(name, O_WRONLY|O_CREAT, 0600); - if (output_stream == NULL) - goto fail_write; - - if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *)message, output_stream) == -1 - || camel_stream_close (output_stream) == -1) - goto fail_write; - - /* close this? */ - camel_object_unref (CAMEL_OBJECT (output_stream)); - - g_free(name); - - camel_object_trigger_event (CAMEL_OBJECT (folder), "folder_changed", - ((CamelLocalFolder *)mh_folder)->changes); - camel_folder_change_info_clear (((CamelLocalFolder *)mh_folder)->changes); - - if (appended_uid) - *appended_uid = g_strdup(camel_message_info_uid(mi)); - - return; - - fail_write: - - /* remove the summary info so we are not out-of-sync with the mh folder */ - camel_folder_summary_remove_uid (CAMEL_FOLDER_SUMMARY (folder->summary), - camel_message_info_uid (mi)); - - if (errno == EINTR) - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("MH append message cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot append message to mh folder: %s: %s"), - name, g_strerror (errno)); - - if (output_stream) { - camel_object_unref (CAMEL_OBJECT (output_stream)); - unlink (name); - } - - g_free (name); -} - -static CamelMimeMessage *mh_get_message(CamelFolder * folder, const gchar * uid, CamelException * ex) -{ - CamelLocalFolder *lf = (CamelLocalFolder *)folder; - CamelStream *message_stream = NULL; - CamelMimeMessage *message = NULL; - CamelMessageInfo *info; - char *name; - - d(printf("getting message: %s\n", uid)); - - /* get the message summary info */ - if ((info = camel_folder_summary_uid(folder->summary, uid)) == NULL) { - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("Cannot get message: %s from folder %s\n %s"), uid, lf->folder_path, - _("No such message")); - return NULL; - } - - /* we only need it to check the message exists */ - camel_message_info_free(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) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get message: %s from folder %s\n %s"), name, lf->folder_path, - g_strerror (errno)); - g_free(name); - return NULL; - } - - message = camel_mime_message_new(); - if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)message, message_stream) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get message: %s from folder %s\n %s"), name, lf->folder_path, - _("Message construction failed.")); - g_free(name); - camel_object_unref((CamelObject *)message_stream); - camel_object_unref((CamelObject *)message); - return NULL; - - } - camel_object_unref((CamelObject *)message_stream); - g_free(name); - - return message; -} diff --git a/camel/providers/local/camel-mh-folder.h b/camel/providers/local/camel-mh-folder.h deleted file mode 100644 index 125f8c8ac5..0000000000 --- a/camel/providers/local/camel-mh-folder.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 1999 Ximian Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_MH_FOLDER_H -#define CAMEL_MH_FOLDER_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus } */ -#include "camel-local-folder.h" - -#define CAMEL_MH_FOLDER_TYPE (camel_mh_folder_get_type ()) -#define CAMEL_MH_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MH_FOLDER_TYPE, CamelMhFolder)) -#define CAMEL_MH_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MH_FOLDER_TYPE, CamelMhFolderClass)) -#define CAMEL_IS_MH_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_MH_FOLDER_TYPE)) - -typedef struct { - CamelLocalFolder parent_object; - -} CamelMhFolder; - -typedef struct { - CamelLocalFolderClass parent_class; - - /* Virtual methods */ - -} CamelMhFolderClass; - -/* public methods */ -CamelFolder *camel_mh_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex); - -/* Standard Camel function */ -CamelType camel_mh_folder_get_type(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* CAMEL_MH_FOLDER_H */ diff --git a/camel/providers/local/camel-mh-store.c b/camel/providers/local/camel-mh-store.c deleted file mode 100644 index 03b6db92bd..0000000000 --- a/camel/providers/local/camel-mh-store.c +++ /dev/null @@ -1,579 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2000 Ximian, Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/stat.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> -#include <dirent.h> - -#include "camel-mh-store.h" -#include "camel-mh-folder.h" -#include "camel-exception.h" -#include "camel-url.h" -#include "camel-private.h" -#include "camel-i18n.h" - -#include <camel/camel-stream-fs.h> -#include <camel/camel-stream-buffer.h> - -#include "camel-mh-summary.h" - -static CamelLocalStoreClass *parent_class = NULL; - -#define d(x) - -/* Returns the class for a CamelMhStore */ -#define CMHS_CLASS(so) CAMEL_MH_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CMHF_CLASS(so) CAMEL_MH_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static void construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex); -static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex); -static CamelFolder *get_inbox (CamelStore *store, CamelException *ex); -static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex); -static void rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex); -static CamelFolderInfo * get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex); - -static void camel_mh_store_class_init(CamelObjectClass * camel_mh_store_class) -{ - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS(camel_mh_store_class); - CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS(camel_mh_store_class); - - parent_class = (CamelLocalStoreClass *)camel_type_get_global_classfuncs(camel_local_store_get_type()); - - /* virtual method overload, use defaults for most */ - camel_service_class->construct = construct; - - camel_store_class->get_folder = get_folder; - camel_store_class->get_inbox = get_inbox; - camel_store_class->delete_folder = delete_folder; - camel_store_class->rename_folder = rename_folder; - camel_store_class->get_folder_info = get_folder_info; -} - -CamelType camel_mh_store_get_type(void) -{ - static CamelType camel_mh_store_type = CAMEL_INVALID_TYPE; - - if (camel_mh_store_type == CAMEL_INVALID_TYPE) { - camel_mh_store_type = camel_type_register(CAMEL_LOCAL_STORE_TYPE, "CamelMhStore", - sizeof(CamelMhStore), - sizeof(CamelMhStoreClass), - (CamelObjectClassInitFunc) camel_mh_store_class_init, - NULL, - NULL, - NULL); - } - - return camel_mh_store_type; -} - -static void -construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex) -{ - CamelMhStore *mh_store = (CamelMhStore *)service; - - CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); - if (camel_exception_is_set (ex)) - return; - - if (camel_url_get_param(url, "dotfolders")) - mh_store->flags |= CAMEL_MH_DOTFOLDERS; -} - -enum { - UPDATE_NONE, - UPDATE_ADD, - UPDATE_REMOVE, -}; - -/* update the .folders file if it exists, or create it if it doesn't */ -static void -folders_update(const char *root, const char *folder, int mode) -{ - char *tmp, *tmpnew, *line = NULL; - CamelStream *stream, *in = NULL, *out = NULL; - - tmpnew = g_alloca (strlen (root) + 16); - sprintf (tmpnew, "%s.folders~", root); - - out = camel_stream_fs_new_with_name(tmpnew, O_WRONLY|O_CREAT|O_TRUNC, 0666); - if (out == NULL) - goto fail; - - tmp = g_alloca (strlen (root) + 16); - sprintf (tmp, "%s.folders", root); - stream = camel_stream_fs_new_with_name(tmp, O_RDONLY, 0); - if (stream) { - in = camel_stream_buffer_new(stream, CAMEL_STREAM_BUFFER_READ); - camel_object_unref(stream); - } - if (in == NULL || stream == NULL) { - if (mode == UPDATE_ADD && camel_stream_printf(out, "%s\n", folder) == -1) - goto fail; - goto done; - } - - while ((line = camel_stream_buffer_read_line((CamelStreamBuffer *)in))) { - int copy = TRUE; - - switch (mode) { - case UPDATE_REMOVE: - if (strcmp(line, folder) == 0) - copy = FALSE; - break; - case UPDATE_ADD: { - int cmp = strcmp(line, folder); - - if (cmp > 0) { - /* found insertion point */ - if (camel_stream_printf(out, "%s\n", folder) == -1) - goto fail; - mode = UPDATE_NONE; - } else if (tmp == 0) { - /* already there */ - mode = UPDATE_NONE; - } - break; } - case UPDATE_NONE: - break; - } - - if (copy && camel_stream_printf(out, "%s\n", line) == -1) - goto fail; - - g_free(line); - line = NULL; - } - - /* add to end? */ - if (mode == UPDATE_ADD && camel_stream_printf(out, "%s\n", folder) == -1) - goto fail; - - if (camel_stream_close(out) == -1) - goto fail; - -done: - /* should we care if this fails? I suppose so ... */ - rename(tmpnew, tmp); -fail: - unlink(tmpnew); /* remove it if its there */ - g_free(line); - if (in) - camel_object_unref(in); - if (out) - camel_object_unref(out); -} - -static CamelFolder * -get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex) -{ - char *name; - struct stat st; - - if (!((CamelStoreClass *)parent_class)->get_folder(store, folder_name, flags, ex)) - return NULL; - - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - - if (stat(name, &st) == -1) { - if (errno != ENOENT) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get folder `%s': %s"), - folder_name, g_strerror (errno)); - g_free (name); - return NULL; - } - if ((flags & CAMEL_STORE_FOLDER_CREATE) == 0) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot get folder `%s': folder does not exist."), - folder_name); - g_free (name); - return NULL; - } - - if (mkdir(name, 0777) != 0) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create folder `%s': %s"), - folder_name, g_strerror (errno)); - g_free (name); - return NULL; - } - - /* add to .folders if we are supposed to */ - /* FIXME: throw exception on error */ - if (((CamelMhStore *)store)->flags & CAMEL_MH_DOTFOLDERS) - folders_update(((CamelLocalStore *)store)->toplevel_dir, folder_name, UPDATE_ADD); - } else if (!S_ISDIR(st.st_mode)) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Cannot get folder `%s': not a directory."), folder_name); - g_free (name); - return NULL; - } else if (flags & CAMEL_STORE_FOLDER_EXCL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create folder `%s': folder exists."), folder_name); - g_free (name); - return NULL; - } - - g_free(name); - - return camel_mh_folder_new(store, folder_name, flags, ex); -} - -static CamelFolder * -get_inbox (CamelStore *store, CamelException *ex) -{ - return get_folder (store, "inbox", 0, ex); -} - -static void delete_folder(CamelStore * store, const char *folder_name, CamelException * ex) -{ - char *name; - - /* remove folder directory - will fail if not empty */ - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - if (rmdir(name) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not delete folder `%s': %s"), - folder_name, g_strerror (errno)); - g_free(name); - return; - } - g_free(name); - - /* remove from .folders if we are supposed to */ - if (((CamelMhStore *)store)->flags & CAMEL_MH_DOTFOLDERS) - folders_update(((CamelLocalStore *)store)->toplevel_dir, folder_name, UPDATE_REMOVE); - - /* and remove metadata */ - ((CamelStoreClass *)parent_class)->delete_folder(store, folder_name, ex); -} - -static void -rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex) -{ - CamelException e; - - camel_exception_init(&e); - ((CamelStoreClass *)parent_class)->rename_folder(store, old, new, &e); - if (camel_exception_is_set(&e)) { - camel_exception_xfer(ex, &e); - return; - } - camel_exception_clear(&e); - - if (((CamelMhStore *)store)->flags & CAMEL_MH_DOTFOLDERS) { - /* yeah this is messy, but so is mh! */ - folders_update(((CamelLocalStore *)store)->toplevel_dir, new, UPDATE_ADD); - folders_update(((CamelLocalStore *)store)->toplevel_dir, old, UPDATE_REMOVE); - } -} - -static void -fill_fi(CamelStore *store, CamelFolderInfo *fi, guint32 flags) -{ - CamelFolder *folder; - - folder = camel_object_bag_get(store->folders, fi->full_name); - - if (folder == NULL - && (flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0) - folder = camel_store_get_folder(store, fi->full_name, 0, NULL); - - if (folder) { - if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0) - camel_folder_refresh_info(folder, NULL); - fi->unread = camel_folder_get_unread_message_count(folder); - fi->total = camel_folder_get_message_count(folder); - camel_object_unref(folder); - } else { - char *path, *folderpath; - CamelFolderSummary *s; - const char *root; - - /* This should be fast enough not to have to test for INFO_FAST */ - - /* We could: if we have no folder, and FAST isn't specified, perform a full - scan of all messages for their status flags. But its probably not worth - it as we need to read the top of every file, i.e. very very slow */ - - root = camel_local_store_get_toplevel_dir((CamelLocalStore *)store); - path = g_strdup_printf("%s/%s.ev-summary", root, fi->full_name); - folderpath = g_strdup_printf("%s/%s", root, fi->full_name); - s = (CamelFolderSummary *)camel_mh_summary_new(NULL, path, folderpath, NULL); - if (camel_folder_summary_header_load(s) != -1) { - fi->unread = s->unread_count; - fi->total = s->saved_count; - } - camel_object_unref(s); - g_free(folderpath); - g_free(path); - } -} - -static CamelFolderInfo * -folder_info_new (CamelStore *store, CamelURL *url, const char *root, const char *path, guint32 flags) -{ - /* FIXME: need to set fi->flags = CAMEL_FOLDER_NOSELECT (and possibly others) when appropriate */ - CamelFolderInfo *fi; - char *base; - - base = strrchr(path, '/'); - - camel_url_set_fragment (url, path); - - /* Build the folder info structure. */ - fi = g_malloc0(sizeof(*fi)); - fi->uri = camel_url_to_string (url, 0); - fi->full_name = g_strdup(path); - fi->name = g_strdup(base?base+1:path); - fill_fi(store, fi, flags); - - d(printf("New folderinfo:\n '%s'\n '%s'\n '%s'\n", fi->full_name, fi->uri, fi->path)); - - return fi; -} - -/* used to find out where we've visited already */ -struct _inode { - dev_t dnode; - ino_t inode; -}; - -/* Scan path, under root, for directories to add folders for. Both - * root and path should have a trailing "/" if they aren't empty. */ -static void -recursive_scan (CamelStore *store, CamelURL *url, CamelFolderInfo **fip, CamelFolderInfo *parent, - GHashTable *visited, const char *root, const char *path, guint32 flags) -{ - char *fullpath, *tmp; - DIR *dp; - struct dirent *d; - struct stat st; - CamelFolderInfo *fi; - struct _inode in, *inew; - - /* Open the specified directory. */ - if (path[0]) { - fullpath = alloca (strlen (root) + strlen (path) + 2); - sprintf (fullpath, "%s/%s", root, path); - } else - fullpath = (char *)root; - - if (stat(fullpath, &st) == -1 || !S_ISDIR(st.st_mode)) - return; - - in.dnode = st.st_dev; - in.inode = st.st_ino; - - /* see if we've visited already */ - if (g_hash_table_lookup(visited, &in) != NULL) - return; - - inew = g_malloc(sizeof(*inew)); - *inew = in; - g_hash_table_insert(visited, inew, inew); - - /* link in ... */ - fi = folder_info_new(store, url, root, path, flags); - fi->parent = parent; - fi->next = *fip; - *fip = fi; - - if (((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) || parent == NULL)) { - /* now check content for possible other directories */ - dp = opendir(fullpath); - if (dp == NULL) - return; - - /* Look for subdirectories to add and scan. */ - while ((d = readdir(dp)) != NULL) { - /* Skip current and parent directory. */ - if (strcmp(d->d_name, ".") == 0 - || strcmp(d->d_name, "..") == 0) - continue; - - /* skip fully-numerical entries (i.e. mh messages) */ - strtoul(d->d_name, &tmp, 10); - if (*tmp == 0) - continue; - - /* otherwise, treat at potential node, and recurse, a bit more expensive than needed, but tough! */ - if (path[0]) { - tmp = g_strdup_printf("%s/%s", path, d->d_name); - recursive_scan(store, url, &fi->child, fi, visited, root, tmp, flags); - g_free(tmp); - } else { - recursive_scan(store, url, &fi->child, fi, visited, root, d->d_name, flags); - } - } - - closedir(dp); - } -} - -/* scan a .folders file */ -static void -folders_scan(CamelStore *store, CamelURL *url, const char *root, const char *top, CamelFolderInfo **fip, guint32 flags) -{ - CamelFolderInfo *fi; - char line[512], *path, *tmp; - CamelStream *stream, *in; - struct stat st; - GPtrArray *folders; - GHashTable *visited; - int len; - - tmp = g_alloca (strlen (root) + 16); - sprintf (tmp, "%s/.folders", root); - stream = camel_stream_fs_new_with_name(tmp, 0, O_RDONLY); - if (stream == NULL) - return; - - in = camel_stream_buffer_new(stream, CAMEL_STREAM_BUFFER_READ); - camel_object_unref(stream); - if (in == NULL) - return; - - visited = g_hash_table_new(g_str_hash, g_str_equal); - folders = g_ptr_array_new(); - - while ( (len = camel_stream_buffer_gets((CamelStreamBuffer *)in, line, sizeof(line))) > 0) { - /* ignore blank lines */ - if (len <= 1) - continue; - /* check for invalidly long lines, we abort evreything and fallback */ - if (line[len-1] != '\n') { - int i; - - for (i=0;i<folders->len;i++) - camel_folder_info_free(folders->pdata[i]); - g_ptr_array_set_size(folders, 0); - break; - } - line[len-1] = 0; - - /* check for \r ? */ - - if (top && top[0]) { - int toplen = strlen(top); - - /* check is subdir */ - if (strncmp(top, line, len) != 0) - continue; - - /* check is not sub-subdir if not recursive */ - if ((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) == 0 - && (tmp = strrchr(line, '/')) - && tmp > line+toplen) - continue; - } - - if (g_hash_table_lookup(visited, line) != NULL) - continue; - - tmp = g_strdup(line); - g_hash_table_insert(visited, tmp, tmp); - - path = g_strdup_printf("%s/%s", root, line); - if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { - fi = folder_info_new(store, url, root, line, flags); - g_ptr_array_add(folders, fi); - } - g_free(path); - } - - if (folders->len) - *fip = camel_folder_info_build(folders, NULL, '/', TRUE); - g_ptr_array_free(folders, TRUE); - - g_hash_table_foreach(visited, (GHFunc)g_free, NULL); - g_hash_table_destroy(visited); - - camel_object_unref(in); -} - -/* FIXME: move to camel-local, this is shared with maildir code */ -static guint inode_hash(const void *d) -{ - const struct _inode *v = d; - - return v->inode ^ v->dnode; -} - -static gboolean inode_equal(const void *a, const void *b) -{ - const struct _inode *v1 = a, *v2 = b; - - return v1->inode == v2->inode && v1->dnode == v2->dnode; -} - -static void inode_free(void *k, void *v, void *d) -{ - g_free(k); -} - -static CamelFolderInfo * -get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - CamelFolderInfo *fi = NULL; - CamelURL *url; - char *root; - - root = ((CamelService *)store)->url->path; - - url = camel_url_copy (((CamelService *) store)->url); - - /* use .folders if we are supposed to */ - if (((CamelMhStore *)store)->flags & CAMEL_MH_DOTFOLDERS) { - folders_scan(store, url, root, top, &fi, flags); - } else { - GHashTable *visited = g_hash_table_new(inode_hash, inode_equal); - - if (top == NULL) - top = ""; - - recursive_scan(store, url, &fi, NULL, visited, root, top, flags); - - /* if we actually scanned from root, we have a "" root node we dont want */ - if (fi != NULL && top[0] == 0) { - CamelFolderInfo *rfi; - - rfi = fi; - fi = rfi->child; - rfi->child = NULL; - camel_folder_info_free(rfi); - } - - g_hash_table_foreach(visited, inode_free, NULL); - g_hash_table_destroy(visited); - } - - camel_url_free (url); - - return fi; -} diff --git a/camel/providers/local/camel-mh-store.h b/camel/providers/local/camel-mh-store.h deleted file mode 100644 index 96522cb01f..0000000000 --- a/camel/providers/local/camel-mh-store.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2000 Ximian, Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_MH_STORE_H -#define CAMEL_MH_STORE_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus } */ - -#include "camel-local-store.h" - -#define CAMEL_MH_STORE_TYPE (camel_mh_store_get_type ()) -#define CAMEL_MH_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_MH_STORE_TYPE, CamelMhStore)) -#define CAMEL_MH_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_MH_STORE_TYPE, CamelMhStoreClass)) -#define CAMEL_IS_MH_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_MH_STORE_TYPE)) - -enum { - CAMEL_MH_DOTFOLDERS = (1<<0), /* update/use .folders file */ -}; - -typedef struct { - CamelLocalStore parent_object; - - guint32 flags; -} CamelMhStore; - -typedef struct { - CamelLocalStoreClass parent_class; - -} CamelMhStoreClass; - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_mh_store_get_type(void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* CAMEL_MH_STORE_H */ diff --git a/camel/providers/local/camel-mh-summary.c b/camel/providers/local/camel-mh-summary.c deleted file mode 100644 index fe0201e4f2..0000000000 --- a/camel/providers/local/camel-mh-summary.c +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Not Zed <notzed@lostzed.mmc.com.au> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#include <sys/uio.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> - -#include <dirent.h> - -#include <ctype.h> - -#include "camel-mh-summary.h" -#include <camel/camel-mime-message.h> - -#include "camel-private.h" -#include "camel-i18n.h" - -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -#define CAMEL_MH_SUMMARY_VERSION (0x2000) - -static int mh_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); -static int mh_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); -/*static int mh_summary_add(CamelLocalSummary *cls, CamelMimeMessage *msg, CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex);*/ - -static char *mh_summary_next_uid_string(CamelFolderSummary *s); - -static void camel_mh_summary_class_init (CamelMhSummaryClass *class); -static void camel_mh_summary_init (CamelMhSummary *gspaper); -static void camel_mh_summary_finalise (CamelObject *obj); - -#define _PRIVATE(x) (((CamelMhSummary *)(x))->priv) - -struct _CamelMhSummaryPrivate { - char *current_uid; -}; - -static CamelLocalSummaryClass *parent_class; - -CamelType -camel_mh_summary_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_local_summary_get_type (), "CamelMhSummary", - sizeof(CamelMhSummary), - sizeof(CamelMhSummaryClass), - (CamelObjectClassInitFunc)camel_mh_summary_class_init, - NULL, - (CamelObjectInitFunc)camel_mh_summary_init, - (CamelObjectFinalizeFunc)camel_mh_summary_finalise); - } - - return type; -} - -static void -camel_mh_summary_class_init (CamelMhSummaryClass *class) -{ - CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *) class; - CamelLocalSummaryClass *lklass = (CamelLocalSummaryClass *)class; - - parent_class = (CamelLocalSummaryClass *)camel_type_get_global_classfuncs(camel_local_summary_get_type ()); - - /* override methods */ - sklass->next_uid_string = mh_summary_next_uid_string; - - lklass->check = mh_summary_check; - lklass->sync = mh_summary_sync; - /*lklass->add = mh_summary_add;*/ -} - -static void -camel_mh_summary_init (CamelMhSummary *o) -{ - struct _CamelFolderSummary *s = (CamelFolderSummary *) o; - - o->priv = g_malloc0(sizeof(*o->priv)); - /* set unique file version */ - s->version += CAMEL_MH_SUMMARY_VERSION; -} - -static void -camel_mh_summary_finalise(CamelObject *obj) -{ - CamelMhSummary *o = (CamelMhSummary *)obj; - - g_free(o->priv); -} - -/** - * camel_mh_summary_new: - * - * Create a new CamelMhSummary object. - * - * Return value: A new #CamelMhSummary object. - **/ -CamelMhSummary *camel_mh_summary_new(struct _CamelFolder *folder, const char *filename, const char *mhdir, CamelIndex *index) -{ - CamelMhSummary *o = (CamelMhSummary *)camel_object_new(camel_mh_summary_get_type ()); - - ((CamelFolderSummary *)o)->folder = folder; - - camel_local_summary_construct((CamelLocalSummary *)o, filename, mhdir, index); - return o; -} - -static char *mh_summary_next_uid_string(CamelFolderSummary *s) -{ - CamelMhSummary *mhs = (CamelMhSummary *)s; - CamelLocalSummary *cls = (CamelLocalSummary *)s; - int fd = -1; - guint32 uid; - char *name; - char *uidstr; - - /* if we are working to add an existing file, then use current_uid */ - if (mhs->priv->current_uid) { - uidstr = g_strdup(mhs->priv->current_uid); - /* tell the summary of this, so we always append numbers to the end */ - camel_folder_summary_set_uid(s, strtoul(uidstr, NULL, 10)+1); - } else { - /* else scan for one - and create it too, to make sure */ - do { - close(fd); - uid = camel_folder_summary_next_uid(s); - name = g_strdup_printf("%s/%u", cls->folder_path, uid); - /* O_EXCL isn't guaranteed, sigh. Oh well, bad luck, mh has problems anyway */ - fd = open(name, O_WRONLY|O_CREAT|O_EXCL, 0600); - g_free(name); - } while (fd == -1 && errno == EEXIST); - - close(fd); - - uidstr = g_strdup_printf("%u", uid); - } - - return uidstr; -} - -static int camel_mh_summary_add(CamelLocalSummary *cls, const char *name, int forceindex) -{ - CamelMhSummary *mhs = (CamelMhSummary *)cls; - char *filename = g_strdup_printf("%s/%s", cls->folder_path, name); - int fd; - CamelMimeParser *mp; - - d(printf("summarising: %s\n", name)); - - fd = open(filename, O_RDONLY); - if (fd == -1) { - g_warning ("Cannot summarise/index: %s: %s", filename, strerror (errno)); - g_free(filename); - return -1; - } - mp = camel_mime_parser_new(); - camel_mime_parser_scan_from(mp, FALSE); - camel_mime_parser_init_with_fd(mp, fd); - if (cls->index && (forceindex || !camel_index_has_name(cls->index, name))) { - d(printf("forcing indexing of message content\n")); - camel_folder_summary_set_index((CamelFolderSummary *)mhs, cls->index); - } else { - camel_folder_summary_set_index((CamelFolderSummary *)mhs, NULL); - } - mhs->priv->current_uid = (char *)name; - camel_folder_summary_add_from_parser((CamelFolderSummary *)mhs, mp); - camel_object_unref((CamelObject *)mp); - mhs->priv->current_uid = NULL; - camel_folder_summary_set_index((CamelFolderSummary *)mhs, NULL); - g_free(filename); - return 0; -} - -static void -remove_summary(char *key, CamelMessageInfo *info, CamelLocalSummary *cls) -{ - d(printf("removing message %s from summary\n", key)); - if (cls->index) - camel_index_delete_name(cls->index, camel_message_info_uid(info)); - camel_folder_summary_remove((CamelFolderSummary *)cls, info); - camel_message_info_free(info); -} - -static int -sort_uid_cmp(const void *ap, const void *bp) -{ - const CamelMessageInfo - *a = *((CamelMessageInfo **)ap), - *b = *((CamelMessageInfo **)bp); - const char - *auid = camel_message_info_uid(a), - *buid = camel_message_info_uid(b); - int aval = atoi(auid), bval = atoi(buid); - - return (aval < bval) ? -1 : (aval > bval) ? 1 : 0; -} - -static int -mh_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - DIR *dir; - struct dirent *d; - char *p, c; - CamelMessageInfo *info; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - GHashTable *left; - int i, count; - int forceindex; - - /* FIXME: Handle changeinfo */ - - d(printf("checking summary ...\n")); - - /* scan the directory, check for mail files not in the index, or index entries that - no longer exist */ - dir = opendir(cls->folder_path); - if (dir == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot open MH directory path: %s: %s"), - cls->folder_path, g_strerror (errno)); - return -1; - } - - /* keeps track of all uid's that have not been processed */ - left = g_hash_table_new(g_str_hash, g_str_equal); - count = camel_folder_summary_count((CamelFolderSummary *)cls); - forceindex = count == 0; - for (i=0;i<count;i++) { - info = camel_folder_summary_index((CamelFolderSummary *)cls, i); - if (info) { - g_hash_table_insert(left, (char *)camel_message_info_uid(info), info); - } - } - - while ( (d = readdir(dir)) ) { - /* FIXME: also run stat to check for regular file */ - p = d->d_name; - while ( (c = *p++) ) { - if (!isdigit(c)) - break; - } - if (c==0) { - info = camel_folder_summary_uid((CamelFolderSummary *)cls, d->d_name); - if (info == NULL || (cls->index && (!camel_index_has_name(cls->index, d->d_name)))) { - /* need to add this file to the summary */ - if (info != NULL) { - g_hash_table_remove(left, camel_message_info_uid(info)); - camel_folder_summary_remove((CamelFolderSummary *)cls, info); - camel_message_info_free(info); - } - camel_mh_summary_add(cls, d->d_name, forceindex); - } else { - const char *uid = camel_message_info_uid(info); - CamelMessageInfo *old = g_hash_table_lookup(left, uid); - - if (old) { - camel_message_info_free(old); - g_hash_table_remove(left, uid); - } - camel_message_info_free(info); - } - } - } - closedir(dir); - g_hash_table_foreach(left, (GHFunc)remove_summary, cls); - g_hash_table_destroy(left); - - /* sort the summary based on message number (uid), since the directory order is not useful */ - CAMEL_SUMMARY_LOCK(s, summary_lock); - qsort(s->messages->pdata, s->messages->len, sizeof(CamelMessageInfo *), sort_uid_cmp); - CAMEL_SUMMARY_UNLOCK(s, summary_lock); - - return 0; -} - -static int -mh_summary_sync_message(CamelLocalSummary *cls, CamelLocalMessageInfo *info, CamelException *ex) -{ - CamelMimeParser *mp; - const char *xev, *buffer; - int xevoffset; - int fd, outfd, len, outlen, ret=0; - char *name, *tmpname, *xevnew; - - name = g_strdup_printf("%s/%s", cls->folder_path, camel_message_info_uid(info)); - fd = open(name, O_RDWR); - if (fd == -1) - return -1; - - mp = camel_mime_parser_new(); - camel_mime_parser_init_with_fd(mp, fd); - if (camel_mime_parser_step(mp, 0, 0) != CAMEL_MIME_PARSER_STATE_EOF) { - xev = camel_mime_parser_header(mp, "X-Evolution", &xevoffset); - d(printf("xev = '%s'\n", xev)); - xevnew = camel_local_summary_encode_x_evolution(cls, info); - if (xev == NULL - || camel_local_summary_decode_x_evolution(cls, xev, NULL) == -1 - || strlen(xev)-1 != strlen(xevnew)) { - - d(printf("camel local summary_decode_xev = %d\n", camel_local_summary_decode_x_evolution(cls, xev, NULL))); - - /* need to write a new copy/unlink old */ - tmpname = g_strdup_printf("%s/.tmp.%d.%s", cls->folder_path, getpid(), camel_message_info_uid(info)); - d(printf("old xev was %d %s new xev is %d %s\n", strlen(xev), xev, strlen(xevnew), xevnew)); - d(printf("creating new message %s\n", tmpname)); - outfd = open(tmpname, O_CREAT|O_WRONLY|O_TRUNC, 0600); - if (outfd != -1) { - outlen = 0; - len = camel_local_summary_write_headers(outfd, camel_mime_parser_headers_raw(mp), xevnew, NULL, NULL); - if (len != -1) { - while (outlen != -1 && (len = camel_mime_parser_read(mp, &buffer, 10240)) > 0) { - d(printf("camel mime parser read, read %d bytes: %.*s\n", len, len, buffer)); - do { - outlen = write(outfd, buffer, len); - } while (outlen == -1 && errno == EINTR); - } - } - - d(printf("len = %d outlen = %d, renaming/finishing\n", len, outlen)); - if (close(outfd) == -1 - || len == -1 - || outlen == -1 - || rename(tmpname, name) == -1) { - unlink(tmpname); - ret = -1; - } - } else { - g_warning("sync can't create tmp file: %s", strerror (errno)); - } - g_free(tmpname); - } else { - d(printf("stamping in updated X-EV at %d\n", (int)xevoffset)); - /* else, we can just update the flags field */ - lseek(fd, xevoffset+strlen("X-Evolution: "), SEEK_SET); - do { - len = write(fd, xevnew, strlen(xevnew)); - } while (len == -1 && errno == EINTR); - if (len == -1) - ret = -1; - } - - g_free(xevnew); - } - - camel_object_unref((CamelObject *)mp); - g_free(name); - return ret; -} - -/* sync the summary file with the ondisk files */ -static int -mh_summary_sync(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changes, CamelException *ex) -{ - int count, i; - CamelLocalMessageInfo *info; - char *name; - const char *uid; - - d(printf("summary_sync(expunge=%s)\n", expunge?"true":"false")); - - /* we could probably get away without this ... but why not use it, esp if we're going to - be doing any significant io already */ - if (camel_local_summary_check(cls, changes, ex) == -1) - return -1; - - count = camel_folder_summary_count((CamelFolderSummary *)cls); - for (i=count-1;i>=0;i--) { - info = (CamelLocalMessageInfo *)camel_folder_summary_index((CamelFolderSummary *)cls, i); - g_assert(info); - if (expunge && (info->info.flags & CAMEL_MESSAGE_DELETED)) { - uid = camel_message_info_uid(info); - name = g_strdup_printf("%s/%s", cls->folder_path, uid); - d(printf("deleting %s\n", name)); - if (unlink(name) == 0 || errno==ENOENT) { - - /* FIXME: put this in folder_summary::remove()? */ - if (cls->index) - camel_index_delete_name(cls->index, (char *)uid); - - camel_folder_change_info_remove_uid(changes, uid); - camel_folder_summary_remove((CamelFolderSummary *)cls, (CamelMessageInfo *)info); - } - g_free(name); - } else if (info->info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV|CAMEL_MESSAGE_FOLDER_FLAGGED)) { - if (mh_summary_sync_message(cls, info, ex) != -1) { - info->info.flags &= 0xffff; - } else { - g_warning("Problem occured when trying to expunge, ignored"); - } - } - camel_message_info_free(info); - } - - return ((CamelLocalSummaryClass *)parent_class)->sync(cls, expunge, changes, ex); -} diff --git a/camel/providers/local/camel-mh-summary.h b/camel/providers/local/camel-mh-summary.h deleted file mode 100644 index d2fdcd1e4a..0000000000 --- a/camel/providers/local/camel-mh-summary.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * Authors: Not Zed <notzed@lostzed.mmc.com.au> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_MH_SUMMARY_H -#define _CAMEL_MH_SUMMARY_H - -#include "camel-local-summary.h" -#include <camel/camel-folder.h> -#include <camel/camel-exception.h> -#include <camel/camel-index.h> - -#define CAMEL_MH_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_mh_summary_get_type (), CamelMhSummary) -#define CAMEL_MH_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_mh_summary_get_type (), CamelMhSummaryClass) -#define CAMEL_IS_MH_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_mh_summary_get_type ()) - -typedef struct _CamelMhSummary CamelMhSummary; -typedef struct _CamelMhSummaryClass CamelMhSummaryClass; - -struct _CamelMhSummary { - CamelLocalSummary parent; - struct _CamelMhSummaryPrivate *priv; -}; - -struct _CamelMhSummaryClass { - CamelLocalSummaryClass parent_class; - - /* virtual methods */ - - /* signals */ -}; - -CamelType camel_mh_summary_get_type (void); -CamelMhSummary *camel_mh_summary_new(struct _CamelFolder *, const char *filename, const char *mhdir, CamelIndex *index); - -#endif /* ! _CAMEL_MH_SUMMARY_H */ - diff --git a/camel/providers/local/camel-spool-folder.c b/camel/providers/local/camel-spool-folder.c deleted file mode 100644 index c4c7da91b6..0000000000 --- a/camel/providers/local/camel-spool-folder.c +++ /dev/null @@ -1,217 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2001-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <sys/types.h> -#include <dirent.h> -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <fcntl.h> - -#include "camel-spool-folder.h" -#include "camel-spool-store.h" -#include "camel-stream-fs.h" -#include "camel-spool-summary.h" -#include "camel-data-wrapper.h" -#include "camel-mime-message.h" -#include "camel-stream-filter.h" -#include "camel-mime-filter-from.h" -#include "camel-exception.h" -#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))*/ - -static CamelFolderClass *parent_class = NULL; - -/* Returns the class for a CamelSpoolFolder */ -#define CSPOOLF_CLASS(so) CAMEL_SPOOL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CSPOOLS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static char *spool_get_full_path(CamelLocalFolder *lf, const char *toplevel_dir, const char *full_name); -static char *spool_get_meta_path(CamelLocalFolder *lf, const char *toplevel_dir, const char *full_name, const char *ext); -static CamelLocalSummary *spool_create_summary(CamelLocalFolder *lf, const char *path, const char *folder, CamelIndex *index); - -static int spool_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex); -static void spool_unlock(CamelLocalFolder *lf); - -static void spool_finalize(CamelObject * object); - -static void -camel_spool_folder_class_init(CamelSpoolFolderClass *klass) -{ - CamelLocalFolderClass *lklass = (CamelLocalFolderClass *)klass; - - parent_class = (CamelFolderClass *)camel_mbox_folder_get_type(); - - lklass->get_full_path = spool_get_full_path; - lklass->get_meta_path = spool_get_meta_path; - lklass->create_summary = spool_create_summary; - lklass->lock = spool_lock; - lklass->unlock = spool_unlock; -} - -static void -spool_init(gpointer object, gpointer klass) -{ - CamelSpoolFolder *spool_folder = object; - - spool_folder->lockid = -1; -} - -static void -spool_finalize(CamelObject * object) -{ - /*CamelSpoolFolder *spool_folder = CAMEL_SPOOL_FOLDER(object);*/ -} - -CamelType camel_spool_folder_get_type(void) -{ - static CamelType camel_spool_folder_type = CAMEL_INVALID_TYPE; - - if (camel_spool_folder_type == CAMEL_INVALID_TYPE) { - camel_spool_folder_type = camel_type_register(camel_mbox_folder_get_type(), "CamelSpoolFolder", - sizeof(CamelSpoolFolder), - sizeof(CamelSpoolFolderClass), - (CamelObjectClassInitFunc) camel_spool_folder_class_init, - NULL, - (CamelObjectInitFunc) spool_init, - (CamelObjectFinalizeFunc) spool_finalize); - } - - return camel_spool_folder_type; -} - -CamelFolder * -camel_spool_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex) -{ - CamelFolder *folder; - - d(printf("Creating spool folder: %s in %s\n", full_name, camel_local_store_get_toplevel_dir((CamelLocalStore *)parent_store))); - - folder = (CamelFolder *)camel_object_new(CAMEL_SPOOL_FOLDER_TYPE); - - if (parent_store->flags & CAMEL_STORE_FILTER_INBOX - && strcmp(full_name, "INBOX") == 0) - folder->folder_flags |= CAMEL_FOLDER_FILTER_RECENT; - flags &= ~CAMEL_STORE_FOLDER_BODY_INDEX; - - folder = (CamelFolder *)camel_local_folder_construct((CamelLocalFolder *)folder, parent_store, full_name, flags, ex); - if (folder) { - if (camel_url_get_param(((CamelService *)parent_store)->url, "xstatus")) - camel_mbox_summary_xstatus((CamelMboxSummary *)folder->summary, TRUE); - } - - return folder; -} - -static char * -spool_get_full_path(CamelLocalFolder *lf, const char *toplevel_dir, const char *full_name) -{ - return g_strdup_printf ("%s/%s", toplevel_dir, full_name); -} - -static char * -spool_get_meta_path(CamelLocalFolder *lf, const char *toplevel_dir, const char *full_name, const char *ext) -{ - CamelService *service = (CamelService *)((CamelFolder *)lf)->parent_store; - char *root = camel_session_get_storage_path(service->session, service, NULL); - char *path; - - if (root == NULL) - return NULL; - - - camel_mkdir(root, 0777); - path = g_strdup_printf("%s/%s%s", root, full_name, ext); - g_free(root); - - return path; -} - -static CamelLocalSummary * -spool_create_summary(CamelLocalFolder *lf, const char *path, const char *folder, CamelIndex *index) -{ - return (CamelLocalSummary *)camel_spool_summary_new((CamelFolder *)lf, folder); -} - -static int -spool_lock(CamelLocalFolder *lf, CamelLockType type, CamelException *ex) -{ - int retry = 0; - CamelMboxFolder *mf = (CamelMboxFolder *)lf; - CamelSpoolFolder *sf = (CamelSpoolFolder *)lf; - - mf->lockfd = open(lf->folder_path, O_RDWR, 0); - if (mf->lockfd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot create folder lock on %s: %s"), - lf->folder_path, g_strerror (errno)); - return -1; - } - - while (retry < CAMEL_LOCK_RETRY) { - if (retry > 0) - sleep(CAMEL_LOCK_DELAY); - - camel_exception_clear(ex); - - if (camel_lock_fcntl(mf->lockfd, type, ex) == 0) { - if (camel_lock_flock(mf->lockfd, type, ex) == 0) { - if ((sf->lockid = camel_lock_helper_lock(lf->folder_path, ex)) != -1) - return 0; - camel_unlock_flock(mf->lockfd); - } - camel_unlock_fcntl(mf->lockfd); - } - retry++; - } - - close (mf->lockfd); - mf->lockfd = -1; - - return -1; -} - -static void -spool_unlock(CamelLocalFolder *lf) -{ - CamelMboxFolder *mf = (CamelMboxFolder *)lf; - CamelSpoolFolder *sf = (CamelSpoolFolder *)lf; - - camel_lock_helper_unlock(sf->lockid); - sf->lockid = -1; - camel_unlock_flock(mf->lockfd); - camel_unlock_fcntl(mf->lockfd); - - close(mf->lockfd); - mf->lockfd = -1; -} diff --git a/camel/providers/local/camel-spool-folder.h b/camel/providers/local/camel-spool-folder.h deleted file mode 100644 index e778cdecf7..0000000000 --- a/camel/providers/local/camel-spool-folder.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Author: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2001 Ximian Inc (www.ximian.com/) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_SPOOL_FOLDER_H -#define CAMEL_SPOOL_FOLDER_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-mbox-folder.h" -#include <camel/camel-folder-search.h> -#include <camel/camel-index.h> -#include "camel-spool-summary.h" -#include "camel-lock.h" - -/* #include "camel-store.h" */ - -#define CAMEL_SPOOL_FOLDER_TYPE (camel_spool_folder_get_type ()) -#define CAMEL_SPOOL_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SPOOL_FOLDER_TYPE, CamelSpoolFolder)) -#define CAMEL_SPOOL_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SPOOL_FOLDER_TYPE, CamelSpoolFolderClass)) -#define CAMEL_IS_SPOOL_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_SPOOL_FOLDER_TYPE)) - -typedef struct { - CamelMboxFolder parent; - - struct _CamelSpoolFolderPrivate *priv; - - int lockid; /* lock id for dot locking */ -} CamelSpoolFolder; - -typedef struct { - CamelMboxFolderClass parent_class; -} CamelSpoolFolderClass; - -/* Standard Camel function */ -CamelType camel_spool_folder_get_type(void); - -CamelFolder *camel_spool_folder_new(CamelStore *parent_store, const char *full_name, guint32 flags, CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SPOOL_FOLDER_H */ diff --git a/camel/providers/local/camel-spool-store.c b/camel/providers/local/camel-spool-store.c deleted file mode 100644 index 3dc21886c8..0000000000 --- a/camel/providers/local/camel-spool-store.c +++ /dev/null @@ -1,466 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2001 Ximian Inc (www.ximian.com/) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_ALLOCA_H -#include <alloca.h> -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> -#include <stdio.h> -#include <dirent.h> - -#include "camel-spool-store.h" -#include "camel-spool-folder.h" -#include "camel-exception.h" -#include "camel-url.h" -#include "camel-private.h" -#include "camel-i18n.h" - -#define d(x) - -/* Returns the class for a CamelSpoolStore */ -#define CSPOOLS_CLASS(so) CAMEL_SPOOL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static void construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex); -static CamelFolder *get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex); -static char *get_name(CamelService *service, gboolean brief); -static CamelFolder *get_inbox (CamelStore *store, CamelException *ex); -static void rename_folder(CamelStore *store, const char *old_name, const char *new_name, CamelException *ex); -static CamelFolderInfo *get_folder_info (CamelStore *store, const char *top, guint32 flags, CamelException *ex); -static void free_folder_info (CamelStore *store, CamelFolderInfo *fi); - -static void delete_folder(CamelStore *store, const char *folder_name, CamelException *ex); -static void rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex); - -static CamelStoreClass *parent_class = NULL; - -static void -camel_spool_store_class_init (CamelSpoolStoreClass *camel_spool_store_class) -{ - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_spool_store_class); - CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS (camel_spool_store_class); - - parent_class = CAMEL_STORE_CLASS(camel_mbox_store_get_type()); - - /* virtual method overload */ - camel_service_class->construct = construct; - camel_service_class->get_name = get_name; - camel_store_class->get_folder = get_folder; - camel_store_class->get_inbox = get_inbox; - camel_store_class->get_folder_info = get_folder_info; - camel_store_class->free_folder_info = free_folder_info; - - camel_store_class->delete_folder = delete_folder; - camel_store_class->rename_folder = rename_folder; -} - -CamelType -camel_spool_store_get_type (void) -{ - static CamelType camel_spool_store_type = CAMEL_INVALID_TYPE; - - if (camel_spool_store_type == CAMEL_INVALID_TYPE) { - camel_spool_store_type = camel_type_register (camel_mbox_store_get_type(), "CamelSpoolStore", - sizeof (CamelSpoolStore), - sizeof (CamelSpoolStoreClass), - (CamelObjectClassInitFunc) camel_spool_store_class_init, - NULL, - NULL, - NULL); - } - - return camel_spool_store_type; -} - -static void -construct (CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex) -{ - struct stat st; - - d(printf("constructing store of type %s '%s:%s'\n", - camel_type_to_name(((CamelObject *)service)->s.type), url->protocol, url->path)); - - CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); - if (camel_exception_is_set (ex)) - return; - - if (service->url->path[0] != '/') { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Store root %s is not an absolute path"), service->url->path); - return; - } - - if (stat(service->url->path, &st) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Spool `%s' cannot be opened: %s"), - service->url->path, g_strerror (errno)); - return; - } - - if (S_ISREG(st.st_mode)) - ((CamelSpoolStore *)service)->type = CAMEL_SPOOL_STORE_MBOX; - else if (S_ISDIR(st.st_mode)) - /* we could check here for slight variations */ - ((CamelSpoolStore *)service)->type = CAMEL_SPOOL_STORE_ELM; - else { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Spool `%s' is not a regular file or directory"), - service->url->path); - return; - } -} - -static CamelFolder * -get_folder(CamelStore * store, const char *folder_name, guint32 flags, CamelException * ex) -{ - CamelFolder *folder = NULL; - struct stat st; - char *name; - - d(printf("opening folder %s on path %s\n", folder_name, path)); - - /* we only support an 'INBOX' in mbox mode */ - if (((CamelSpoolStore *)store)->type == CAMEL_SPOOL_STORE_MBOX) { - if (strcmp(folder_name, "INBOX") != 0) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Folder `%s/%s' does not exist."), - ((CamelService *)store)->url->path, folder_name); - } else { - folder = camel_spool_folder_new(store, folder_name, flags, ex); - } - } else { - name = g_strdup_printf("%s%s", CAMEL_LOCAL_STORE(store)->toplevel_dir, folder_name); - if (stat(name, &st) == -1) { - if (errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open folder `%s':\n%s"), - folder_name, g_strerror (errno)); - } else if ((flags & CAMEL_STORE_FOLDER_CREATE) == 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Folder `%s' does not exist."), - folder_name); - } else { - if (creat (name, 0600) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create folder `%s':\n%s"), - folder_name, g_strerror (errno)); - } else { - folder = camel_spool_folder_new(store, folder_name, flags, ex); - } - } - } else if (!S_ISREG(st.st_mode)) { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("`%s' is not a mailbox file."), name); - } else { - folder = camel_spool_folder_new(store, folder_name, flags, ex); - } - g_free(name); - } - - return folder; -} - -static CamelFolder * -get_inbox(CamelStore *store, CamelException *ex) -{ - if (((CamelSpoolStore *)store)->type == CAMEL_SPOOL_STORE_MBOX) - return get_folder (store, "INBOX", CAMEL_STORE_FOLDER_CREATE, ex); - else { - camel_exception_setv(ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, - _("Store does not support an INBOX")); - return NULL; - } -} - -static char * -get_name (CamelService *service, gboolean brief) -{ - if (brief) - return g_strdup(service->url->path); - else - return g_strdup_printf(((CamelSpoolStore *)service)->type == CAMEL_SPOOL_STORE_MBOX? - _("Spool mail file %s"):_("Spool folder tree %s"), service->url->path); -} - -/* default implementation, rename all */ -static void -rename_folder(CamelStore *store, const char *old, const char *new, CamelException *ex) -{ - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Spool folders cannot be renamed")); -} - -/* default implementation, only delete metadata */ -static void -delete_folder(CamelStore *store, const char *folder_name, CamelException *ex) -{ - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Spool folders cannot be deleted")); -} - -static void free_folder_info (CamelStore *store, CamelFolderInfo *fi) -{ - if (fi) { - g_free(fi->uri); - g_free(fi->name); - g_free(fi->full_name); - g_free(fi); - } -} - -/* partially copied from mbox */ -static void -spool_fill_fi(CamelStore *store, CamelFolderInfo *fi, guint32 flags) -{ - CamelFolder *folder; - - fi->unread = -1; - fi->total = -1; - folder = camel_object_bag_get(store->folders, fi->full_name); - if (folder) { - if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0) - camel_folder_refresh_info(folder, NULL); - fi->unread = camel_folder_get_unread_message_count(folder); - fi->total = camel_folder_get_message_count(folder); - camel_object_unref(folder); - } -} - -static CamelFolderInfo * -spool_new_fi(CamelStore *store, CamelFolderInfo *parent, CamelFolderInfo **fip, const char *full, guint32 flags) -{ - CamelFolderInfo *fi; - const char *name; - CamelURL *url; - - name = strrchr(full, '/'); - if (name) - name++; - else - name = full; - - fi = g_malloc0(sizeof(*fi)); - url = camel_url_copy(((CamelService *)store)->url); - camel_url_set_fragment(url, full); - fi->uri = camel_url_to_string(url, 0); - camel_url_free(url); - fi->full_name = g_strdup(full); - fi->name = g_strdup(name); - fi->unread = -1; - fi->total = -1; - fi->flags = flags; - - fi->parent = parent; - fi->next = *fip; - *fip = fi; - - d(printf("Adding spoold info: '%s' '%s' '%s' '%s'\n", fi->path, fi->name, fi->full_name, fi->url)); - - return fi; -} - -/* used to find out where we've visited already */ -struct _inode { - dev_t dnode; - ino_t inode; -}; - -/* returns number of records found at or below this level */ -static int scan_dir(CamelStore *store, GHashTable *visited, char *root, const char *path, guint32 flags, CamelFolderInfo *parent, CamelFolderInfo **fip, CamelException *ex) -{ - DIR *dir; - struct dirent *d; - char *name, *tmp, *fname; - CamelFolderInfo *fi = NULL; - struct stat st; - CamelFolder *folder; - char from[80]; - FILE *fp; - - d(printf("checking dir '%s' part '%s' for mbox content\n", root, path)); - - /* look for folders matching the right structure, recursively */ - if (path) { - name = alloca(strlen(root) + strlen(path) + 2); - sprintf(name, "%s/%s", root, path); - } else - name = root; - - if (stat(name, &st) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not scan folder `%s': %s"), - name, g_strerror (errno)); - } else if (S_ISREG(st.st_mode)) { - /* incase we start scanning from a file. messy duplication :-/ */ - if (path) { - fi = spool_new_fi(store, parent, fip, path, CAMEL_FOLDER_NOINFERIORS|CAMEL_FOLDER_NOCHILDREN); - spool_fill_fi(store, fi, flags); - } - return 0; - } - - dir = opendir(name); - if (dir == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not scan folder `%s': %s"), - name, g_strerror (errno)); - return -1; - } - - if (path != NULL) { - fi = spool_new_fi(store, parent, fip, path, CAMEL_FOLDER_NOSELECT); - fip = &fi->child; - parent = fi; - } - - while ( (d = readdir(dir)) ) { - if (strcmp(d->d_name, ".") == 0 - || strcmp(d->d_name, "..") == 0) - continue; - - tmp = g_strdup_printf("%s/%s", name, d->d_name); - if (stat(tmp, &st) == 0) { - if (path) - fname = g_strdup_printf("%s/%s", path, d->d_name); - else - fname = g_strdup(d->d_name); - - if (S_ISREG(st.st_mode)) { - int isfolder = FALSE; - - /* first, see if we already have it open */ - folder = camel_object_bag_get(store->folders, fname); - if (folder == NULL) { - fp = fopen(tmp, "r"); - if (fp != NULL) { - isfolder = (st.st_size == 0 - || (fgets(from, sizeof(from), fp) != NULL - && strncmp(from, "From ", 5) == 0)); - fclose(fp); - } - } - - if (folder != NULL || isfolder) { - fi = spool_new_fi(store, parent, fip, fname, CAMEL_FOLDER_NOINFERIORS|CAMEL_FOLDER_NOCHILDREN); - spool_fill_fi(store, fi, flags); - } - if (folder) - camel_object_unref(folder); - - } else if (S_ISDIR(st.st_mode)) { - struct _inode in = { st.st_dev, st.st_ino }; - - /* see if we've visited already */ - if (g_hash_table_lookup(visited, &in) == NULL) { - struct _inode *inew = g_malloc(sizeof(*inew)); - - *inew = in; - g_hash_table_insert(visited, inew, inew); - - if (scan_dir(store, visited, root, fname, flags, parent, fip, ex) == -1) { - g_free(tmp); - g_free(fname); - closedir(dir); - return -1; - } - } - } - g_free(fname); - - } - g_free(tmp); - } - closedir(dir); - - return 0; -} - -static guint inode_hash(const void *d) -{ - const struct _inode *v = d; - - return v->inode ^ v->dnode; -} - -static gboolean inode_equal(const void *a, const void *b) -{ - const struct _inode *v1 = a, *v2 = b; - - return v1->inode == v2->inode && v1->dnode == v2->dnode; -} - -static void inode_free(void *k, void *v, void *d) -{ - g_free(k); -} - -static CamelFolderInfo * -get_folder_info_elm(CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - CamelFolderInfo *fi = NULL; - GHashTable *visited; - - visited = g_hash_table_new(inode_hash, inode_equal); - - if (scan_dir(store, visited, ((CamelService *)store)->url->path, top, flags, NULL, &fi, ex) == -1 && fi != NULL) { - camel_store_free_folder_info_full(store, fi); - fi = NULL; - } - - g_hash_table_foreach(visited, inode_free, NULL); - g_hash_table_destroy(visited); - - return fi; -} - -static CamelFolderInfo * -get_folder_info_mbox(CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - CamelFolderInfo *fi = NULL, *fip = NULL; - - if (top == NULL || strcmp(top, "INBOX") == 0) { - fi = spool_new_fi(store, NULL, &fip, "INBOX", CAMEL_FOLDER_NOINFERIORS|CAMEL_FOLDER_NOCHILDREN|CAMEL_FOLDER_SYSTEM); - g_free(fi->name); - fi->name = g_strdup(_("Inbox")); - spool_fill_fi(store, fi, flags); - } - - return fi; -} - -static CamelFolderInfo * -get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - if (((CamelSpoolStore *)store)->type == CAMEL_SPOOL_STORE_MBOX) - return get_folder_info_mbox(store, top, flags, ex); - else - return get_folder_info_elm(store, top, flags, ex); -} diff --git a/camel/providers/local/camel-spool-store.h b/camel/providers/local/camel-spool-store.h deleted file mode 100644 index 1e1753481b..0000000000 --- a/camel/providers/local/camel-spool-store.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2001 Ximian Inc (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_SPOOL_STORE_H -#define CAMEL_SPOOL_STORE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-mbox-store.h" - -#define CAMEL_SPOOL_STORE_TYPE (camel_spool_store_get_type ()) -#define CAMEL_SPOOL_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SPOOL_STORE_TYPE, CamelSpoolStore)) -#define CAMEL_SPOOL_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SPOOL_STORE_TYPE, CamelSpoolStoreClass)) -#define CAMEL_IS_SPOOL_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_SPOOL_STORE_TYPE)) - -typedef enum _camel_spool_store_t { - CAMEL_SPOOL_STORE_MBOX, /* a single mbox */ - CAMEL_SPOOL_STORE_ELM, /* elm/pine/etc tree of mbox files in folders */ -} camel_spool_store_t; - -typedef struct { - CamelMboxStore parent_object; - - camel_spool_store_t type; -} CamelSpoolStore; - - - -typedef struct { - CamelMboxStoreClass parent_class; - -} CamelSpoolStoreClass; - - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_spool_store_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SPOOL_STORE_H */ - - diff --git a/camel/providers/local/camel-spool-summary.c b/camel/providers/local/camel-spool-summary.c deleted file mode 100644 index c8e074ae99..0000000000 --- a/camel/providers/local/camel-spool-summary.c +++ /dev/null @@ -1,347 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Copyright (C) 2001 Ximian Inc. (www.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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/uio.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> - -#include <ctype.h> - -#include "camel-spool-summary.h" -#include "camel-mime-message.h" -#include "camel-file-utils.h" -#include "camel-operation.h" -#include "camel-i18n.h" - -#define io(x) -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ - -#define CAMEL_SPOOL_SUMMARY_VERSION (0x400) - -static int spool_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex); -static int spool_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex); - -static int spool_summary_sync_full(CamelMboxSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex); - -static void camel_spool_summary_class_init (CamelSpoolSummaryClass *klass); -static void camel_spool_summary_init (CamelSpoolSummary *obj); -static void camel_spool_summary_finalise (CamelObject *obj); - -static CamelFolderSummaryClass *camel_spool_summary_parent; - -CamelType -camel_spool_summary_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_mbox_summary_get_type(), "CamelSpoolSummary", - sizeof (CamelSpoolSummary), - sizeof (CamelSpoolSummaryClass), - (CamelObjectClassInitFunc) camel_spool_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_spool_summary_init, - (CamelObjectFinalizeFunc) camel_spool_summary_finalise); - } - - return type; -} - -static void -camel_spool_summary_class_init(CamelSpoolSummaryClass *klass) -{ - CamelLocalSummaryClass *lklass = (CamelLocalSummaryClass *)klass; - CamelMboxSummaryClass *mklass = (CamelMboxSummaryClass *)klass; - - camel_spool_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS(camel_mbox_summary_get_type()); - - lklass->load = spool_summary_load; - lklass->check = spool_summary_check; - - mklass->sync_full = spool_summary_sync_full; -} - -static void -camel_spool_summary_init(CamelSpoolSummary *obj) -{ - struct _CamelFolderSummary *s = (CamelFolderSummary *)obj; - - /* message info size is from mbox parent */ - - /* and a unique file version */ - s->version += CAMEL_SPOOL_SUMMARY_VERSION; -} - -static void -camel_spool_summary_finalise(CamelObject *obj) -{ - /*CamelSpoolSummary *mbs = CAMEL_SPOOL_SUMMARY(obj);*/ -} - -CamelSpoolSummary * -camel_spool_summary_new(struct _CamelFolder *folder, const char *mbox_name) -{ - CamelSpoolSummary *new = (CamelSpoolSummary *)camel_object_new(camel_spool_summary_get_type()); - - ((CamelFolderSummary *)new)->folder = folder; - - camel_local_summary_construct((CamelLocalSummary *)new, NULL, mbox_name, NULL); - return new; -} - -static int -spool_summary_load(CamelLocalSummary *cls, int forceindex, CamelException *ex) -{ - g_warning("spool summary - not loading anything\n"); - return 0; -} - -/* perform a full sync */ -static int -spool_summary_sync_full(CamelMboxSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - int fd = -1, fdout = -1; - char *tmpname = NULL; - char *buffer, *p; - off_t spoollen, outlen; - int size, sizeout; - struct stat st; - guint32 flags = (expunge?1:0); - - d(printf("performing full summary/sync\n")); - - camel_operation_start(NULL, _("Storing folder")); - - fd = open(((CamelLocalSummary *)cls)->folder_path, O_RDWR); - if (fd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open file: %s: %s"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno)); - camel_operation_end(NULL); - return -1; - } - -#ifdef HAVE_MKSTEMP - tmpname = alloca (64); - sprintf (tmpname, "/tmp/spool.camel.XXXXXX"); - fdout = mkstemp (tmpname); -#else -#warning "Your system has no mkstemp(3), spool updating may be insecure" - tmpname = alloca (L_tmpnam); - tmpnam (tmpname); - fdout = open (tmpname, O_RDWR|O_CREAT|O_EXCL, 0600); -#endif - d(printf("Writing tmp file to %s\n", tmpname)); - if (fdout == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot open temporary mailbox: %s"), - g_strerror (errno)); - goto error; - } - - if (camel_mbox_summary_sync_mbox((CamelMboxSummary *)cls, flags, changeinfo, fd, fdout, ex) == -1) - goto error; - - - /* sync out content */ - if (fsync(fdout) == -1) { - g_warning("Cannot sync temporary folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync temporary folder %s: %s"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno)); - goto error; - } - - /* see if we can write this much to the spool file */ - if (fstat(fd, &st) == -1) { - g_warning("Cannot sync temporary folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync temporary folder %s: %s"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno)); - goto error; - } - spoollen = st.st_size; - - if (fstat(fdout, &st) == -1) { - g_warning("Cannot sync temporary folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync temporary folder %s: %s"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno)); - goto error; - } - outlen = st.st_size; - - /* I think this is the right way to do this - checking that the file will fit the new data */ - if (outlen>0 - && (lseek(fd, outlen-1, SEEK_SET) == -1 - || write(fd, "", 1) != 1 - || fsync(fd) == -1 - || lseek(fd, 0, SEEK_SET) == -1 - || lseek(fdout, 0, SEEK_SET) == -1)) { - g_warning("Cannot sync spool folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync spool folder %s: %s"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno)); - /* incase we ran out of room, remove any trailing space first */ - ftruncate(fd, spoollen); - goto error; - } - - - /* now copy content back */ - buffer = g_malloc(8192); - size = 1; - while (size>0) { - do { - size = read(fdout, buffer, 8192); - } while (size == -1 && errno == EINTR); - - if (size > 0) { - p = buffer; - do { - sizeout = write(fd, p, size); - if (sizeout > 0) { - p+= sizeout; - size -= sizeout; - } - } while ((sizeout == -1 && errno == EINTR) && size > 0); - size = sizeout; - } - - if (size == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync spool folder %s: %s\n" - "Folder may be corrupt, copy saved in `%s'"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno), tmpnam); - /* so we dont delete it */ - close(fdout); - tmpname = NULL; - fdout = -1; - g_free(buffer); - goto error; - } - } - - g_free(buffer); - - d(printf("Closing folders\n")); - - if (ftruncate(fd, outlen) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync spool folder %s: %s\n" - "Folder may be corrupt, copy saved in `%s'"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno), tmpnam); - close(fdout); - tmpname = NULL; - fdout = -1; - goto error; - } - - if (close(fd) == -1) { - g_warning("Cannot close source folder: %s", strerror (errno)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not sync spool folder %s: %s\n" - "Folder may be corrupt, copy saved in `%s'"), - ((CamelLocalSummary *)cls)->folder_path, - g_strerror (errno), tmpnam); - close(fdout); - tmpname = NULL; - fdout = -1; - fd = -1; - goto error; - } - - close(fdout); - unlink(tmpname); - - camel_operation_end(NULL); - - return 0; - error: - if (fd != -1) - close(fd); - - if (fdout != -1) - close(fdout); - - if (tmpname) - unlink(tmpname); - - camel_operation_end(NULL); - - return -1; -} - -static int -spool_summary_check(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, CamelException *ex) -{ - int i, work, count; - struct stat st; - CamelFolderSummary *s = (CamelFolderSummary *)cls; - - if (((CamelLocalSummaryClass *)camel_spool_summary_parent)->check(cls, changeinfo, ex) == -1) - return -1; - - /* check to see if we need to copy/update the file; missing xev headers prompt this */ - work = FALSE; - count = camel_folder_summary_count(s); - for (i=0;!work && i<count; i++) { - CamelMboxMessageInfo *info = (CamelMboxMessageInfo *)camel_folder_summary_index(s, i); - g_assert(info); - work = (info->info.info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV)) != 0; - camel_message_info_free((CamelMessageInfo *)info); - } - - /* if we do, then write out the headers using sync_full, etc */ - if (work) { - d(printf("Have to add new headers, re-syncing from the start to accomplish this\n")); - if (((CamelMboxSummaryClass *)((CamelObject *)cls)->klass)->sync_full((CamelMboxSummary *)cls, FALSE, changeinfo, ex) == -1) - return -1; - - if (stat(cls->folder_path, &st) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Unknown error: %s"), - g_strerror (errno)); - return -1; - } - - ((CamelMboxSummary *)cls)->folder_size = st.st_size; - ((CamelFolderSummary *)cls)->time = st.st_mtime; - } - - return 0; -} diff --git a/camel/providers/local/camel-spool-summary.h b/camel/providers/local/camel-spool-summary.h deleted file mode 100644 index 2849c8cc20..0000000000 --- a/camel/providers/local/camel-spool-summary.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2001 Ximian Inc. (www.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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_SPOOL_SUMMARY_H -#define _CAMEL_SPOOL_SUMMARY_H - -#include <camel/camel-folder-summary.h> -#include <camel/camel-folder.h> -#include <camel/camel-exception.h> -#include <camel/camel-index.h> -#include "camel-mbox-summary.h" - -#define CAMEL_SPOOL_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_spool_summary_get_type (), CamelSpoolSummary) -#define CAMEL_SPOOL_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_spool_summary_get_type (), CamelSpoolSummaryClass) -#define CAMEL_IS_SPOOL_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_spool_summary_get_type ()) - -typedef struct _CamelSpoolSummary CamelSpoolSummary; -typedef struct _CamelSpoolSummaryClass CamelSpoolSummaryClass; - -struct _CamelSpoolSummary { - CamelMboxSummary parent; - -}; - -struct _CamelSpoolSummaryClass { - CamelMboxSummaryClass parent_class; -}; - -CamelType camel_spool_summary_get_type (void); -void camel_spool_summary_construct (CamelSpoolSummary *new, const char *filename, const char *spool_name, CamelIndex *index); - -/* create the summary, in-memory only */ -CamelSpoolSummary *camel_spool_summary_new(struct _CamelFolder *, const char *filename); - -/* load/check the summary */ -int camel_spool_summary_load(CamelSpoolSummary *cls, int forceindex, CamelException *ex); -/* check for new/removed messages */ -int camel_spool_summary_check(CamelSpoolSummary *cls, CamelFolderChangeInfo *, CamelException *ex); -/* perform a folder sync or expunge, if needed */ -int camel_spool_summary_sync(CamelSpoolSummary *cls, gboolean expunge, CamelFolderChangeInfo *, CamelException *ex); -/* add a new message to the summary */ -CamelMessageInfo *camel_spool_summary_add(CamelSpoolSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, CamelException *ex); - -/* generate an X-Evolution header line */ -char *camel_spool_summary_encode_x_evolution(CamelSpoolSummary *cls, const CamelMessageInfo *info); -int camel_spool_summary_decode_x_evolution(CamelSpoolSummary *cls, const char *xev, CamelMessageInfo *info); - -/* utility functions - write headers to a file with optional X-Evolution header */ -int camel_spool_summary_write_headers(int fd, struct _camel_header_raw *header, char *xevline); - -#endif /* ! _CAMEL_SPOOL_SUMMARY_H */ - diff --git a/camel/providers/local/libcamellocal.urls b/camel/providers/local/libcamellocal.urls deleted file mode 100644 index 207c19a98f..0000000000 --- a/camel/providers/local/libcamellocal.urls +++ /dev/null @@ -1,4 +0,0 @@ -mh -mbox -maildir -spool diff --git a/camel/providers/nntp/.cvsignore b/camel/providers/nntp/.cvsignore deleted file mode 100644 index 2fbeab8712..0000000000 --- a/camel/providers/nntp/.cvsignore +++ /dev/null @@ -1,12 +0,0 @@ -.deps -Makefile -Makefile.in -.libs -.deps -*.lo -*.la -test-newsrc -*.bb -*.bbg -*.da -*.gcov diff --git a/camel/providers/nntp/Makefile.am b/camel/providers/nntp/Makefile.am deleted file mode 100644 index bc8b82ccad..0000000000 --- a/camel/providers/nntp/Makefile.am +++ /dev/null @@ -1,36 +0,0 @@ -## Process this file with automake to produce Makefile.in - -camel_provider_LTLIBRARIES = libcamelnntp.la -camel_provider_DATA = libcamelnntp.urls - -INCLUDES = -I../.. \ - -I$(top_srcdir) \ - -I$(top_srcdir)/camel \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/e-util \ - -I$(top_srcdir) \ - $(CAMEL_CFLAGS) \ - $(GNOME_INCLUDEDIR) \ - $(GTK_INCLUDEDIR) \ - -DG_LOG_DOMAIN=\"camel-nntp-provider\" - -libcamelnntp_la_SOURCES = \ - camel-nntp-provider.c \ - camel-nntp-store.c \ - camel-nntp-folder.c \ - camel-nntp-stream.c \ - camel-nntp-summary.c \ - camel-nntp-store-summary.c - -noinst_HEADERS = \ - camel-nntp-store.h \ - camel-nntp-folder.h \ - camel-nntp-resp-codes.h \ - camel-nntp-stream.h \ - camel-nntp-summary.h \ - camel-nntp-store-summary.h \ - camel-nntp-private.h - -libcamelnntp_la_LDFLAGS = -avoid-version -module - -EXTRA_DIST = libcamelnntp.urls diff --git a/camel/providers/nntp/camel-nntp-auth.c b/camel/providers/nntp/camel-nntp-auth.c deleted file mode 100644 index f8d3a62e27..0000000000 --- a/camel/providers/nntp/camel-nntp-auth.c +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-auth.c : authentication for nntp */ - -/* - * - * Copyright (C) 2000 Ximian, Inc. <toshok@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include <camel-nntp-auth.h> -#include <camel-nntp-store.h> -#include <camel-nntp-resp-codes.h> -#include <camel-exception.h> -#include <camel-session.h> - -int -camel_nntp_auth_authenticate (CamelNNTPStore *store, CamelException *ex) -{ - CamelService *service = CAMEL_SERVICE (store); - CamelSession *session = camel_service_get_session (service); - int resp; - - if (!service->url->authmech && !service->url->passwd) { - gchar *prompt; - - prompt = g_strdup_printf (_("Please enter the NNTP password for %s@%s"), - service->url->user, service->url->host); - service->url->passwd = - camel_session_get_password (session, prompt, - TRUE, service, "password", ex); - g_free (prompt); - - if (!service->url->passwd) { - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - "You didn\'t enter a password."); - resp = 666; - goto done; - } - } - - /* first send username */ - resp = camel_nntp_command (store, ex, NULL, "AUTHINFO USER %s", service->url->user); - - if (resp == NNTP_AUTH_REJECTED) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Server rejected username")); - goto done; - - } - else if (resp != NNTP_AUTH_CONTINUE) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Failed to send username to server")); - goto done; - } - - /* then send the username if the server asks for it */ - resp = camel_nntp_command (store, ex, NULL, "AUTHINFO PASS %s", service->url->passwd); - - if (resp == NNTP_AUTH_REJECTED) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Server rejected username/password")); - goto done; - } - - done: - - if (service->url->passwd) { - /* let's be paranoid */ - memset (service->url->passwd, 0, strlen (service->url->passwd)); - g_free (service->url->passwd); - service->url->passwd = NULL; - } - return resp; -} diff --git a/camel/providers/nntp/camel-nntp-auth.h b/camel/providers/nntp/camel-nntp-auth.h deleted file mode 100644 index fc96cf6a4e..0000000000 --- a/camel/providers/nntp/camel-nntp-auth.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-auth.h : authentication for nntp */ - -/* - * - * Author : Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 1999 Ximian . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_NNTP_AUTH_H -#define CAMEL_NNTP_AUTH_H 1 - -#include <camel-nntp-store.h> - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -int camel_nntp_auth_authenticate (CamelNNTPStore *store, CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_NNTP_AUTH_H */ diff --git a/camel/providers/nntp/camel-nntp-folder.c b/camel/providers/nntp/camel-nntp-folder.c deleted file mode 100644 index de0f4cd222..0000000000 --- a/camel/providers/nntp/camel-nntp-folder.c +++ /dev/null @@ -1,533 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-folder.c : Class for a news folder - * - * Authors : Chris Toshok <toshok@ximian.com> - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2001-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <dirent.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> - -#include "camel/camel-file-utils.h" -#include "camel/camel-stream-mem.h" -#include "camel/camel-data-wrapper.h" -#include "camel/camel-mime-message.h" -#include "camel/camel-folder-search.h" -#include "camel/camel-exception.h" -#include "camel/camel-session.h" -#include "camel/camel-data-cache.h" - -#include "camel/camel-mime-filter-crlf.h" -#include "camel/camel-stream-filter.h" -#include "camel/camel-mime-message.h" -#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" -#include "camel-nntp-store.h" -#include "camel-nntp-folder.h" -#include "camel-nntp-store.h" -#include "camel-nntp-private.h" - -static CamelFolderClass *folder_class = NULL; -static CamelDiscoFolderClass *parent_class = NULL; - -/* Returns the class for a CamelNNTPFolder */ -#define CNNTPF_CLASS(so) CAMEL_NNTP_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CNNTPS_CLASS(so) CAMEL_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -void -camel_nntp_folder_selected(CamelNNTPFolder *folder, char *line, CamelException *ex) -{ - camel_nntp_summary_check((CamelNNTPSummary *)((CamelFolder *)folder)->summary, - (CamelNNTPStore *)((CamelFolder *)folder)->parent_store, - line, folder->changes, ex); -} - -static void -nntp_folder_refresh_info_online (CamelFolder *folder, CamelException *ex) -{ - CamelNNTPStore *nntp_store; - CamelFolderChangeInfo *changes = NULL; - CamelNNTPFolder *nntp_folder; - char *line; - - nntp_store = (CamelNNTPStore *) folder->parent_store; - nntp_folder = (CamelNNTPFolder *) folder; - - CAMEL_SERVICE_LOCK(nntp_store, connect_lock); - - camel_nntp_command(nntp_store, ex, nntp_folder, &line, NULL); - - if (camel_folder_change_info_changed(nntp_folder->changes)) { - changes = nntp_folder->changes; - nntp_folder->changes = camel_folder_change_info_new(); - } - - CAMEL_SERVICE_UNLOCK(nntp_store, connect_lock); - - if (changes) { - camel_object_trigger_event ((CamelObject *) folder, "folder_changed", changes); - camel_folder_change_info_free (changes); - } -} - -static void -nntp_folder_sync_online (CamelFolder *folder, CamelException *ex) -{ - CAMEL_SERVICE_LOCK(folder->parent_store, connect_lock); - camel_folder_summary_save (folder->summary); - CAMEL_SERVICE_UNLOCK(folder->parent_store, connect_lock); -} - -static void -nntp_folder_sync_offline (CamelFolder *folder, CamelException *ex) -{ - CAMEL_SERVICE_LOCK(folder->parent_store, connect_lock); - camel_folder_summary_save (folder->summary); - CAMEL_SERVICE_UNLOCK(folder->parent_store, connect_lock); -} - -static gboolean -nntp_folder_set_message_flags (CamelFolder *folder, const char *uid, guint32 flags, guint32 set) -{ - return ((CamelFolderClass *) folder_class)->set_message_flags (folder, uid, flags, set); -} - -static CamelStream * -nntp_folder_download_message (CamelNNTPFolder *nntp_folder, const char *id, const char *msgid, CamelException *ex) -{ - CamelNNTPStore *nntp_store = (CamelNNTPStore *) ((CamelFolder *) nntp_folder)->parent_store; - CamelStream *stream = NULL; - int ret; - char *line; - - ret = camel_nntp_command (nntp_store, ex, nntp_folder, &line, "article %s", id); - if (ret == 220) { - stream = camel_data_cache_add (nntp_store->cache, "cache", msgid, NULL); - if (stream) { - if (camel_stream_write_to_stream ((CamelStream *) nntp_store->stream, stream) == -1) - goto fail; - if (camel_stream_reset (stream) == -1) - goto fail; - } else { - stream = (CamelStream *) nntp_store->stream; - camel_object_ref (stream); - } - } else if (ret == 423 || ret == 430) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message %s: %s"), msgid, line); - } else if (ret != -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get message %s: %s"), msgid, line); - } - - return stream; - - fail: - if (errno == EINTR) - camel_exception_setv (ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get message %s: %s"), msgid, g_strerror (errno)); - - return NULL; -} - - -static void -nntp_folder_cache_message (CamelDiscoFolder *disco_folder, const char *uid, CamelException *ex) -{ - CamelNNTPStore *nntp_store = (CamelNNTPStore *)((CamelFolder *) disco_folder)->parent_store; - CamelStream *stream; - char *article, *msgid; - - article = alloca(strlen(uid)+1); - strcpy(article, uid); - msgid = strchr(article, ','); - if (!msgid) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Internal error: uid in invalid format: %s"), uid); - return; - } - *msgid++ = 0; - - CAMEL_SERVICE_LOCK(nntp_store, connect_lock); - - stream = nntp_folder_download_message ((CamelNNTPFolder *) disco_folder, article, msgid, ex); - if (stream) - camel_object_unref (stream); - - CAMEL_SERVICE_UNLOCK(nntp_store, connect_lock); -} - -static CamelMimeMessage * -nntp_folder_get_message (CamelFolder *folder, const char *uid, CamelException *ex) -{ - CamelMimeMessage *message = NULL; - CamelNNTPStore *nntp_store; - CamelFolderChangeInfo *changes; - CamelNNTPFolder *nntp_folder; - CamelStream *stream = NULL; - char *article, *msgid; - - nntp_store = (CamelNNTPStore *) folder->parent_store; - nntp_folder = (CamelNNTPFolder *) folder; - - article = alloca(strlen(uid)+1); - strcpy(article, uid); - msgid = strchr (article, ','); - if (msgid == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Internal error: uid in invalid format: %s"), uid); - return NULL; - } - *msgid++ = 0; - - CAMEL_SERVICE_LOCK(nntp_store, connect_lock); - - /* Lookup in cache, NEWS is global messageid's so use a global cache path */ - stream = camel_data_cache_get (nntp_store->cache, "cache", msgid, NULL); - if (stream == NULL) { - if (camel_disco_store_status ((CamelDiscoStore *) nntp_store) == CAMEL_DISCO_STORE_OFFLINE) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("This message is not currently available")); - goto fail; - } - - stream = nntp_folder_download_message (nntp_folder, article, msgid, ex); - if (stream == NULL) - goto fail; - } - - message = camel_mime_message_new (); - if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) message, stream) == -1) { - if (errno == EINTR) - camel_exception_setv (ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get message %s: %s"), uid, g_strerror (errno)); - camel_object_unref(message); - message = NULL; - } - - camel_object_unref (stream); -fail: - if (camel_folder_change_info_changed (nntp_folder->changes)) { - changes = nntp_folder->changes; - nntp_folder->changes = camel_folder_change_info_new (); - } else { - changes = NULL; - } - - CAMEL_SERVICE_UNLOCK(nntp_store, connect_lock); - - if (changes) { - camel_object_trigger_event ((CamelObject *) folder, "folder_changed", changes); - camel_folder_change_info_free (changes); - } - - return message; -} - -static GPtrArray* -nntp_folder_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex) -{ - CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); - GPtrArray *matches; - - CAMEL_NNTP_FOLDER_LOCK(nntp_folder, search_lock); - - if (nntp_folder->search == NULL) - nntp_folder->search = camel_folder_search_new (); - - camel_folder_search_set_folder (nntp_folder->search, folder); - matches = camel_folder_search_search(nntp_folder->search, expression, NULL, ex); - - CAMEL_NNTP_FOLDER_UNLOCK(nntp_folder, search_lock); - - return matches; -} - -static GPtrArray * -nntp_folder_search_by_uids (CamelFolder *folder, const char *expression, GPtrArray *uids, CamelException *ex) -{ - CamelNNTPFolder *nntp_folder = (CamelNNTPFolder *) folder; - GPtrArray *matches; - - if (uids->len == 0) - return g_ptr_array_new(); - - CAMEL_NNTP_FOLDER_LOCK(folder, search_lock); - - if (nntp_folder->search == NULL) - nntp_folder->search = camel_folder_search_new (); - - camel_folder_search_set_folder (nntp_folder->search, folder); - matches = camel_folder_search_search(nntp_folder->search, expression, uids, ex); - - CAMEL_NNTP_FOLDER_UNLOCK(folder, search_lock); - - return matches; -} - -static void -nntp_folder_search_free (CamelFolder *folder, GPtrArray *result) -{ - CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); - - camel_folder_search_free_result (nntp_folder->search, result); -} - -static void -nntp_folder_append_message_online (CamelFolder *folder, CamelMimeMessage *mime_message, - const CamelMessageInfo *info, char **appended_uid, - CamelException *ex) -{ - CamelNNTPStore *nntp_store = (CamelNNTPStore *) folder->parent_store; - CamelStream *stream = (CamelStream*)nntp_store->stream; - CamelStreamFilter *filtered_stream; - CamelMimeFilter *crlffilter; - int ret; - unsigned int u; - struct _camel_header_raw *header, *savedhdrs, *n, *tail; - char *group, *line; - - CAMEL_SERVICE_LOCK(nntp_store, connect_lock); - - /* send 'POST' command */ - ret = camel_nntp_command (nntp_store, ex, NULL, &line, "post"); - if (ret != 340) { - if (ret == 440) - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION, - _("Posting failed: %s"), line); - else if (ret != -1) - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Posting failed: %s"), line); - CAMEL_SERVICE_UNLOCK(nntp_store, connect_lock); - return; - } - - /* the 'Newsgroups: ' header */ - group = g_strdup_printf ("Newsgroups: %s\r\n", folder->full_name); - - /* setup stream filtering */ - crlffilter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_DOTS); - filtered_stream = camel_stream_filter_new_with_stream (stream); - camel_stream_filter_add (filtered_stream, crlffilter); - camel_object_unref (crlffilter); - - /* remove mail 'To', 'CC', and 'BCC' headers */ - savedhdrs = NULL; - tail = (struct _camel_header_raw *) &savedhdrs; - - header = (struct _camel_header_raw *) &CAMEL_MIME_PART (mime_message)->headers; - n = header->next; - while (n != NULL) { - if (!g_ascii_strcasecmp (n->name, "To") || !g_ascii_strcasecmp (n->name, "Cc") || !g_ascii_strcasecmp (n->name, "Bcc")) { - header->next = n->next; - tail->next = n; - n->next = NULL; - tail = n; - } else { - header = n; - } - - n = header->next; - } - - /* write the message */ - if (camel_stream_write(stream, group, strlen(group)) == -1 - || camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (mime_message), CAMEL_STREAM (filtered_stream)) == -1 - || camel_stream_flush (CAMEL_STREAM (filtered_stream)) == -1 - || camel_stream_write (stream, "\r\n.\r\n", 5) == -1 - || (ret = camel_nntp_stream_line (nntp_store->stream, (unsigned char **)&line, &u)) == -1) { - if (errno == EINTR) - camel_exception_setv (ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Posting failed: %s"), g_strerror (errno)); - } else if (atoi(line) != 240) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Posting failed: %s"), line); - } - - camel_object_unref (filtered_stream); - g_free(group); - header->next = savedhdrs; - - CAMEL_SERVICE_UNLOCK(nntp_store, connect_lock); - - return; -} - -static void -nntp_folder_append_message_offline (CamelFolder *folder, CamelMimeMessage *mime_message, - const CamelMessageInfo *info, char **appended_uid, - CamelException *ex) -{ - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("You cannot post NNTP messages while working offline!")); -} - -/* I do not know what to do this exactly. Looking at the IMAP implementation for this, it - seems to assume the message is copied to a folder on the same store. In that case, an - NNTP implementation doesn't seem to make any sense. */ -static void -nntp_folder_transfer_message (CamelFolder *source, GPtrArray *uids, CamelFolder *dest, - GPtrArray **transferred_uids, gboolean delete_orig, CamelException *ex) -{ - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("You cannot copy messages from a NNTP folder!")); -} - -static void -nntp_folder_init (CamelNNTPFolder *nntp_folder, CamelNNTPFolderClass *klass) -{ - struct _CamelNNTPFolderPrivate *p; - - nntp_folder->changes = camel_folder_change_info_new (); - p = nntp_folder->priv = g_malloc0 (sizeof (*nntp_folder->priv)); - p->search_lock = g_mutex_new (); - p->cache_lock = g_mutex_new (); -} - -static void -nntp_folder_finalise (CamelNNTPFolder *nntp_folder) -{ - struct _CamelNNTPFolderPrivate *p; - - camel_folder_summary_save (((CamelFolder*) nntp_folder)->summary); - - p = nntp_folder->priv; - g_mutex_free (p->search_lock); - g_mutex_free (p->cache_lock); - g_free (p); -} - -static void -nntp_folder_class_init (CamelNNTPFolderClass *camel_nntp_folder_class) -{ - CamelDiscoFolderClass *camel_disco_folder_class = CAMEL_DISCO_FOLDER_CLASS (camel_nntp_folder_class); - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS (camel_nntp_folder_class); - - parent_class = CAMEL_DISCO_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_disco_folder_get_type ())); - folder_class = CAMEL_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_folder_get_type ())); - - /* virtual method definition */ - - /* virtual method overload */ - camel_disco_folder_class->sync_online = nntp_folder_sync_online; - camel_disco_folder_class->sync_resyncing = nntp_folder_sync_offline; - camel_disco_folder_class->sync_offline = nntp_folder_sync_offline; - camel_disco_folder_class->cache_message = nntp_folder_cache_message; - camel_disco_folder_class->append_online = nntp_folder_append_message_online; - camel_disco_folder_class->append_resyncing = nntp_folder_append_message_online; - camel_disco_folder_class->append_offline = nntp_folder_append_message_offline; - camel_disco_folder_class->transfer_online = nntp_folder_transfer_message; - camel_disco_folder_class->transfer_resyncing = nntp_folder_transfer_message; - camel_disco_folder_class->transfer_offline = nntp_folder_transfer_message; - camel_disco_folder_class->refresh_info_online = nntp_folder_refresh_info_online; - - camel_folder_class->set_message_flags = nntp_folder_set_message_flags; - camel_folder_class->get_message = nntp_folder_get_message; - camel_folder_class->search_by_expression = nntp_folder_search_by_expression; - camel_folder_class->search_by_uids = nntp_folder_search_by_uids; - camel_folder_class->search_free = nntp_folder_search_free; -} - -CamelType -camel_nntp_folder_get_type (void) -{ - static CamelType camel_nntp_folder_type = CAMEL_INVALID_TYPE; - - if (camel_nntp_folder_type == CAMEL_INVALID_TYPE) { - camel_nntp_folder_type = camel_type_register (CAMEL_DISCO_FOLDER_TYPE, "CamelNNTPFolder", - sizeof (CamelNNTPFolder), - sizeof (CamelNNTPFolderClass), - (CamelObjectClassInitFunc) nntp_folder_class_init, - NULL, - (CamelObjectInitFunc) nntp_folder_init, - (CamelObjectFinalizeFunc) nntp_folder_finalise); - } - - return camel_nntp_folder_type; -} - -CamelFolder * -camel_nntp_folder_new (CamelStore *parent, const char *folder_name, CamelException *ex) -{ - CamelFolder *folder; - CamelNNTPFolder *nntp_folder; - char *root; - CamelService *service; - CamelStoreInfo *si; - gboolean subscribed = TRUE; - - service = (CamelService *) parent; - root = camel_session_get_storage_path (service->session, service, ex); - if (root == NULL) - return NULL; - - /* If this doesn't work, stuff wont save, but let it continue anyway */ - camel_mkdir (root, 0777); - - folder = (CamelFolder *) camel_object_new (CAMEL_NNTP_FOLDER_TYPE); - nntp_folder = (CamelNNTPFolder *)folder; - - camel_folder_construct (folder, parent, folder_name, folder_name); - folder->folder_flags |= CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY|CAMEL_FOLDER_HAS_SEARCH_CAPABILITY; - - nntp_folder->storage_path = g_build_filename (root, folder->full_name, NULL); - g_free (root); - - root = g_strdup_printf ("%s.cmeta", nntp_folder->storage_path); - camel_object_set(nntp_folder, NULL, CAMEL_OBJECT_STATE_FILE, root, NULL); - camel_object_state_read(nntp_folder); - g_free(root); - - root = g_strdup_printf("%s.ev-summary", nntp_folder->storage_path); - folder->summary = (CamelFolderSummary *) camel_nntp_summary_new (folder, root); - g_free(root); - camel_folder_summary_load (folder->summary); - - si = camel_store_summary_path ((CamelStoreSummary *) ((CamelNNTPStore*) parent)->summary, folder_name); - if (si) { - subscribed = (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) != 0; - camel_store_summary_info_free ((CamelStoreSummary *) ((CamelNNTPStore*) parent)->summary, si); - } - - if (subscribed) { - camel_folder_refresh_info(folder, ex); - if (camel_exception_is_set(ex)) { - camel_object_unref (folder); - folder = NULL; - } - } - - return folder; -} diff --git a/camel/providers/nntp/camel-nntp-folder.h b/camel/providers/nntp/camel-nntp-folder.h deleted file mode 100644 index 0914ee4cad..0000000000 --- a/camel/providers/nntp/camel-nntp-folder.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-folder.h : NNTP group (folder) support. */ - -/* - * - * Author : Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 2000 Ximian . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_NNTP_FOLDER_H -#define CAMEL_NNTP_FOLDER_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel/camel-folder.h" -#include "camel/camel-disco-folder.h" - -/* #include "camel-store.h" */ - -#define CAMEL_NNTP_FOLDER_TYPE (camel_nntp_folder_get_type ()) -#define CAMEL_NNTP_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_NNTP_FOLDER_TYPE, CamelNNTPFolder)) -#define CAMEL_NNTP_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_NNTP_FOLDER_TYPE, CamelNNTPFolderClass)) -#define CAMEL_IS_NNTP_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_NNTP_FOLDER_TYPE)) - -typedef struct _CamelNNTPFolder { - CamelDiscoFolder parent; - - struct _CamelNNTPFolderPrivate *priv; - - struct _CamelFolderChangeInfo *changes; - char *storage_path; - CamelFolderSearch *search; -} CamelNNTPFolder; - -typedef struct _CamelNNTPFolderClass { - CamelDiscoFolderClass parent; - - /* Virtual methods */ - -} CamelNNTPFolderClass; - -/* public methods */ - -/* Standard Camel function */ -CamelType camel_nntp_folder_get_type (void); - -CamelFolder *camel_nntp_folder_new (CamelStore *parent, const char *folder_name, CamelException *ex); - -void camel_nntp_folder_selected(CamelNNTPFolder *folder, char *line, CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_NNTP_FOLDER_H */ diff --git a/camel/providers/nntp/camel-nntp-grouplist.c b/camel/providers/nntp/camel-nntp-grouplist.c deleted file mode 100644 index cbcf2b30b2..0000000000 --- a/camel/providers/nntp/camel-nntp-grouplist.c +++ /dev/null @@ -1,218 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-grouplist.c : getting/updating the list of newsgroups on the server. */ - -/* - * Author : Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 2000 Ximian . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include <config.h> -#include <errno.h> -#include <string.h> - -#include "camel-exception.h" -#include "camel-nntp-grouplist.h" -#include "camel-nntp-resp-codes.h" - -static CamelNNTPGroupList * -camel_nntp_get_grouplist_from_server (CamelNNTPStore *store, CamelException *ex) -{ - int status; - gboolean done = FALSE; - CamelNNTPGroupList *list; - - CAMEL_NNTP_STORE_LOCK(store); - status = camel_nntp_command (store, ex, NULL, &line, "LIST"); - - if (status != NNTP_LIST_FOLLOWS) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not get group list from server.")); - return NULL; - } - - list = g_new0 (CamelNNTPGroupList, 1); - list->time = time (NULL); - - while (!done) { - char *line; - - if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (store), &line, ex) < 0) { - list->group_list = g_list_reverse(list->group_list); - return list; - } - - if (*line == '.') { - done = TRUE; - } - else { - CamelNNTPGroupListEntry *entry = g_new (CamelNNTPGroupListEntry, 1); - char **split_line = g_strsplit (line, " ", 4); - - entry->group_name = g_strdup (split_line[0]); - entry->high = atoi (split_line[1]); - entry->low = atoi (split_line[2]); - - g_strfreev (split_line); - - list->group_list = g_list_prepend (list->group_list, entry); - } - } - CAMEL_NNTP_STORE_UNLOCK(store); - - list->group_list = g_list_reverse(list->group_list); - return list; -} - -static CamelNNTPGroupList* -camel_nntp_get_grouplist_from_file (CamelNNTPStore *store, CamelException *ex) -{ - gchar *root_dir = camel_nntp_store_get_toplevel_dir(CAMEL_NNTP_STORE(store)); - gchar *grouplist_file = g_strdup_printf ("%s/grouplist", root_dir); - CamelNNTPGroupList *list; - FILE *fp; - char buf[300]; - unsigned long time; - - g_free (root_dir); - fp = fopen (grouplist_file, "r"); - g_free (grouplist_file); - - if (fp == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Unable to load grouplist file for %s: %s"), - CAMEL_SERVICE(store)->url->host, - strerror(errno)); - return NULL; - } - - /* read the time */ - if (!fgets (buf, sizeof (buf), fp)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Unable to load grouplist file for %s: %s"), - CAMEL_SERVICE(store)->url->host, - strerror(errno)); - fclose (fp); - return NULL; - } - - - list = g_new0 (CamelNNTPGroupList, 1); - list->store = store; - sscanf (buf, "%lu", &time); - list->time = time; - - while (fgets (buf, sizeof (buf), fp)) { - CamelNNTPGroupListEntry *entry = g_new (CamelNNTPGroupListEntry, 1); - char **split_line = g_strsplit (buf, " ", 4); - - entry->group_name = g_strdup (split_line[0]); - entry->high = atoi (split_line[1]); - entry->low = atoi (split_line[2]); - - g_strfreev (split_line); - - list->group_list = g_list_prepend (list->group_list, entry); - } - - fclose (fp); - - list->group_list = g_list_reverse(list->group_list); - return list; -} - -static void -save_entry (CamelNNTPGroupListEntry *entry, FILE *fp) -{ - fprintf (fp, "%s %d %d\n", entry->group_name, entry->low, entry->high); -} - -void -camel_nntp_grouplist_save (CamelNNTPGroupList *group_list, CamelException *ex) -{ - FILE *fp; - gchar *root_dir = camel_nntp_store_get_toplevel_dir(CAMEL_NNTP_STORE(group_list->store)); - gchar *grouplist_file = g_strdup_printf ("%s/grouplist", root_dir); - - g_free (root_dir); - fp = fopen (grouplist_file, "w"); - g_free (grouplist_file); - - if (fp == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Unable to save grouplist file for %s: %s"), - CAMEL_SERVICE(group_list->store)->url->host, - strerror(errno)); - return; - } - - fprintf (fp, "%lu\n", (long)group_list->time); - - g_list_foreach (group_list->group_list, (GFunc)save_entry, fp); - - fclose (fp); -} - -static void -free_entry (CamelNNTPGroupListEntry *entry, void *data) -{ - g_free (entry->group_name); - g_free (entry); -} - -void -camel_nntp_grouplist_free (CamelNNTPGroupList *group_list) -{ - g_return_if_fail (group_list); - - g_list_foreach (group_list->group_list, (GFunc)free_entry, NULL); - - g_free (group_list); -} - -CamelNNTPGroupList* -camel_nntp_grouplist_fetch (CamelNNTPStore *store, CamelException *ex) -{ - CamelNNTPGroupList *list; - - list = camel_nntp_get_grouplist_from_file (store, ex); - - printf ("camel_nntp_get_grouplist_from_file returned %p\n", list); - - if (!list) { - camel_exception_clear (ex); - - list = camel_nntp_get_grouplist_from_server (store, ex); - - if (!list) { - camel_nntp_grouplist_free (list); - } - else { - list->store = store; - camel_nntp_grouplist_save (list, ex); - return list; - } - } - - return list; -} - -gint -camel_nntp_grouplist_update (CamelNNTPGroupList *group_list, CamelException *ex) -{ - return 0; -} diff --git a/camel/providers/nntp/camel-nntp-grouplist.h b/camel/providers/nntp/camel-nntp-grouplist.h deleted file mode 100644 index b45d352cd8..0000000000 --- a/camel/providers/nntp/camel-nntp-grouplist.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-grouplist.h : getting/updating the list of newsgroups on the server. */ - -/* - * Author : Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 2000 Ximian . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_NNTP_GROUPLIST_H -#define CAMEL_NNTP_GROUPLIST_H 1 - -#include <time.h> -#include "camel-nntp-store.h" - -struct CamelNNTPGroupListEntry { - char *group_name; - guint32 low; - guint32 high; - guint32 flags; -}; - -struct CamelNNTPGroupList { - CamelNNTPStore *store; - time_t time; - GList *group_list; -}; - -typedef struct CamelNNTPGroupList _CamelNNTPGroupList; -typedef struct CamelNNTPGroupListEntry _CamelNNTPGroupListEntry; - -struct CamelNNTPGroupList* camel_nntp_grouplist_fetch (CamelNNTPStore *store, CamelException *ex); -gint camel_nntp_grouplist_update (struct CamelNNTPGroupList *group_list, CamelException *ex); -void camel_nntp_grouplist_save (struct CamelNNTPGroupList *group_list, CamelException *ex); -void camel_nntp_grouplist_free (struct CamelNNTPGroupList *group_list); - -#endif /* CAMEL_NNTP_GROUPLIST_H */ diff --git a/camel/providers/nntp/camel-nntp-newsrc.c b/camel/providers/nntp/camel-nntp-newsrc.c deleted file mode 100644 index 309e1f45c8..0000000000 --- a/camel/providers/nntp/camel-nntp-newsrc.c +++ /dev/null @@ -1,651 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Authors: Chris Toshok <toshok@ximian.com> - * - * Copyright 2000-2003 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <glib.h> - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <pthread.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> - -#include "camel-nntp-newsrc.h" -#include <camel/camel-folder-summary.h> - -#define NEWSRC_LOCK(f, l) (g_mutex_lock(((CamelNNTPNewsrc *)f)->l)) -#define NEWSRC_UNLOCK(f, l) (g_mutex_unlock(((CamelNNTPNewsrc *)f)->l)) - -typedef struct { - guint low; - guint high; -} ArticleRange; - -typedef struct { - char *name; - GArray *ranges; - gboolean subscribed; -} NewsrcGroup; - -struct CamelNNTPNewsrc { - gchar *filename; - GHashTable *groups; - gboolean dirty; - GMutex *lock; -}; - - -static NewsrcGroup * -camel_nntp_newsrc_group_add (CamelNNTPNewsrc *newsrc, const char *group_name, gboolean subscribed) -{ - NewsrcGroup *new_group = g_malloc(sizeof(NewsrcGroup)); - - new_group->name = g_strdup(group_name); - new_group->subscribed = subscribed; - new_group->ranges = g_array_new (FALSE, FALSE, sizeof (ArticleRange)); - - g_hash_table_insert (newsrc->groups, new_group->name, new_group); - - newsrc->dirty = TRUE; - - return new_group; -} - -static int -camel_nntp_newsrc_group_get_highest_article_read(CamelNNTPNewsrc *newsrc, NewsrcGroup *group) -{ - if (!group || group->ranges->len == 0) - return 0; - - return g_array_index(group->ranges, ArticleRange, group->ranges->len - 1).high; -} - -static int -camel_nntp_newsrc_group_get_num_articles_read(CamelNNTPNewsrc *newsrc, NewsrcGroup *group) -{ - int i; - int count = 0; - - if (group == NULL) - return 0; - - for (i = 0; i < group->ranges->len; i ++) - count += (g_array_index(group->ranges, ArticleRange, i).high - - g_array_index(group->ranges, ArticleRange, i).low) + 1; - - return count; -} - - -static void -camel_nntp_newsrc_group_mark_range_read(CamelNNTPNewsrc *newsrc, NewsrcGroup *group, long low, long high) -{ - int i; - - if (group->ranges->len == 1 - && g_array_index (group->ranges, ArticleRange, 0).low == 0 - && g_array_index (group->ranges, ArticleRange, 0).high == 0) { - g_array_index (group->ranges, ArticleRange, 0).low = low; - g_array_index (group->ranges, ArticleRange, 0).high = high; - - newsrc->dirty = TRUE; - } - else { - ArticleRange tmp_range; - - for (i = 0; i < group->ranges->len; i ++) { - guint range_low = g_array_index (group->ranges, ArticleRange, i).low; - guint range_high = g_array_index (group->ranges, ArticleRange, i).high; - - /* if it's already part of a range, return immediately. */ - if (low >= range_low && - low <= range_high && - high >= range_low && - high <= range_high) { - return; - } - /* if we have a new lower bound for this range, set it. */ - else if (low <= range_low - && high >= range_low - && high <= range_high) { - g_array_index (group->ranges, ArticleRange, i).low = low; - newsrc->dirty = TRUE; - return; - } - /* if we have a new upper bound for this range, set it. */ - else if (high >= range_high - && low >= range_low - && low <= range_high) { - g_array_index (group->ranges, ArticleRange, i).high = high; - newsrc->dirty = TRUE; - return; - } - /* if we would be inserting another range that - starts one index higher than an existing - one, make the upper value of the existing - range the upper value of the new one. */ - else if (low == range_high + 1) { - g_array_index (group->ranges, ArticleRange, i).high = high; - newsrc->dirty = TRUE; - return; - } - /* if we would be inserting another range that - ends one index lower than an existing one, - group the existing range by setting its low - to the new low */ - else if (high == range_low - 1) { - g_array_index (group->ranges, ArticleRange, i).low = low; - newsrc->dirty = TRUE; - return; - } - /* if the range lies entirely outside another - range, doesn't coincide with it's - endpoints, and has lower values, insert it - into the middle of the list. */ - else if (low < range_low - && high < range_low) { - tmp_range.low = low; - tmp_range.high = high; - - group->ranges = g_array_insert_val (group->ranges, i, tmp_range); - newsrc->dirty = TRUE; - - return; - } - } - - /* if we made it here, the range needs to go at the end */ - tmp_range.low = low; - tmp_range.high = high; - group->ranges = g_array_append_val (group->ranges, tmp_range); - newsrc->dirty = TRUE; - } -} - -int -camel_nntp_newsrc_get_highest_article_read (CamelNNTPNewsrc *newsrc, const char *group_name) -{ - NewsrcGroup *group; - int ret; - - NEWSRC_LOCK(newsrc, lock); - - group = g_hash_table_lookup (newsrc->groups, group_name); - - if (group) - ret = camel_nntp_newsrc_group_get_highest_article_read (newsrc, group); - else - ret = 0; - - NEWSRC_UNLOCK(newsrc, lock); - - return ret; -} - -int -camel_nntp_newsrc_get_num_articles_read (CamelNNTPNewsrc *newsrc, const char *group_name) -{ - NewsrcGroup *group; - int ret; - - NEWSRC_LOCK(newsrc, lock); - - group = g_hash_table_lookup (newsrc->groups, group_name); - - if (group) - ret = camel_nntp_newsrc_group_get_num_articles_read (newsrc, group); - else - ret = 0; - - NEWSRC_UNLOCK(newsrc, lock); - - return ret; -} - -void -camel_nntp_newsrc_mark_article_read (CamelNNTPNewsrc *newsrc, const char *group_name, int num) -{ - camel_nntp_newsrc_mark_range_read (newsrc, group_name, num, num); -} - -void -camel_nntp_newsrc_mark_range_read(CamelNNTPNewsrc *newsrc, const char *group_name, long low, long high) -{ - NewsrcGroup *group; - - /* swap them if they're in the wrong order. */ - if (low > high) { - long tmp; - - tmp = high; - high = low; - low = tmp; - } - - NEWSRC_LOCK(newsrc, lock); - group = g_hash_table_lookup (newsrc->groups, group_name); - - if (group) - camel_nntp_newsrc_group_mark_range_read (newsrc, group, low, high); - NEWSRC_UNLOCK(newsrc, lock); -} - -gboolean -camel_nntp_newsrc_article_is_read (CamelNNTPNewsrc *newsrc, const char *group_name, long num) -{ - int i; - NewsrcGroup *group; - int ret = FALSE; - - NEWSRC_LOCK(newsrc, lock); - group = g_hash_table_lookup (newsrc->groups, group_name); - - if (group) { - for (i = 0; i < group->ranges->len; i++) { - if (num >= g_array_index (group->ranges, ArticleRange, i).low && - num <= g_array_index (group->ranges, ArticleRange, i).high) { - ret = TRUE; - break; - } - } - } - - NEWSRC_UNLOCK(newsrc, lock); - - return FALSE; -} - -gboolean -camel_nntp_newsrc_group_is_subscribed (CamelNNTPNewsrc *newsrc, const char *group_name) -{ - NewsrcGroup *group; - int ret = FALSE; - - NEWSRC_LOCK(newsrc, lock); - - group = g_hash_table_lookup (newsrc->groups, group_name); - - if (group) { - ret = group->subscribed; - } - - NEWSRC_UNLOCK(newsrc, lock); - - return ret; -} - -void -camel_nntp_newsrc_subscribe_group (CamelNNTPNewsrc *newsrc, const char *group_name) -{ - NewsrcGroup *group; - - NEWSRC_LOCK(newsrc, lock); - - group = g_hash_table_lookup (newsrc->groups, group_name); - - if (group) { - if (!group->subscribed) - newsrc->dirty = TRUE; - group->subscribed = TRUE; - } - else { - camel_nntp_newsrc_group_add (newsrc, group_name, TRUE); - } - - NEWSRC_UNLOCK(newsrc, lock); -} - -void -camel_nntp_newsrc_unsubscribe_group (CamelNNTPNewsrc *newsrc, const char *group_name) -{ - NewsrcGroup *group; - - NEWSRC_LOCK(newsrc, lock); - - group = g_hash_table_lookup (newsrc->groups, group_name); - if (group) { - if (group->subscribed) - newsrc->dirty = TRUE; - group->subscribed = FALSE; - } - else { - camel_nntp_newsrc_group_add (newsrc, group_name, FALSE); - } - - NEWSRC_UNLOCK(newsrc, lock); -} - -struct newsrc_ptr_array { - GPtrArray *ptr_array; - gboolean subscribed_only; -}; - -/* this needs to strdup the grup_name, if the group array is likely to change */ -static void -get_group_foreach (char *group_name, NewsrcGroup *group, struct newsrc_ptr_array *npa) -{ - if (group->subscribed || !npa->subscribed_only) { - g_ptr_array_add (npa->ptr_array, group_name); - } -} - -GPtrArray * -camel_nntp_newsrc_get_subscribed_group_names (CamelNNTPNewsrc *newsrc) -{ - struct newsrc_ptr_array npa; - - g_return_val_if_fail (newsrc, NULL); - - NEWSRC_LOCK(newsrc, lock); - - npa.ptr_array = g_ptr_array_new(); - npa.subscribed_only = TRUE; - - g_hash_table_foreach (newsrc->groups, - (GHFunc)get_group_foreach, &npa); - - NEWSRC_UNLOCK(newsrc, lock); - - return npa.ptr_array; -} - -GPtrArray * -camel_nntp_newsrc_get_all_group_names (CamelNNTPNewsrc *newsrc) -{ - struct newsrc_ptr_array npa; - - g_return_val_if_fail (newsrc, NULL); - - NEWSRC_LOCK(newsrc, lock); - - npa.ptr_array = g_ptr_array_new(); - npa.subscribed_only = FALSE; - - g_hash_table_foreach (newsrc->groups, - (GHFunc)get_group_foreach, &npa); - - NEWSRC_UNLOCK(newsrc, lock); - - return npa.ptr_array; -} - -void -camel_nntp_newsrc_free_group_names (CamelNNTPNewsrc *newsrc, GPtrArray *group_names) -{ - g_ptr_array_free (group_names, TRUE); -} - -struct newsrc_fp { - CamelNNTPNewsrc *newsrc; - FILE *fp; -}; - -static void -camel_nntp_newsrc_write_group_line(gpointer key, NewsrcGroup *group, struct newsrc_fp *newsrc_fp) -{ - CamelNNTPNewsrc *newsrc; - FILE *fp; - int i; - - fp = newsrc_fp->fp; - newsrc = newsrc_fp->newsrc; - - fprintf (fp, "%s%c", group->name, group->subscribed ? ':' : '!'); - - if (group->ranges->len == 1 - && g_array_index (group->ranges, ArticleRange, 0).low == 0 - && g_array_index (group->ranges, ArticleRange, 0).high == 0) { - fprintf (fp, "\n"); - - return; /* special case since our parsing code will insert this - bogus range if there were no read articles. The code - to add a range is smart enough to remove this one if we - ever mark an article read, but we still need to deal with - it if that code doesn't get hit. */ - } - - fprintf (fp, " "); - - for (i = 0; i < group->ranges->len; i ++) { - char range_buffer[100]; - guint low = g_array_index (group->ranges, ArticleRange, i).low; - guint high = g_array_index (group->ranges, ArticleRange, i).high; - - if (low == high) - sprintf(range_buffer, "%d", low); - else if (low == high - 1) - sprintf(range_buffer, "%d,%d", low, high); - else - sprintf(range_buffer, "%d-%d", low, high); - - if (i != group->ranges->len - 1) - strcat(range_buffer, ","); - - fprintf (fp, range_buffer); - } - - fprintf (fp, "\n"); -} - -void -camel_nntp_newsrc_write_to_file(CamelNNTPNewsrc *newsrc, FILE *fp) -{ - struct newsrc_fp newsrc_fp; - - g_return_if_fail (newsrc); - - newsrc_fp.newsrc = newsrc; - newsrc_fp.fp = fp; - - NEWSRC_LOCK(newsrc, lock); - - g_hash_table_foreach (newsrc->groups, - (GHFunc)camel_nntp_newsrc_write_group_line, - &newsrc_fp); - - NEWSRC_UNLOCK(newsrc, lock); -} - -void -camel_nntp_newsrc_write(CamelNNTPNewsrc *newsrc) -{ - FILE *fp; - - g_return_if_fail (newsrc); - - NEWSRC_LOCK(newsrc, lock); - - if (!newsrc->dirty) { - NEWSRC_UNLOCK(newsrc, lock); - return; - } - - if ((fp = fopen(newsrc->filename, "w")) == NULL) { - g_warning ("Couldn't open newsrc file '%s'.\n", newsrc->filename); - NEWSRC_UNLOCK(newsrc, lock); - return; - } - - newsrc->dirty = FALSE; - NEWSRC_UNLOCK(newsrc, lock); - - camel_nntp_newsrc_write_to_file(newsrc, fp); - - fclose(fp); -} - -static void -camel_nntp_newsrc_parse_line(CamelNNTPNewsrc *newsrc, char *line) -{ - char *p, *comma, *dash; - gboolean is_subscribed; - NewsrcGroup *group; - - p = strchr(line, ':'); - - if (p) { - is_subscribed = TRUE; - } - else { - p = strchr(line, '!'); - if (p) - is_subscribed = FALSE; - else - return; /* bogus line. */ - } - - *p++ = '\0'; - - group = camel_nntp_newsrc_group_add (newsrc, line, is_subscribed); - - do { - guint high, low; - - comma = strchr(p, ','); - - if (comma) - *comma = '\0'; - - dash = strchr(p, '-'); - - if (!dash) { /* there wasn't a dash. must be just one number */ - high = low = atol(p); - } - else { /* there was a dash. */ - *dash = '\0'; - low = atol(p); - *dash = '-'; - p = dash + 1; - high = atol(p); - } - - camel_nntp_newsrc_group_mark_range_read (newsrc, group, low, high); - - if (comma) { - *comma = ','; - p = comma + 1; - } - - } while(comma); -} - -static char* -get_line (char *buf, char **p) -{ - char *l; - char *line; - - g_assert (*p == NULL || **p == '\n' || **p == '\0'); - - if (*p == NULL) { - *p = buf; - - if (**p == '\0') - return NULL; - } - else { - if (**p == '\0') - return NULL; - - (*p) ++; - - /* if we just incremented to the end of the buffer, return NULL */ - if (**p == '\0') - return NULL; - } - - l = strchr (*p, '\n'); - if (l) { - *l = '\0'; - line = g_strdup (*p); - *l = '\n'; - *p = l; - } - else { - /* we're at the last line (which isn't terminated by a \n, btw) */ - line = g_strdup (*p); - (*p) += strlen (*p); - } - - return line; -} - -CamelNNTPNewsrc * -camel_nntp_newsrc_read_for_server (const char *server) -{ - int fd; - char buf[1024]; - char *file_contents, *line, *p; - char *filename; - CamelNNTPNewsrc *newsrc; - int newsrc_len; - int len_read = 0; - struct stat sb; - - filename = g_strdup_printf ("%s/.newsrc-%s", g_get_home_dir(), server); - - newsrc = g_new0(CamelNNTPNewsrc, 1); - newsrc->filename = filename; - newsrc->groups = g_hash_table_new (g_str_hash, g_str_equal); - newsrc->lock = g_mutex_new(); - - if ((fd = open(filename, O_RDONLY)) == -1) { - g_warning ("~/.newsrc-%s not present.\n", server); - return newsrc; - } - - if (fstat (fd, &sb) == -1) { - g_warning ("failed fstat on ~/.newsrc-%s: %s\n", server, strerror(errno)); - return newsrc; - } - newsrc_len = sb.st_size; - - file_contents = g_malloc (newsrc_len + 1); - - while (len_read < newsrc_len) { - int c = read (fd, buf, sizeof (buf)); - - if (c == -1) - break; - - memcpy (&file_contents[len_read], buf, c); - len_read += c; - } - file_contents [len_read] = 0; - - p = NULL; - while ((line = get_line (file_contents, &p))) { - camel_nntp_newsrc_parse_line(newsrc, line); - g_free (line); - } - - close (fd); - g_free (file_contents); - - return newsrc; -} diff --git a/camel/providers/nntp/camel-nntp-newsrc.h b/camel/providers/nntp/camel-nntp-newsrc.h deleted file mode 100644 index 652e3edbce..0000000000 --- a/camel/providers/nntp/camel-nntp-newsrc.h +++ /dev/null @@ -1,34 +0,0 @@ - -#ifndef _CAMEL_NNTP_NEWSRC_H_ -#define _CAMEL_NNTP_NEWSRC_H_ - -#include <stdio.h> -#include "glib.h" - -typedef struct CamelNNTPNewsrc CamelNNTPNewsrc; - -int camel_nntp_newsrc_get_highest_article_read (CamelNNTPNewsrc *newsrc, const char *group_name); -int camel_nntp_newsrc_get_num_articles_read (CamelNNTPNewsrc *newsrc, const char *group_name); -void camel_nntp_newsrc_mark_article_read (CamelNNTPNewsrc *newsrc, - const char *group_name, int num); -void camel_nntp_newsrc_mark_range_read (CamelNNTPNewsrc *newsrc, - const char *group_name, long low, long high); - -gboolean camel_nntp_newsrc_article_is_read (CamelNNTPNewsrc *newsrc, - const char *group_name, long num); - -gboolean camel_nntp_newsrc_group_is_subscribed (CamelNNTPNewsrc *newsrc, const char *group_name); -void camel_nntp_newsrc_subscribe_group (CamelNNTPNewsrc *newsrc, const char *group_name); -void camel_nntp_newsrc_unsubscribe_group (CamelNNTPNewsrc *newsrc, const char *group_name); - -GPtrArray* camel_nntp_newsrc_get_subscribed_group_names (CamelNNTPNewsrc *newsrc); -GPtrArray* camel_nntp_newsrc_get_all_group_names (CamelNNTPNewsrc *newsrc); -void camel_nntp_newsrc_free_group_names (CamelNNTPNewsrc *newsrc, GPtrArray *group_names); - -void camel_nntp_newsrc_write_to_file (CamelNNTPNewsrc *newsrc, FILE *fp); -void camel_nntp_newsrc_write (CamelNNTPNewsrc *newsrc); -CamelNNTPNewsrc *camel_nntp_newsrc_read_for_server (const char *server); - -#endif /* _CAMEL_NNTP_NEWSRC_H_ */ - - diff --git a/camel/providers/nntp/camel-nntp-private.h b/camel/providers/nntp/camel-nntp-private.h deleted file mode 100644 index 520c9db134..0000000000 --- a/camel/providers/nntp/camel-nntp-private.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * camel-nntp-private.h: Private info for nntp. - * - * Authors: Michael Zucchi <notzed@ximian.com> - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_NNTP_PRIVATE_H -#define CAMEL_NNTP_PRIVATE_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -/* need a way to configure and save this data, if this header is to - be installed. For now, dont install it */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "libedataserver/e-msgport.h" - -struct _CamelNNTPStorePrivate { - int dummy; -}; - -#define CAMEL_NNTP_STORE_LOCK(f, l) (e_mutex_lock(((CamelNNTPStore *)f)->priv->l)) -#define CAMEL_NNTP_STORE_UNLOCK(f, l) (e_mutex_unlock(((CamelNNTPStore *)f)->priv->l)) - - -struct _CamelNNTPFolderPrivate { - GMutex *search_lock; /* for locking the search object */ - GMutex *cache_lock; /* for locking the cache object */ -}; - -#define CAMEL_NNTP_FOLDER_LOCK(f, l) (g_mutex_lock(((CamelNNTPFolder *)f)->priv->l)) -#define CAMEL_NNTP_FOLDER_UNLOCK(f, l) (g_mutex_unlock(((CamelNNTPFolder *)f)->priv->l)) -#else -#define CAMEL_NNTP_FOLDER_LOCK(f, l) -#define CAMEL_NNTP_FOLDER_UNLOCK(f, l) - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_NNTP_PRIVATE_H */ - diff --git a/camel/providers/nntp/camel-nntp-provider.c b/camel/providers/nntp/camel-nntp-provider.c deleted file mode 100644 index 5780c41f9d..0000000000 --- a/camel/providers/nntp/camel-nntp-provider.c +++ /dev/null @@ -1,138 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-provider.c: nntp provider registration code */ - -/* - * Authors : - * Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <string.h> -#include "camel-nntp-store.h" -#include "camel-provider.h" -#include "camel-session.h" -#include "camel-i18n.h" - -static void add_hash (guint *hash, char *s); -static guint nntp_url_hash (gconstpointer key); -static gint check_equal (char *s1, char *s2); -static gint nntp_url_equal (gconstpointer a, gconstpointer b); - -CamelProviderConfEntry nntp_conf_entries[] = { - { CAMEL_PROVIDER_CONF_SECTION_START, "folders", NULL, - N_("Folders") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "show_short_notation", NULL, - N_("Show folders in short notation (e.g. c.o.linux rather than comp.os.linux)"), "1" }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "folder_hierarchy_relative", NULL, - N_("In the subscription dialog, show relative folder names"), "1" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider news_provider = { - "nntp", - N_("USENET news"), - - N_("This is a provider for reading from and posting to" - "USENET newsgroups."), - - "news", - - CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE | - CAMEL_PROVIDER_IS_STORAGE | CAMEL_PROVIDER_SUPPORTS_SSL, - - CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_USER | - CAMEL_URL_ALLOW_PASSWORD | CAMEL_URL_ALLOW_AUTH, - - nntp_conf_entries - - /* ... */ -}; - -CamelServiceAuthType camel_nntp_password_authtype = { - N_("Password"), - - N_("This option will authenticate with the NNTP server using a " - "plaintext password."), - - "", - TRUE -}; - -void -camel_provider_module_init(void) -{ - news_provider.object_types[CAMEL_PROVIDER_STORE] = camel_nntp_store_get_type(); - - news_provider.url_hash = nntp_url_hash; - news_provider.url_equal = nntp_url_equal; - news_provider.authtypes = g_list_append (NULL, &camel_nntp_password_authtype); - - camel_provider_register(&news_provider); -} - -static void -add_hash (guint *hash, char *s) -{ - if (s) - *hash ^= g_str_hash(s); -} - -static guint -nntp_url_hash (gconstpointer key) -{ - const CamelURL *u = (CamelURL *)key; - guint hash = 0; - - add_hash (&hash, u->user); - add_hash (&hash, u->host); - hash ^= u->port; - - return hash; -} - -static gint -check_equal (char *s1, char *s2) -{ - if (s1 == NULL) { - if (s2 == NULL) - return TRUE; - else - return FALSE; - } - - if (s2 == NULL) - return FALSE; - - return strcmp (s1, s2) == 0; -} - -static gint -nntp_url_equal (gconstpointer a, gconstpointer b) -{ - const CamelURL *u1 = a, *u2 = b; - - return check_equal(u1->protocol, u2->protocol) - && check_equal (u1->user, u2->user) - && check_equal (u1->host, u2->host) - && u1->port == u2->port; -} diff --git a/camel/providers/nntp/camel-nntp-resp-codes.h b/camel/providers/nntp/camel-nntp-resp-codes.h deleted file mode 100644 index d9aace81ef..0000000000 --- a/camel/providers/nntp/camel-nntp-resp-codes.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-resp-codes.h : #defines for all the response codes we care about */ - -/* - * - * Copyright (C) 2000 Ximian, Inc. <toshok@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_NNTP_RESP_CODES_H -#define CAMEL_NNTP_RESP_CODES_H 1 - -#define CAMEL_NNTP_OK(x) ((x) < 400) -#define CAMEL_NNTP_ERR(x) (!CAMEL_NNTP_OK(x) && (x) < 500) -#define CAMEL_NNTP_FAIL(x) (!CAMEL_NNTP_OK(x) && !CAMEL_NNTP_ERR(x)) - -#define NNTP_GREETING_POSTING_OK 200 -#define NNTP_GREETING_NO_POSTING 201 - -#define NNTP_EXTENSIONS_SUPPORTED 202 -#define NNTP_GROUP_SELECTED 211 -#define NNTP_LIST_FOLLOWS 215 -#define NNTP_ARTICLE_FOLLOWS 220 -#define NNTP_HEAD_FOLLOWS 221 -#define NNTP_DATA_FOLLOWS 224 -#define NNTP_NEW_ARTICLE_LIST_FOLLOWS 230 -#define NNTP_NEW_GROUP_LIST_FOLLOWS 231 - -#define NNTP_NO_SUCH_GROUP 411 -#define NNTP_NO_SUCH_ARTICLE 430 - -#define NNTP_NO_PERMISSION 502 - -/* authentication */ -#define NNTP_AUTH_ACCEPTED 281 -#define NNTP_AUTH_CONTINUE 381 -#define NNTP_AUTH_REQUIRED 480 -#define NNTP_AUTH_REJECTED 482 - -#define NNTP_PROTOCOL_ERROR 666 - -#endif /* CAMEL_NNTP_RESP_CODES_H */ diff --git a/camel/providers/nntp/camel-nntp-store-summary.c b/camel/providers/nntp/camel-nntp-store-summary.c deleted file mode 100644 index 4c7e3df1aa..0000000000 --- a/camel/providers/nntp/camel-nntp-store-summary.c +++ /dev/null @@ -1,438 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2002 Ximian Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <unistd.h> -#include <ctype.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> - -#include "camel-nntp-store-summary.h" - -#include "camel-file-utils.h" - -#include "libedataserver/md5-utils.h" -#include "libedataserver/e-memory.h" - -#include "camel-private.h" -#include "camel-utf8.h" - -#define d(x) -#define io(x) /* io debug */ - -#define CAMEL_NNTP_STORE_SUMMARY_VERSION_0 (0) -#define CAMEL_NNTP_STORE_SUMMARY_VERSION_1 (1) - -#define CAMEL_NNTP_STORE_SUMMARY_VERSION (1) - -#define _PRIVATE(o) (((CamelNNTPStoreSummary *)(o))->priv) - -static int summary_header_load(CamelStoreSummary *, FILE *); -static int summary_header_save(CamelStoreSummary *, FILE *); - -/*static CamelStoreInfo * store_info_new(CamelStoreSummary *, const char *);*/ -static CamelStoreInfo * store_info_load(CamelStoreSummary *, FILE *); -static int store_info_save(CamelStoreSummary *, FILE *, CamelStoreInfo *); -static void store_info_free(CamelStoreSummary *, CamelStoreInfo *); - -static const char *store_info_string(CamelStoreSummary *, const CamelStoreInfo *, int); -static void store_info_set_string(CamelStoreSummary *, CamelStoreInfo *, int, const char *); - -static void camel_nntp_store_summary_class_init (CamelNNTPStoreSummaryClass *klass); -static void camel_nntp_store_summary_init (CamelNNTPStoreSummary *obj); -static void camel_nntp_store_summary_finalise (CamelObject *obj); - -static CamelStoreSummaryClass *camel_nntp_store_summary_parent; - -static void -camel_nntp_store_summary_class_init (CamelNNTPStoreSummaryClass *klass) -{ - CamelStoreSummaryClass *ssklass = (CamelStoreSummaryClass *)klass; - - ssklass->summary_header_load = summary_header_load; - ssklass->summary_header_save = summary_header_save; - - /*ssklass->store_info_new = store_info_new;*/ - ssklass->store_info_load = store_info_load; - ssklass->store_info_save = store_info_save; - ssklass->store_info_free = store_info_free; - - ssklass->store_info_string = store_info_string; - ssklass->store_info_set_string = store_info_set_string; -} - -static void -camel_nntp_store_summary_init (CamelNNTPStoreSummary *s) -{ - /*struct _CamelNNTPStoreSummaryPrivate *p; - - p = _PRIVATE(s) = g_malloc0(sizeof(*p));*/ - - ((CamelStoreSummary *) s)->store_info_size = sizeof (CamelNNTPStoreInfo); - s->version = CAMEL_NNTP_STORE_SUMMARY_VERSION; - memset (&s->last_newslist, 0, sizeof (s->last_newslist)); -} - -static void -camel_nntp_store_summary_finalise (CamelObject *obj) -{ - /*struct _CamelNNTPStoreSummaryPrivate *p;*/ - /*CamelNNTPStoreSummary *s = (CamelNNTPStoreSummary *)obj;*/ - - /*p = _PRIVATE(obj); - g_free(p);*/ -} - -CamelType -camel_nntp_store_summary_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - camel_nntp_store_summary_parent = (CamelStoreSummaryClass *)camel_store_summary_get_type(); - type = camel_type_register((CamelType)camel_nntp_store_summary_parent, "CamelNNTPStoreSummary", - sizeof (CamelNNTPStoreSummary), - sizeof (CamelNNTPStoreSummaryClass), - (CamelObjectClassInitFunc) camel_nntp_store_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_nntp_store_summary_init, - (CamelObjectFinalizeFunc) camel_nntp_store_summary_finalise); - } - - return type; -} - -/** - * camel_nntp_store_summary_new: - * - * Create a new CamelNNTPStoreSummary object. - * - * Return value: A new CamelNNTPStoreSummary widget. - **/ -CamelNNTPStoreSummary * -camel_nntp_store_summary_new (void) -{ - return (CamelNNTPStoreSummary *) camel_object_new (camel_nntp_store_summary_get_type ()); -} - -/** - * camel_nntp_store_summary_full_name: - * @s: - * @path: - * - * Retrieve a summary item by full name. - * - * A referenced to the summary item is returned, which may be - * ref'd or free'd as appropriate. - * - * Return value: The summary item, or NULL if the @full_name name - * is not available. - * It must be freed using camel_store_summary_info_free(). - **/ -CamelNNTPStoreInfo * -camel_nntp_store_summary_full_name(CamelNNTPStoreSummary *s, const char *full_name) -{ - int count, i; - CamelNNTPStoreInfo *info; - - count = camel_store_summary_count ((CamelStoreSummary *) s); - for (i = 0; i < count; i++) { - info = (CamelNNTPStoreInfo *)camel_store_summary_index ((CamelStoreSummary *) s, i); - if (info) { - if (strcmp (info->full_name, full_name) == 0) - return info; - camel_store_summary_info_free ((CamelStoreSummary *) s, (CamelStoreInfo *)info); - } - } - - return NULL; -} - -char * -camel_nntp_store_summary_full_to_path (CamelNNTPStoreSummary *s, const char *full_name, char dir_sep) -{ - char *path, *p; - int c; - const char *f; - - if (dir_sep != '/') { - p = path = g_alloca (strlen (full_name) * 3 + 1); - f = full_name; - while ((c = *f++ & 0xff)) { - if (c == dir_sep) - *p++ = '/'; - else if (c == '/' || c == '%') - p += sprintf (p, "%%%02X", c); - else - *p++ = c; - } - *p = 0; - } else - path = (char *) full_name; - - return camel_utf7_utf8 (path); -} - -static guint32 -hexnib (guint32 c) -{ - if (c >= '0' && c <= '9') - return c-'0'; - else if (c >= 'A' && c <= 'Z') - return c - 'A' + 10; - else - return 0; -} - -char * -camel_nntp_store_summary_path_to_full (CamelNNTPStoreSummary *s, const char *path, char dir_sep) -{ - unsigned char *full, *f; - guint32 c, v = 0; - const char *p; - int state=0; - char *subpath, *last = NULL; - CamelStoreInfo *si; - - /* check to see if we have a subpath of path already defined */ - subpath = g_alloca (strlen (path) + 1); - strcpy (subpath, path); - do { - si = camel_store_summary_path ((CamelStoreSummary *) s, subpath); - if (si == NULL) { - last = strrchr (subpath, '/'); - if (last) - *last = 0; - } - } while (si == NULL && last); - - /* path is already present, use the raw version we have */ - if (si && strlen (subpath) == strlen (path)) { - f = g_strdup (camel_nntp_store_info_full_name (s, si)); - camel_store_summary_info_free ((CamelStoreSummary *) s, si); - return f; - } - - f = full = g_alloca (strlen (path)*2+1); - if (si) - p = path + strlen (subpath); - else - p = path; - - while ((c = camel_utf8_getc ((const unsigned char **) &p))) { - switch (state) { - case 0: - if (c == '%') { - state = 1; - } else { - if (c == '/') - c = dir_sep; - camel_utf8_putc(&f, c); - } - break; - case 1: - state = 2; - v = hexnib (c) << 4; - break; - case 2: - state = 0; - v |= hexnib (c); - camel_utf8_putc (&f, v); - break; - } - } - camel_utf8_putc (&f, c); - - /* merge old path part if required */ - f = camel_utf8_utf7 (full); - if (si) { - full = g_strdup_printf ("%s%s", camel_nntp_store_info_full_name (s, si), f); - g_free (f); - camel_store_summary_info_free ((CamelStoreSummary *) s, si); - f = full; - } - - return f; -} - -CamelNNTPStoreInfo * -camel_nntp_store_summary_add_from_full (CamelNNTPStoreSummary *s, const char *full, char dir_sep) -{ - CamelNNTPStoreInfo *info; - char *pathu8; - int len; - char *full_name; - - d(printf("adding full name '%s' '%c'\n", full, dir_sep)); - - len = strlen (full); - full_name = g_alloca (len+1); - strcpy(full_name, full); - if (full_name[len-1] == dir_sep) - full_name[len-1] = 0; - - info = camel_nntp_store_summary_full_name (s, full_name); - if (info) { - camel_store_summary_info_free ((CamelStoreSummary *) s, (CamelStoreInfo *) info); - d(printf(" already there\n")); - return info; - } - - pathu8 = camel_nntp_store_summary_full_to_path (s, full_name, dir_sep); - - info = (CamelNNTPStoreInfo *) camel_store_summary_add_from_path ((CamelStoreSummary *) s, pathu8); - if (info) { - d(printf(" '%s' -> '%s'\n", pathu8, full_name)); - camel_store_info_set_string((CamelStoreSummary *)s, (CamelStoreInfo *)info, CAMEL_NNTP_STORE_INFO_FULL_NAME, full_name); - } else - d(printf(" failed\n")); - - return info; -} - -static int -summary_header_load (CamelStoreSummary *s, FILE *in) -{ - CamelNNTPStoreSummary *is = (CamelNNTPStoreSummary *) s; - gint32 version, nil; - - if (camel_nntp_store_summary_parent->summary_header_load ((CamelStoreSummary *) s, in) == -1 - || camel_file_util_decode_fixed_int32 (in, &version) == -1) - return -1; - - is->version = version; - - if (version < CAMEL_NNTP_STORE_SUMMARY_VERSION_0) { - g_warning("Store summary header version too low"); - return -1; - } - - if (fread (is->last_newslist, 1, NNTP_DATE_SIZE, in) < NNTP_DATE_SIZE) - return -1; - - camel_file_util_decode_fixed_int32 (in, &nil); - - return 0; -} - -static int -summary_header_save (CamelStoreSummary *s, FILE *out) -{ - CamelNNTPStoreSummary *is = (CamelNNTPStoreSummary *) s; - - /* always write as latest version */ - if (camel_nntp_store_summary_parent->summary_header_save ((CamelStoreSummary *) s, out) == -1 - || camel_file_util_encode_fixed_int32 (out, CAMEL_NNTP_STORE_SUMMARY_VERSION) == -1 - || fwrite (is->last_newslist, 1, NNTP_DATE_SIZE, out) < NNTP_DATE_SIZE - || camel_file_util_encode_fixed_int32 (out, 0) == -1) - return -1; - - return 0; -} - -static CamelStoreInfo * -store_info_load (CamelStoreSummary *s, FILE *in) -{ - CamelNNTPStoreInfo *ni; - - ni = (CamelNNTPStoreInfo *) camel_nntp_store_summary_parent->store_info_load (s, in); - if (ni) { - if (camel_file_util_decode_string (in, &ni->full_name) == -1) { - camel_store_summary_info_free (s, (CamelStoreInfo *) ni); - return NULL; - } - if (((CamelNNTPStoreSummary *)s)->version >= CAMEL_NNTP_STORE_SUMMARY_VERSION_1) { - if (camel_file_util_decode_uint32(in, &ni->first) == -1 - || camel_file_util_decode_uint32(in, &ni->last) == -1) { - camel_store_summary_info_free (s, (CamelStoreInfo *) ni); - return NULL; - } - } - /* set the URL */ - } - - return (CamelStoreInfo *) ni; -} - -static int -store_info_save (CamelStoreSummary *s, FILE *out, CamelStoreInfo *mi) -{ - CamelNNTPStoreInfo *isi = (CamelNNTPStoreInfo *)mi; - - if (camel_nntp_store_summary_parent->store_info_save (s, out, mi) == -1 - || camel_file_util_encode_string (out, isi->full_name) == -1 - || camel_file_util_encode_uint32(out, isi->first) == -1 - || camel_file_util_encode_uint32(out, isi->last) == -1) - return -1; - - return 0; -} - -static void -store_info_free (CamelStoreSummary *s, CamelStoreInfo *mi) -{ - CamelNNTPStoreInfo *nsi = (CamelNNTPStoreInfo *) mi; - - g_free (nsi->full_name); - camel_nntp_store_summary_parent->store_info_free (s, mi); -} - -static const char * -store_info_string(CamelStoreSummary *s, const CamelStoreInfo *mi, int type) -{ - CamelNNTPStoreInfo *nsi = (CamelNNTPStoreInfo *)mi; - - /* FIXME: Locks? */ - - g_assert (mi != NULL); - - switch (type) { - case CAMEL_NNTP_STORE_INFO_FULL_NAME: - return nsi->full_name; - default: - return camel_nntp_store_summary_parent->store_info_string(s, mi, type); - } -} - -static void -store_info_set_string(CamelStoreSummary *s, CamelStoreInfo *mi, int type, const char *str) -{ - CamelNNTPStoreInfo *nsi = (CamelNNTPStoreInfo *)mi; - - g_assert(mi != NULL); - - switch (type) { - case CAMEL_NNTP_STORE_INFO_FULL_NAME: - d(printf("Set full name %s -> %s\n", nsi->full_name, str)); - CAMEL_STORE_SUMMARY_LOCK(s, summary_lock); - g_free (nsi->full_name); - nsi->full_name = g_strdup (str); - CAMEL_STORE_SUMMARY_UNLOCK(s, summary_lock); - break; - default: - camel_nntp_store_summary_parent->store_info_set_string (s, mi, type, str); - break; - } -} diff --git a/camel/providers/nntp/camel-nntp-store-summary.h b/camel/providers/nntp/camel-nntp-store-summary.h deleted file mode 100644 index 2e442a8166..0000000000 --- a/camel/providers/nntp/camel-nntp-store-summary.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2002 Ximian Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* currently, this is just a straigt s/imap/nntp from the IMAP file*/ - - -#ifndef _CAMEL_NNTP_STORE_SUMMARY_H -#define _CAMEL_NNTP_STORE_SUMMARY_H - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include <camel/camel-object.h> -#include <camel/camel-store-summary.h> - -#define CAMEL_NNTP_STORE_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_nntp_store_summary_get_type (), CamelNNTPStoreSummary) -#define CAMEL_NNTP_STORE_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_nntp_store_summary_get_type (), CamelNNTPStoreSummaryClass) -#define CAMEL_IS_NNTP_STORE_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_nntp_store_summary_get_type ()) - -typedef struct _CamelNNTPStoreSummary CamelNNTPStoreSummary; -typedef struct _CamelNNTPStoreSummaryClass CamelNNTPStoreSummaryClass; - -typedef struct _CamelNNTPStoreInfo CamelNNTPStoreInfo; - -enum { - CAMEL_NNTP_STORE_INFO_FULL_NAME = CAMEL_STORE_INFO_LAST, - CAMEL_NNTP_STORE_INFO_LAST, -}; - -struct _CamelNNTPStoreInfo { - CamelStoreInfo info; - char *full_name; - guint32 first; /* from LIST or NEWGROUPS return */ - guint32 last; -}; - -#define NNTP_DATE_SIZE 14 - -struct _CamelNNTPStoreSummary { - CamelStoreSummary summary; - - struct _CamelNNTPStoreSummaryPrivate *priv; - - /* header info */ - guint32 version; /* version of base part of file */ - char last_newslist[NNTP_DATE_SIZE]; -}; - -struct _CamelNNTPStoreSummaryClass { - CamelStoreSummaryClass summary_class; -}; - -CamelType camel_nntp_store_summary_get_type (void); -CamelNNTPStoreSummary *camel_nntp_store_summary_new (void); - -/* TODO: this api needs some more work, needs to support lists */ -/*CamelNNTPStoreNamespace *camel_nntp_store_summary_namespace_new(CamelNNTPStoreSummary *s, const char *full_name, char dir_sep);*/ -/*void camel_nntp_store_summary_namespace_set(CamelNNTPStoreSummary *s, CamelNNTPStoreNamespace *ns);*/ -/*CamelNNTPStoreNamespace *camel_nntp_store_summary_namespace_find_path(CamelNNTPStoreSummary *s, const char *path);*/ -/*CamelNNTPStoreNamespace *camel_nntp_store_summary_namespace_find_full(CamelNNTPStoreSummary *s, const char *full_name);*/ - -/* helper macro's */ -#define camel_nntp_store_info_full_name(s, i) (camel_store_info_string((CamelStoreSummary *)s, (const CamelStoreInfo *)i, CAMEL_NNTP_STORE_INFO_FULL_NAME)) - -/* converts to/from utf8 canonical nasmes */ -char *camel_nntp_store_summary_full_to_path(CamelNNTPStoreSummary *s, const char *full_name, char dir_sep); - -char *camel_nntp_store_summary_path_to_full(CamelNNTPStoreSummary *s, const char *path, char dir_sep); -char *camel_nntp_store_summary_dotted_to_full(CamelNNTPStoreSummary *s, const char *dotted, char dir_sep); - -CamelNNTPStoreInfo *camel_nntp_store_summary_full_name(CamelNNTPStoreSummary *s, const char *full_name); -CamelNNTPStoreInfo *camel_nntp_store_summary_add_from_full(CamelNNTPStoreSummary *s, const char *full_name, char dir_sep); - -/* a convenience lookup function. always use this if path known */ -char *camel_nntp_store_summary_full_from_path(CamelNNTPStoreSummary *s, const char *path); - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ! _CAMEL_NNTP_STORE_SUMMARY_H */ diff --git a/camel/providers/nntp/camel-nntp-store.c b/camel/providers/nntp/camel-nntp-store.c deleted file mode 100644 index f9daad8515..0000000000 --- a/camel/providers/nntp/camel-nntp-store.c +++ /dev/null @@ -1,1391 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * - * Copyright (C) 2001-2003 Ximian, Inc. <www.ximain.com> - * - * Authors: Christopher Toshok <toshok@ximian.com> - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <unistd.h> -#include <dirent.h> -#include <errno.h> - -#include <camel/camel-url.h> -#include <camel/camel-string-utils.h> -#include <camel/camel-session.h> -#include <camel/camel-tcp-stream-raw.h> -#include <camel/camel-tcp-stream-ssl.h> - -#include <camel/camel-stream-mem.h> -#include <camel/camel-data-cache.h> - -#include <camel/camel-disco-store.h> -#include <camel/camel-disco-diary.h> -#include "camel/camel-private.h" -#include <camel/camel-debug.h> - -#include "camel-nntp-summary.h" -#include "camel-nntp-store.h" -#include "camel-nntp-store-summary.h" -#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) - -#define NNTP_PORT "119" -#define NNTPS_PORT "563" - -#define DUMP_EXTENSIONS - -static CamelDiscoStoreClass *parent_class = NULL; -static CamelServiceClass *service_class = NULL; - -/* Returns the class for a CamelNNTPStore */ -#define CNNTPS_CLASS(so) CAMEL_NNTP_STORE_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CF_CLASS(so) CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) -#define CNNTPF_CLASS(so) CAMEL_NNTP_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(so)) - -static int camel_nntp_try_authenticate (CamelNNTPStore *store, CamelException *ex); - -static void nntp_construct (CamelService *service, CamelSession *session, - CamelProvider *provider, CamelURL *url, - CamelException *ex); - - -static gboolean -nntp_can_work_offline(CamelDiscoStore *store) -{ - return TRUE; -} - -static struct { - const char *name; - int type; -} headers[] = { - { "subject", 0 }, - { "from", 0 }, - { "date", 0 }, - { "message-id", 1 }, - { "references", 0 }, - { "bytes", 2 }, -}; - -static int -xover_setup(CamelNNTPStore *store, CamelException *ex) -{ - int ret, i; - char *line; - unsigned int len; - unsigned char c, *p; - struct _xover_header *xover, *last; - - /* manual override */ - if (store->xover || getenv("CAMEL_NNTP_DISABLE_XOVER") != NULL) - return 0; - - ret = camel_nntp_raw_command_auth(store, ex, &line, "list overview.fmt"); - if (ret == -1) { - return -1; - } else if (ret != 215) - /* unsupported command? ignore */ - return 0; - - last = (struct _xover_header *)&store->xover; - - /* supported command */ - while ((ret = camel_nntp_stream_line(store->stream, (unsigned char **)&line, &len)) > 0) { - p = line; - xover = g_malloc0(sizeof(*xover)); - last->next = xover; - last = xover; - while ((c = *p++)) { - if (c == ':') { - p[-1] = 0; - for (i=0;i<sizeof(headers)/sizeof(headers[0]);i++) { - if (strcmp(line, headers[i].name) == 0) { - xover->name = headers[i].name; - if (strncmp(p, "full", 4) == 0) - xover->skip = strlen(xover->name)+1; - else - xover->skip = 0; - xover->type = headers[i].type; - break; - } - } - break; - } else { - p[-1] = camel_tolower(c); - } - } - } - - 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) -{ - CamelNNTPStore *store = (CamelNNTPStore *) service; - CamelDiscoStore *disco_store = (CamelDiscoStore*) service; - CamelStream *tcp_stream; - gboolean retval = FALSE; - unsigned char *buf; - unsigned int len; - int ret; - char *path; - - CAMEL_SERVICE_LOCK(store, connect_lock); - - /* setup store-wide cache */ - if (store->cache == NULL) { - if (store->storage_path == NULL) - goto fail; - - store->cache = camel_data_cache_new (store->storage_path, 0, ex); - if (store->cache == NULL) - goto fail; - - /* Default cache expiry - 2 weeks old, or not visited in 5 days */ - 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 (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); - } -#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 */ - } else { - tcp_stream = camel_tcp_stream_raw_new (); - } - - 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)); - - camel_object_unref (tcp_stream); - - goto fail; - } - - store->stream = (CamelNNTPStream *) camel_nntp_stream_new (tcp_stream); - camel_object_unref (tcp_stream); - - /* Read the greeting, if any. */ - if (camel_nntp_stream_line (store->stream, &buf, &len) == -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 read greeting from %s: %s"), - service->url->host, g_strerror (errno)); - - camel_object_unref (store->stream); - store->stream = NULL; - - goto fail; - } - - len = strtoul (buf, (char **) &buf, 10); - if (len != 200 && len != 201) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("NNTP server %s returned error code %d: %s"), - service->url->host, len, buf); - - camel_object_unref (store->stream); - store->stream = NULL; - - goto fail; - } - - /* if we have username, try it here */ - 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 */ - 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; - - if (xover_setup(store, ex) == -1) - goto fail; - - path = g_build_filename (store->storage_path, ".ev-journal", NULL); - disco_store->diary = camel_disco_diary_new (disco_store, path, ex); - g_free (path); - - retval = TRUE; - - g_free(store->current_folder); - store->current_folder = NULL; - - fail: - CAMEL_SERVICE_UNLOCK(store, connect_lock); - return retval; -} - -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 }, -}; - -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; - - 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 = "nntp"; - port = NNTP_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; - - ret = connect_to_server (service, ai, mode, ex); - - camel_freeaddrinfo (ai); - - return ret; -} - -static gboolean -nntp_connect_offline (CamelService *service, CamelException *ex) -{ - CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE(service); - CamelDiscoStore *disco_store = (CamelDiscoStore *) nntp_store; - char *path; - - if (nntp_store->storage_path == NULL) - return FALSE; - - /* setup store-wide cache */ - if (nntp_store->cache == NULL) { - nntp_store->cache = camel_data_cache_new (nntp_store->storage_path, 0, ex); - if (nntp_store->cache == NULL) - return FALSE; - - /* Default cache expiry - 2 weeks old, or not visited in 5 days */ - camel_data_cache_set_expire_age (nntp_store->cache, 60*60*24*14); - camel_data_cache_set_expire_access (nntp_store->cache, 60*60*24*5); - } - - path = g_build_filename (nntp_store->storage_path, ".ev-journal", NULL); - disco_store->diary = camel_disco_diary_new (disco_store, path, ex); - g_free (path); - - if (!disco_store->diary) - return FALSE; - - return TRUE; -} - -static gboolean -nntp_disconnect_online (CamelService *service, gboolean clean, CamelException *ex) -{ - CamelNNTPStore *store = CAMEL_NNTP_STORE (service); - char *line; - - CAMEL_SERVICE_LOCK(store, connect_lock); - - if (clean) { - camel_nntp_raw_command (store, ex, &line, "quit"); - camel_exception_clear(ex); - } - - if (!service_class->disconnect (service, clean, ex)) { - CAMEL_SERVICE_UNLOCK(store, connect_lock); - return FALSE; - } - - camel_object_unref (store->stream); - store->stream = NULL; - g_free(store->current_folder); - store->current_folder = NULL; - - CAMEL_SERVICE_UNLOCK(store, connect_lock); - - return TRUE; -} - -static gboolean -nntp_disconnect_offline (CamelService *service, gboolean clean, CamelException *ex) -{ - CamelDiscoStore *disco = CAMEL_DISCO_STORE(service); - - if (!service_class->disconnect (service, clean, ex)) - return FALSE; - - if (disco->diary) { - camel_object_unref (disco->diary); - disco->diary = NULL; - } - - return TRUE; -} - -static char * -nntp_store_get_name (CamelService *service, gboolean brief) -{ - if (brief) - return g_strdup_printf ("%s", service->url->host); - else - return g_strdup_printf (_("USENET News via %s"), service->url->host); - -} - -extern CamelServiceAuthType camel_nntp_password_authtype; - -static GList * -nntp_store_query_auth_types (CamelService *service, CamelException *ex) -{ - return g_list_append (NULL, &camel_nntp_password_authtype); -} - -static CamelFolder * -nntp_get_folder(CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex) -{ - CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (store); - CamelFolder *folder; - - CAMEL_SERVICE_LOCK(nntp_store, connect_lock); - - folder = camel_nntp_folder_new(store, folder_name, ex); - - CAMEL_SERVICE_UNLOCK(nntp_store, connect_lock); - - return folder; -} - -/* - * Converts a fully-fledged newsgroup name to a name in short dotted notation, - * e.g. nl.comp.os.linux.programmeren becomes n.c.o.l.programmeren - */ - -static char * -nntp_newsgroup_name_short (const char *name) -{ - char *resptr, *tmp; - const char *ptr2; - - resptr = tmp = g_malloc0 (strlen (name) + 1); - - while ((ptr2 = strchr (name, '.'))) { - if (ptr2 == name) { - name++; - continue; - } - - *resptr++ = *name; - *resptr++ = '.'; - name = ptr2 + 1; - } - - strcpy (resptr, name); - return tmp; -} - -/* - * This function converts a NNTPStoreSummary item to a FolderInfo item that - * can be returned by the get_folders() call to the store. Both structs have - * essentially the same fields. - */ - -static CamelFolderInfo * -nntp_folder_info_from_store_info (CamelNNTPStore *store, gboolean short_notation, CamelStoreInfo *si) -{ - CamelURL *base_url = ((CamelService *) store)->url; - CamelFolderInfo *fi = g_malloc0(sizeof(*fi)); - CamelURL *url; - char *path; - - fi->full_name = g_strdup (si->path); - - if (short_notation) - fi->name = nntp_newsgroup_name_short (si->path); - else - fi->name = g_strdup (si->path); - - fi->unread = si->unread; - fi->total = si->total; - path = alloca(strlen(fi->full_name)+2); - sprintf(path, "/%s", fi->full_name); - url = camel_url_new_with_base (base_url, path); - fi->uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - camel_url_free (url); - - return fi; -} - -static CamelFolderInfo * -nntp_folder_info_from_name (CamelNNTPStore *store, gboolean short_notation, const char *name) -{ - CamelFolderInfo *fi = g_malloc0(sizeof(*fi)); - CamelURL *base_url = ((CamelService *)store)->url; - CamelURL *url; - char *path; - - fi->full_name = g_strdup (name); - - if (short_notation) - fi->name = nntp_newsgroup_name_short (name); - else - fi->name = g_strdup (name); - - fi->unread = -1; - - path = alloca(strlen(fi->full_name)+2); - sprintf(path, "/%s", fi->full_name); - url = camel_url_new_with_base (base_url, path); - fi->uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - camel_url_free (url); - - return fi; -} - -/* handle list/newgroups response */ -static CamelNNTPStoreInfo * -nntp_store_info_update(CamelNNTPStore *store, char *line) -{ - CamelStoreSummary *summ = (CamelStoreSummary *)store->summary; - CamelURL *base_url = ((CamelService *)store)->url; - CamelNNTPStoreInfo *si, *fsi; - CamelURL *url; - char *relpath, *tmp; - guint32 last = 0, first = 0, new = 0; - - tmp = strchr(line, ' '); - if (tmp) - *tmp++ = 0; - - fsi = si = (CamelNNTPStoreInfo *)camel_store_summary_path((CamelStoreSummary *)store->summary, line); - if (si == NULL) { - si = (CamelNNTPStoreInfo*)camel_store_summary_info_new(summ); - - relpath = g_alloca(strlen(line)+2); - sprintf(relpath, "/%s", line); - url = camel_url_new_with_base (base_url, relpath); - si->info.uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - camel_url_free (url); - - si->info.path = g_strdup (line); - si->full_name = g_strdup (line); /* why do we keep this? */ - camel_store_summary_add((CamelStoreSummary *)store->summary, &si->info); - } else { - first = si->first; - last = si->last; - } - - if (tmp && *tmp >= '0' && *tmp <= '9') { - last = strtoul(tmp, &tmp, 10); - if (*tmp == ' ' && tmp[1] >= '0' && tmp[1] <= '9') { - first = strtoul(tmp+1, &tmp, 10); - if (*tmp == ' ' && tmp[1] != 'y') - si->info.flags |= CAMEL_STORE_INFO_FOLDER_READONLY; - } - } - - printf("store info update '%s' first '%d' last '%d'\n", line, first, last); - - if (si->last) { - if (last > si->last) - new = last-si->last; - } else { - if (last > first) - new = last - first; - } - - si->info.total = last > first?last-first:0; - si->info.unread += new; /* this is a _guess_ */ - si->last = last; - si->first = first; - - if (fsi) - camel_store_summary_info_free((CamelStoreSummary *)store->summary, &fsi->info); - else /* TODO see if we really did touch it */ - camel_store_summary_touch ((CamelStoreSummary *)store->summary); - - return si; -} - -static CamelFolderInfo * -nntp_store_get_subscribed_folder_info (CamelNNTPStore *store, const char *top, guint flags, CamelException *ex) -{ - int i; - CamelStoreInfo *si; - CamelFolderInfo *first = NULL, *last = NULL, *fi = NULL; - - /* since we do not do a tree, any request that is not for root is sure to give no results */ - if (top != NULL && top[0] != 0) - return NULL; - - for (i=0;(si = camel_store_summary_index ((CamelStoreSummary *) store->summary, i));i++) { - if (si == NULL) - continue; - - if (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) { - /* slow mode? open and update the folder, always! this will implictly update - our storeinfo too; in a very round-about way */ - if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0) { - CamelNNTPFolder *folder; - char *line; - - folder = (CamelNNTPFolder *)camel_store_get_folder((CamelStore *)store, si->path, 0, ex); - if (folder) { - CAMEL_SERVICE_LOCK(store, connect_lock); - camel_nntp_command(store, ex, folder, &line, NULL); - CAMEL_SERVICE_UNLOCK(store, connect_lock); - camel_object_unref(folder); - } - camel_exception_clear(ex); - } - fi = nntp_folder_info_from_store_info (store, store->do_short_folder_notation, si); - fi->flags |= CAMEL_FOLDER_NOINFERIORS | CAMEL_FOLDER_NOCHILDREN | CAMEL_FOLDER_SYSTEM; - if (last) - last->next = fi; - else - first = fi; - last = fi; - } - camel_store_summary_info_free ((CamelStoreSummary *) store->summary, si); - } - - return first; -} - -/* - * get folder info, using the information in our StoreSummary - */ -static CamelFolderInfo * -nntp_store_get_cached_folder_info (CamelNNTPStore *store, const char *orig_top, guint flags, CamelException *ex) -{ - int i; - int subscribed_or_flag = (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) ? 0 : 1, - root_or_flag = (orig_top == NULL || orig_top[0] == '\0') ? 1 : 0, - recursive_flag = flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE; - CamelStoreInfo *si; - CamelFolderInfo *first = NULL, *last = NULL, *fi = NULL; - char *tmpname; - char *top = g_strconcat(orig_top?orig_top:"", ".", NULL); - int toplen = strlen(top); - - for (i = 0; (si = camel_store_summary_index ((CamelStoreSummary *) store->summary, i)); i++) { - if ((subscribed_or_flag || (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED)) - && (root_or_flag || strncmp (si->path, top, toplen) == 0)) { - if (recursive_flag || strchr (si->path + toplen, '.') == NULL) { - /* add the item */ - fi = nntp_folder_info_from_store_info(store, FALSE, si); - if (!fi) - continue; - if (store->folder_hierarchy_relative) { - g_free (fi->name); - fi->name = g_strdup (si->path + ((toplen == 1) ? 0 : toplen)); - } - } else { - /* apparently, this is an indirect subitem. if it's not a subitem of - the item we added last, we need to add a portion of this item to - the list as a placeholder */ - if (!last || - strncmp(si->path, last->full_name, strlen(last->full_name)) != 0 || - si->path[strlen(last->full_name)] != '.') { - tmpname = g_strdup(si->path); - *(strchr(tmpname + toplen, '.')) = '\0'; - fi = nntp_folder_info_from_name(store, FALSE, tmpname); - fi->flags |= CAMEL_FOLDER_NOSELECT; - if (store->folder_hierarchy_relative) { - g_free(fi->name); - fi->name = g_strdup(tmpname + ((toplen==1) ? 0 : toplen)); - } - g_free(tmpname); - } else { - continue; - } - } - if (last) - last->next = fi; - else - first = fi; - last = fi; - } else if (subscribed_or_flag && first) { - /* we have already added subitems, but this item is no longer a subitem */ - camel_store_summary_info_free((CamelStoreSummary *)store->summary, si); - break; - } - camel_store_summary_info_free((CamelStoreSummary *)store->summary, si); - } - - g_free(top); - return first; -} - -/* retrieves the date from the NNTP server */ -static gboolean -nntp_get_date(CamelNNTPStore *nntp_store, CamelException *ex) -{ - unsigned char *line; - int ret = camel_nntp_command(nntp_store, ex, NULL, (char **)&line, "date"); - char *ptr; - - nntp_store->summary->last_newslist[0] = 0; - - if (ret == 111) { - ptr = line + 3; - while (*ptr == ' ' || *ptr == '\t') - ptr++; - - if (strlen (ptr) == NNTP_DATE_SIZE) { - memcpy (nntp_store->summary->last_newslist, ptr, NNTP_DATE_SIZE); - return TRUE; - } - } - return FALSE; -} - -static void -store_info_remove(void *key, void *value, void *data) -{ - CamelStoreSummary *summary = data; - CamelStoreInfo *si = value; - - camel_store_summary_remove(summary, si); -} - -static gint -store_info_sort (gconstpointer a, gconstpointer b) -{ - return strcmp ((*(CamelNNTPStoreInfo**) a)->full_name, (*(CamelNNTPStoreInfo**) b)->full_name); -} - -static CamelFolderInfo * -nntp_store_get_folder_info_all(CamelNNTPStore *nntp_store, const char *top, guint32 flags, gboolean online, CamelException *ex) -{ - CamelNNTPStoreSummary *summary = nntp_store->summary; - CamelNNTPStoreInfo *si; - unsigned int len; - unsigned char *line; - int ret = -1; - CamelFolderInfo *fi = NULL; - - CAMEL_SERVICE_LOCK(nntp_store, connect_lock); - - if (top == NULL) - top = ""; - - if (online && (top == NULL || top[0] == 0)) { - /* we may need to update */ - if (summary->last_newslist[0] != 0) { - char date[14]; - memcpy(date, summary->last_newslist + 2, 6); /* YYMMDDD */ - date[6] = ' '; - memcpy(date + 7, summary->last_newslist + 8, 6); /* HHMMSS */ - date[13] = '\0'; - - if (!nntp_get_date (nntp_store, ex)) - goto error; - - ret = camel_nntp_command (nntp_store, ex, NULL, (char **) &line, "newgroups %s", date); - if (ret == -1) - goto error; - else if (ret != 231) { - /* newgroups not supported :S so reload the complete list */ - summary->last_newslist[0] = 0; - goto do_complete_list; - } - - while ((ret = camel_nntp_stream_line (nntp_store->stream, &line, &len)) > 0) - nntp_store_info_update(nntp_store, line); - } else { - GHashTable *all; - int i; - - do_complete_list: - /* seems we do need a complete list */ - /* at first, we do a DATE to find out the last load occasion */ - if (!nntp_get_date (nntp_store, ex)) - goto error; - - ret = camel_nntp_command (nntp_store, ex, NULL, (char **)&line, "list"); - if (ret == -1) - goto error; - else if (ret != 215) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_INVALID, - _("Error retrieving newsgroups:\n\n%s"), line); - goto error; - } - - all = g_hash_table_new(g_str_hash, g_str_equal); - for (i = 0; (si = (CamelNNTPStoreInfo *)camel_store_summary_index ((CamelStoreSummary *)nntp_store->summary, i)); i++) - g_hash_table_insert(all, si->info.path, si); - - while ((ret = camel_nntp_stream_line(nntp_store->stream, &line, &len)) > 0) { - si = nntp_store_info_update(nntp_store, line); - g_hash_table_remove(all, si->info.path); - } - - g_hash_table_foreach(all, store_info_remove, nntp_store->summary); - g_hash_table_destroy(all); - } - - /* sort the list */ - g_ptr_array_sort (CAMEL_STORE_SUMMARY (nntp_store->summary)->folders, store_info_sort); - if (ret < 0) - goto error; - - camel_store_summary_save ((CamelStoreSummary *) nntp_store->summary); - } - - fi = nntp_store_get_cached_folder_info (nntp_store, top, flags, ex); - error: - CAMEL_SERVICE_UNLOCK(nntp_store, connect_lock); - - return fi; -} - -static CamelFolderInfo * -nntp_get_folder_info (CamelStore *store, const char *top, guint32 flags, gboolean online, CamelException *ex) -{ - CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE(store); - CamelFolderInfo *first = NULL; - - dd(printf("g_f_i: fast %d subscr %d recursive %d online %d top \"%s\"\n", - flags & CAMEL_STORE_FOLDER_INFO_FAST, - flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, - flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE, - online, - top?top:"")); - - if (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) - first = nntp_store_get_subscribed_folder_info (nntp_store, top, flags, ex); - else - first = nntp_store_get_folder_info_all (nntp_store, top, flags, online, ex); - - return first; -} - -static CamelFolderInfo * -nntp_get_folder_info_online (CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - return nntp_get_folder_info (store, top, flags, TRUE, ex); -} - -static CamelFolderInfo * -nntp_get_folder_info_offline(CamelStore *store, const char *top, guint32 flags, CamelException *ex) -{ - return nntp_get_folder_info (store, top, flags, FALSE, ex); -} - -static gboolean -nntp_store_folder_subscribed (CamelStore *store, const char *folder_name) -{ - CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (store); - CamelStoreInfo *si; - int truth = FALSE; - - si = camel_store_summary_path ((CamelStoreSummary *) nntp_store->summary, folder_name); - if (si) { - truth = (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) != 0; - camel_store_summary_info_free ((CamelStoreSummary *) nntp_store->summary, si); - } - - return truth; -} - -static void -nntp_store_subscribe_folder (CamelStore *store, const char *folder_name, - CamelException *ex) -{ - CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE(store); - CamelStoreInfo *si; - CamelFolderInfo *fi; - - CAMEL_SERVICE_LOCK(nntp_store, connect_lock); - - si = camel_store_summary_path(CAMEL_STORE_SUMMARY(nntp_store->summary), folder_name); - if (!si) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID, - _("You cannot subscribe to this newsgroup:\n\n" - "No such newsgroup. The selected item is a probably a parent folder.")); - } else { - if (!(si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED)) { - si->flags |= CAMEL_STORE_INFO_FOLDER_SUBSCRIBED; - fi = nntp_folder_info_from_store_info(nntp_store, nntp_store->do_short_folder_notation, si); - fi->flags |= CAMEL_FOLDER_NOINFERIORS | CAMEL_FOLDER_NOCHILDREN; - camel_store_summary_touch ((CamelStoreSummary *) nntp_store->summary); - camel_store_summary_save ((CamelStoreSummary *) nntp_store->summary); - CAMEL_SERVICE_UNLOCK(nntp_store, connect_lock); - camel_object_trigger_event ((CamelObject *) nntp_store, "folder_subscribed", fi); - camel_folder_info_free (fi); - return; - } - } - - CAMEL_SERVICE_UNLOCK(nntp_store, connect_lock); -} - -static void -nntp_store_unsubscribe_folder (CamelStore *store, const char *folder_name, - CamelException *ex) -{ - CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE(store); - CamelFolderInfo *fi; - CamelStoreInfo *fitem; - CAMEL_SERVICE_LOCK(nntp_store, connect_lock); - - fitem = camel_store_summary_path(CAMEL_STORE_SUMMARY(nntp_store->summary), folder_name); - - if (!fitem) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID, - _("You cannot unsubscribe to this newsgroup:\n\n" - "newsgroup does not exist!")); - } else { - if (fitem->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) { - fitem->flags &= ~CAMEL_STORE_INFO_FOLDER_SUBSCRIBED; - fi = nntp_folder_info_from_store_info (nntp_store, nntp_store->do_short_folder_notation, fitem); - camel_store_summary_touch ((CamelStoreSummary *) nntp_store->summary); - camel_store_summary_save ((CamelStoreSummary *) nntp_store->summary); - CAMEL_SERVICE_UNLOCK(nntp_store, connect_lock); - camel_object_trigger_event ((CamelObject *) nntp_store, "folder_unsubscribed", fi); - camel_folder_info_free (fi); - return; - } - } - - CAMEL_SERVICE_UNLOCK(nntp_store, connect_lock); -} - -/* stubs for various folder operations we're not implementing */ - -static CamelFolderInfo * -nntp_create_folder (CamelStore *store, const char *parent_name, - const char *folder_name, CamelException *ex) -{ - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID, - _("You cannot create a folder in a News store: subscribe instead.")); - return NULL; -} - -static void -nntp_rename_folder (CamelStore *store, const char *old_name, const char *new_name_in, CamelException *ex) -{ - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID, - _("You cannot rename a folder in a News store.")); -} - -static void -nntp_delete_folder (CamelStore *store, const char *folder_name, CamelException *ex) -{ - nntp_store_subscribe_folder (store, folder_name, ex); - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID, - _("You cannot remove a folder in a News store: unsubscribe instead.")); - return; -} - -static void -nntp_store_finalize (CamelObject *object) -{ - /* call base finalize */ - CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (object); - struct _CamelNNTPStorePrivate *p = nntp_store->priv; - struct _xover_header *xover, *xn; - - camel_service_disconnect ((CamelService *)object, TRUE, NULL); - - if (nntp_store->summary) { - camel_store_summary_save ((CamelStoreSummary *) nntp_store->summary); - camel_object_unref (nntp_store->summary); - } - - camel_object_unref (nntp_store->mem); - nntp_store->mem = NULL; - if (nntp_store->stream) - camel_object_unref (nntp_store->stream); - - if (nntp_store->base_url) - g_free (nntp_store->base_url); - if (nntp_store->storage_path) - g_free (nntp_store->storage_path); - - xover = nntp_store->xover; - while (xover) { - xn = xover->next; - g_free(xover); - xover = xn; - } - - g_free(p); -} - -static void -nntp_store_class_init (CamelNNTPStoreClass *camel_nntp_store_class) -{ - CamelDiscoStoreClass *camel_disco_store_class = CAMEL_DISCO_STORE_CLASS (camel_nntp_store_class); - CamelStoreClass *camel_store_class = CAMEL_STORE_CLASS (camel_nntp_store_class); - CamelServiceClass *camel_service_class = CAMEL_SERVICE_CLASS (camel_nntp_store_class); - - parent_class = CAMEL_DISCO_STORE_CLASS (camel_type_get_global_classfuncs (camel_disco_store_get_type ())); - service_class = CAMEL_SERVICE_CLASS (camel_type_get_global_classfuncs (camel_service_get_type ())); - - /* virtual method overload */ - camel_service_class->construct = nntp_construct; - camel_service_class->query_auth_types = nntp_store_query_auth_types; - camel_service_class->get_name = nntp_store_get_name; - - camel_disco_store_class->can_work_offline = nntp_can_work_offline; - camel_disco_store_class->connect_online = nntp_connect_online; - camel_disco_store_class->connect_offline = nntp_connect_offline; - camel_disco_store_class->disconnect_online = nntp_disconnect_online; - camel_disco_store_class->disconnect_offline = nntp_disconnect_offline; - camel_disco_store_class->get_folder_online = nntp_get_folder; - camel_disco_store_class->get_folder_resyncing = nntp_get_folder; - camel_disco_store_class->get_folder_offline = nntp_get_folder; - - camel_disco_store_class->get_folder_info_online = nntp_get_folder_info_online; - camel_disco_store_class->get_folder_info_resyncing = nntp_get_folder_info_online; - camel_disco_store_class->get_folder_info_offline = nntp_get_folder_info_offline; - - camel_store_class->free_folder_info = camel_store_free_folder_info_full; - - camel_store_class->folder_subscribed = nntp_store_folder_subscribed; - camel_store_class->subscribe_folder = nntp_store_subscribe_folder; - camel_store_class->unsubscribe_folder = nntp_store_unsubscribe_folder; - - camel_store_class->create_folder = nntp_create_folder; - camel_store_class->delete_folder = nntp_delete_folder; - camel_store_class->rename_folder = nntp_rename_folder; -} - -/* construction function in which we set some basic store properties */ -static void -nntp_construct (CamelService *service, CamelSession *session, - CamelProvider *provider, CamelURL *url, - CamelException *ex) -{ - CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE(service); - CamelURL *summary_url; - char *tmp; - - /* construct the parent first */ - CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); - if (camel_exception_is_set (ex)) - return; - - /* find out the storage path, base url */ - nntp_store->storage_path = camel_session_get_storage_path (session, service, ex); - if (!nntp_store->storage_path) - return; - - /* FIXME */ - nntp_store->base_url = camel_url_to_string (service->url, (CAMEL_URL_HIDE_PASSWORD | - CAMEL_URL_HIDE_PARAMS | - CAMEL_URL_HIDE_AUTH)); - - tmp = g_build_filename (nntp_store->storage_path, ".ev-store-summary", NULL); - nntp_store->summary = camel_nntp_store_summary_new (); - camel_store_summary_set_filename ((CamelStoreSummary *) nntp_store->summary, tmp); - summary_url = camel_url_new (nntp_store->base_url, NULL); - camel_store_summary_set_uri_base ((CamelStoreSummary *) nntp_store->summary, summary_url); - g_free (tmp); - - camel_url_free (summary_url); - if (camel_store_summary_load ((CamelStoreSummary *)nntp_store->summary) == 0) - ; - - /* get options */ - if (camel_url_get_param (url, "show_short_notation")) - nntp_store->do_short_folder_notation = TRUE; - else - nntp_store->do_short_folder_notation = FALSE; - if (camel_url_get_param (url, "folder_hierarchy_relative")) - nntp_store->folder_hierarchy_relative = TRUE; - else - nntp_store->folder_hierarchy_relative = FALSE; -} - - -static void -nntp_store_init (gpointer object, gpointer klass) -{ - CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE(object); - CamelStore *store = CAMEL_STORE (object); - struct _CamelNNTPStorePrivate *p; - - store->flags = CAMEL_STORE_SUBSCRIPTIONS; - - nntp_store->mem = (CamelStreamMem *)camel_stream_mem_new(); - - p = nntp_store->priv = g_malloc0(sizeof(*p)); -} - -CamelType -camel_nntp_store_get_type (void) -{ - static CamelType camel_nntp_store_type = CAMEL_INVALID_TYPE; - - if (camel_nntp_store_type == CAMEL_INVALID_TYPE) { - camel_nntp_store_type = - camel_type_register (CAMEL_DISCO_STORE_TYPE, - "CamelNNTPStore", - sizeof (CamelNNTPStore), - sizeof (CamelNNTPStoreClass), - (CamelObjectClassInitFunc) nntp_store_class_init, - NULL, - (CamelObjectInitFunc) nntp_store_init, - (CamelObjectFinalizeFunc) nntp_store_finalize); - } - - return camel_nntp_store_type; -} - -static int -camel_nntp_try_authenticate (CamelNNTPStore *store, CamelException *ex) -{ - CamelService *service = (CamelService *) store; - CamelSession *session = camel_service_get_session (service); - int ret; - char *line = NULL; - - if (!service->url->user) { - camel_exception_setv(ex, CAMEL_EXCEPTION_INVALID_PARAM, - _("Authentication requested but no username provided")); - return -1; - } - - /* if nessecary, prompt for the password */ - if (!service->url->passwd) { - char *prompt, *base; - retry: - base = g_strdup_printf (_("Please enter the NNTP password for %s@%s"), - service->url->user, - service->url->host); - if (line) { - char *top = g_strdup_printf(_("Cannot authenticate to server: %s"), line); - - prompt = g_strdup_printf("%s\n\n%s", top, base); - g_free(top); - } else { - prompt = base; - base = NULL; - } - - service->url->passwd = - camel_session_get_password (session, service, NULL, - prompt, "password", CAMEL_SESSION_PASSWORD_SECRET, ex); - g_free(prompt); - g_free(base); - - if (!service->url->passwd) - return -1; - } - - /* now, send auth info (currently, only authinfo user/pass is supported) */ - ret = camel_nntp_raw_command(store, ex, &line, "authinfo user %s", service->url->user); - if (ret == NNTP_AUTH_CONTINUE) - ret = camel_nntp_raw_command(store, ex, &line, "authinfo pass %s", service->url->passwd); - - if (ret != NNTP_AUTH_ACCEPTED) { - if (ret != -1) { - /* Need to forget the password here since we have no context on it */ - camel_session_forget_password(session, service, NULL, "password", ex); - goto retry; - } - return -1; - } - - return ret; -} - -/* Enter owning lock */ -int -camel_nntp_raw_commandv (CamelNNTPStore *store, CamelException *ex, char **line, const char *fmt, va_list ap) -{ - const unsigned char *p, *ps; - unsigned char c; - char *s; - int d; - unsigned int u, u2; - - e_mutex_assert_locked(((CamelService *)store)->priv->connect_lock); - g_assert(store->stream->mode != CAMEL_NNTP_STREAM_DATA); - - camel_nntp_stream_set_mode(store->stream, CAMEL_NNTP_STREAM_LINE); - - ps = p = fmt; - while ((c = *p++)) { - switch (c) { - case '%': - c = *p++; - camel_stream_write ((CamelStream *) store->mem, ps, p - ps - (c == '%' ? 1 : 2)); - ps = p; - switch (c) { - case 's': - s = va_arg(ap, char *); - camel_stream_write((CamelStream *)store->mem, s, strlen(s)); - break; - case 'd': - d = va_arg(ap, int); - camel_stream_printf((CamelStream *)store->mem, "%d", d); - break; - case 'u': - u = va_arg(ap, unsigned int); - camel_stream_printf((CamelStream *)store->mem, "%u", u); - break; - case 'm': - s = va_arg(ap, char *); - camel_stream_printf((CamelStream *)store->mem, "<%s>", s); - break; - case 'r': - u = va_arg(ap, unsigned int); - u2 = va_arg(ap, unsigned int); - if (u == u2) - camel_stream_printf((CamelStream *)store->mem, "%u", u); - else - camel_stream_printf((CamelStream *)store->mem, "%u-%u", u, u2); - break; - default: - g_warning("Passing unknown format to nntp_command: %c\n", c); - g_assert(0); - } - } - } - - camel_stream_write ((CamelStream *) store->mem, ps, p-ps-1); - dd(printf("NNTP_COMMAND: '%.*s'\n", (int)store->mem->buffer->len, store->mem->buffer->data)); - camel_stream_write ((CamelStream *) store->mem, "\r\n", 2); - - if (camel_stream_write((CamelStream *) store->stream, store->mem->buffer->data, store->mem->buffer->len) == -1) - goto ioerror; - - /* FIXME: hack */ - camel_stream_reset ((CamelStream *) store->mem); - g_byte_array_set_size (store->mem->buffer, 0); - - if (camel_nntp_stream_line (store->stream, (unsigned char **) line, &u) == -1) - goto ioerror; - - u = strtoul (*line, NULL, 10); - - /* Handle all switching to data mode here, to make callers job easier */ - if (u == 215 || (u >= 220 && u <=224) || (u >= 230 && u <= 231)) - camel_nntp_stream_set_mode(store->stream, CAMEL_NNTP_STREAM_DATA); - - return u; - -ioerror: - if (errno == EINTR) - camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled.")); - else - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("NNTP Command failed: %s"), g_strerror(errno)); - return -1; -} - -int -camel_nntp_raw_command(CamelNNTPStore *store, CamelException *ex, char **line, const char *fmt, ...) -{ - int ret; - va_list ap; - - va_start(ap, fmt); - ret = camel_nntp_raw_commandv(store, ex, line, fmt, ap); - va_end(ap); - - return ret; -} - -/* use this where you also need auth to be handled, i.e. most cases where you'd try raw command */ -int -camel_nntp_raw_command_auth(CamelNNTPStore *store, CamelException *ex, char **line, const char *fmt, ...) -{ - int ret, retry, go; - va_list ap; - - retry = 0; - - do { - go = FALSE; - retry++; - - va_start(ap, fmt); - ret = camel_nntp_raw_commandv(store, ex, line, fmt, ap); - va_end(ap); - - if (ret == NNTP_AUTH_REQUIRED) { - if (camel_nntp_try_authenticate(store, ex) != NNTP_AUTH_ACCEPTED) - return -1; - go = TRUE; - } - } while (retry < 3 && go); - - return ret; -} - -int -camel_nntp_command (CamelNNTPStore *store, CamelException *ex, CamelNNTPFolder *folder, char **line, const char *fmt, ...) -{ - const unsigned char *p; - va_list ap; - int ret, retry; - unsigned int u; - - e_mutex_assert_locked(((CamelService *)store)->priv->connect_lock); - - if (((CamelDiscoStore *)store)->status == CAMEL_DISCO_STORE_OFFLINE) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SERVICE_NOT_CONNECTED, - _("Not connected.")); - return -1; - } - - retry = 0; - do { - retry ++; - - if (store->stream == NULL - && !camel_service_connect (CAMEL_SERVICE (store), ex)) - return -1; - - /* Check for unprocessed data, ! */ - if (store->stream->mode == CAMEL_NNTP_STREAM_DATA) { - g_warning("Unprocessed data left in stream, flushing"); - while (camel_nntp_stream_getd(store->stream, (unsigned char **)&p, &u) > 0) - ; - } - camel_nntp_stream_set_mode(store->stream, CAMEL_NNTP_STREAM_LINE); - - if (folder != NULL - && (store->current_folder == NULL || strcmp(store->current_folder, ((CamelFolder *)folder)->full_name) != 0)) { - ret = camel_nntp_raw_command_auth(store, ex, line, "group %s", ((CamelFolder *)folder)->full_name); - if (ret == 211) { - g_free(store->current_folder); - store->current_folder = g_strdup(((CamelFolder *)folder)->full_name); - camel_nntp_folder_selected(folder, *line, ex); - if (camel_exception_is_set(ex)) { - ret = -1; - goto error; - } - } else { - goto error; - } - } - - /* dummy fmt, we just wanted to select the folder */ - if (fmt == NULL) - return 0; - - va_start(ap, fmt); - ret = camel_nntp_raw_commandv(store, ex, line, fmt, ap); - va_end(ap); - error: - switch (ret) { - case NNTP_AUTH_REQUIRED: - if (camel_nntp_try_authenticate(store, ex) != NNTP_AUTH_ACCEPTED) - return -1; - retry--; - ret = -1; - continue; - case 411: /* no such group */ - camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID, - _("No such folder: %s"), line); - return -1; - case 400: /* service discontinued */ - case 401: /* wrong client state - this should quit but this is what the old code did */ - case 503: /* information not available - this should quit but this is what the old code did (?) */ - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); - ret = -1; - continue; - case -1: /* i/o error */ - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); - if (camel_exception_get_id(ex) == CAMEL_EXCEPTION_USER_CANCEL || retry >= 3) - return -1; - camel_exception_clear(ex); - break; - } - } while (ret == -1 && retry < 3); - - return ret; -} diff --git a/camel/providers/nntp/camel-nntp-store.h b/camel/providers/nntp/camel-nntp-store.h deleted file mode 100644 index a9bd682cbd..0000000000 --- a/camel/providers/nntp/camel-nntp-store.h +++ /dev/null @@ -1,114 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-store.h : class for an nntp store */ - -/* - * - * Copyright (C) 2000 Ximian, Inc. <toshok@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_NNTP_STORE_H -#define CAMEL_NNTP_STORE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include <camel/camel-disco-store.h> - -#include "camel-nntp-stream.h" -#include "camel-nntp-store-summary.h" - -struct _CamelNNTPFolder; -struct _CamelException; - -#define CAMEL_NNTP_STORE_TYPE (camel_nntp_store_get_type ()) -#define CAMEL_NNTP_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_NNTP_STORE_TYPE, CamelNNTPStore)) -#define CAMEL_NNTP_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_NNTP_STORE_TYPE, CamelNNTPStoreClass)) -#define CAMEL_IS_NNTP_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_NNTP_STORE_TYPE)) - -#define CAMEL_NNTP_EXT_SEARCH (1<<0) -#define CAMEL_NNTP_EXT_SETGET (1<<1) -#define CAMEL_NNTP_EXT_OVER (1<<2) -#define CAMEL_NNTP_EXT_XPATTEXT (1<<3) -#define CAMEL_NNTP_EXT_XACTIVE (1<<4) -#define CAMEL_NNTP_EXT_LISTMOTD (1<<5) -#define CAMEL_NNTP_EXT_LISTSUBSCR (1<<6) -#define CAMEL_NNTP_EXT_LISTPNAMES (1<<7) - -typedef struct _CamelNNTPStore CamelNNTPStore; -typedef struct _CamelNNTPStoreClass CamelNNTPStoreClass; - -enum _xover_t { - XOVER_STRING = 0, - XOVER_MSGID, - XOVER_SIZE, -}; - -struct _xover_header { - struct _xover_header *next; - - const char *name; - unsigned int skip:8; - enum _xover_t type:8; -}; - -struct _CamelNNTPStore { - CamelDiscoStore parent_object; - - struct _CamelNNTPStorePrivate *priv; - - guint32 extensions; - - unsigned int posting_allowed:1; - unsigned int do_short_folder_notation:1; - unsigned int folder_hierarchy_relative:1; - - struct _CamelNNTPStoreSummary *summary; - - struct _CamelNNTPStream *stream; - struct _CamelStreamMem *mem; - - struct _CamelDataCache *cache; - - char *current_folder, *storage_path, *base_url; - - struct _xover_header *xover; -}; - -struct _CamelNNTPStoreClass { - CamelDiscoStoreClass parent_class; - -}; - -/* Standard Camel function */ -CamelType camel_nntp_store_get_type (void); - -int camel_nntp_raw_commandv (CamelNNTPStore *store, struct _CamelException *ex, char **line, const char *fmt, va_list ap); -int camel_nntp_raw_command(CamelNNTPStore *store, struct _CamelException *ex, char **line, const char *fmt, ...); -int camel_nntp_raw_command_auth(CamelNNTPStore *store, struct _CamelException *ex, char **line, const char *fmt, ...); -int camel_nntp_command (CamelNNTPStore *store, struct _CamelException *ex, struct _CamelNNTPFolder *folder, char **line, const char *fmt, ...); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_NNTP_STORE_H */ - - diff --git a/camel/providers/nntp/camel-nntp-stream.c b/camel/providers/nntp/camel-nntp-stream.c deleted file mode 100644 index 244b67acb1..0000000000 --- a/camel/providers/nntp/camel-nntp-stream.c +++ /dev/null @@ -1,464 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Author: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <errno.h> - -#include <string.h> -#include <stdio.h> - -#include <glib.h> - -#include "camel-nntp-stream.h" -#include "camel-debug.h" - -#define dd(x) (camel_debug("nntp:stream")?(x):0) - -static CamelObjectClass *parent_class = NULL; - -/* Returns the class for a CamelStream */ -#define CS_CLASS(so) CAMEL_NNTP_STREAM_CLASS(CAMEL_OBJECT_GET_CLASS(so)) - -#define CAMEL_NNTP_STREAM_SIZE (4096) -#define CAMEL_NNTP_STREAM_LINE_SIZE (1024) /* maximum line size */ - -static int -stream_fill(CamelNNTPStream *is) -{ - int left = 0; - - if (is->source) { - left = is->end - is->ptr; - memcpy(is->buf, is->ptr, left); - is->end = is->buf + left; - is->ptr = is->buf; - left = camel_stream_read(is->source, is->end, CAMEL_NNTP_STREAM_SIZE - (is->end - is->buf)); - if (left > 0) { - is->end += left; - 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; - } - } - - return 0; -} - -static ssize_t -stream_read(CamelStream *stream, char *buffer, size_t n) -{ - CamelNNTPStream *is = (CamelNNTPStream *)stream; - char *o, *oe; - unsigned char *p, *e, c; - int state; - - if (is->mode != CAMEL_NNTP_STREAM_DATA || n == 0) - return 0; - - o = buffer; - oe = buffer + n; - state = is->state; - - /* Need to copy/strip '.'s and whatnot */ - p = is->ptr; - e = is->end; - - switch(state) { - state_0: - case 0: /* start of line, always read at least 3 chars */ - while (e - p < 3) { - is->ptr = p; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } - if (p[0] == '.') { - if (p[1] == '\r' && p[2] == '\n') { - is->ptr = p+3; - is->mode = CAMEL_NNTP_STREAM_EOD; - is->state = 0; - dd(printf("NNTP_STREAM_READ(%d):\n%.*s\n", o-buffer, o-buffer, buffer)); - return o-buffer; - } - p++; - } - state = 1; - /* FALLS THROUGH */ - case 1: /* looking for next sol */ - while (o < oe) { - c = *p++; - if (c == '\n') { - /* end of input sentinal check */ - if (p > e) { - is->ptr = e; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } else { - *o++ = '\n'; - state = 0; - goto state_0; - } - } else if (c != '\r') { - *o++ = c; - } - } - break; - } - - is->ptr = p; - is->state = state; - - dd(printf("NNTP_STREAM_READ(%d):\n%.*s\n", o-buffer, o-buffer, buffer)); - - return o-buffer; -} - -static ssize_t -stream_write(CamelStream *stream, const char *buffer, size_t n) -{ - CamelNNTPStream *is = (CamelNNTPStream *)stream; - - return camel_stream_write(is->source, buffer, n); -} - -static int -stream_close(CamelStream *stream) -{ - /* nop? */ - return 0; -} - -static int -stream_flush(CamelStream *stream) -{ - /* nop? */ - return 0; -} - -static gboolean -stream_eos(CamelStream *stream) -{ - CamelNNTPStream *is = (CamelNNTPStream *)stream; - - return is->mode != CAMEL_NNTP_STREAM_DATA; -} - -static int -stream_reset(CamelStream *stream) -{ - /* nop? reset literal mode? */ - return 0; -} - -static void -camel_nntp_stream_class_init (CamelStreamClass *camel_nntp_stream_class) -{ - CamelStreamClass *camel_stream_class = (CamelStreamClass *)camel_nntp_stream_class; - - parent_class = camel_type_get_global_classfuncs( CAMEL_OBJECT_TYPE ); - - /* virtual method definition */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->close = stream_close; - camel_stream_class->flush = stream_flush; - camel_stream_class->eos = stream_eos; - camel_stream_class->reset = stream_reset; -} - -static void -camel_nntp_stream_init(CamelNNTPStream *is, CamelNNTPStreamClass *isclass) -{ - /* +1 is room for appending a 0 if we need to for a line */ - is->ptr = is->end = is->buf = g_malloc(CAMEL_NNTP_STREAM_SIZE+1); - is->lineptr = is->linebuf = g_malloc(CAMEL_NNTP_STREAM_LINE_SIZE+1); - is->lineend = is->linebuf + CAMEL_NNTP_STREAM_LINE_SIZE; - - /* init sentinal */ - is->ptr[0] = '\n'; - - is->state = 0; - is->mode = CAMEL_NNTP_STREAM_LINE; -} - -static void -camel_nntp_stream_finalise(CamelNNTPStream *is) -{ - g_free(is->buf); - g_free(is->linebuf); - if (is->source) - camel_object_unref((CamelObject *)is->source); -} - -CamelType -camel_nntp_stream_get_type (void) -{ - static CamelType camel_nntp_stream_type = CAMEL_INVALID_TYPE; - - if (camel_nntp_stream_type == CAMEL_INVALID_TYPE) { - camel_nntp_stream_type = camel_type_register( camel_stream_get_type(), - "CamelNNTPStream", - sizeof( CamelNNTPStream ), - sizeof( CamelNNTPStreamClass ), - (CamelObjectClassInitFunc) camel_nntp_stream_class_init, - NULL, - (CamelObjectInitFunc) camel_nntp_stream_init, - (CamelObjectFinalizeFunc) camel_nntp_stream_finalise ); - } - - return camel_nntp_stream_type; -} - -/** - * camel_nntp_stream_new: - * - * Returns a NULL stream. A null stream is always at eof, and - * always returns success for all reads and writes. - * - * Return value: the stream - **/ -CamelStream * -camel_nntp_stream_new(CamelStream *source) -{ - CamelNNTPStream *is; - - is = (CamelNNTPStream *)camel_object_new(camel_nntp_stream_get_type ()); - camel_object_ref((CamelObject *)source); - is->source = source; - - return (CamelStream *)is; -} - -/* Get one line from the nntp stream */ -int -camel_nntp_stream_line(CamelNNTPStream *is, unsigned char **data, unsigned int *len) -{ - register unsigned char c, *p, *o, *oe; - int newlen, oldlen; - unsigned char *e; - - if (is->mode == CAMEL_NNTP_STREAM_EOD) { - *data = is->linebuf; - *len = 0; - return 0; - } - - o = is->linebuf; - oe = is->lineend - 1; - p = is->ptr; - e = is->end; - - /* Data mode, convert leading '..' to '.', and stop when we reach a solitary '.' */ - if (is->mode == CAMEL_NNTP_STREAM_DATA) { - /* need at least 3 chars in buffer */ - while (e-p < 3) { - is->ptr = p; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } - - /* check for isolated '.\r\n' or begging of line '.' */ - if (p[0] == '.') { - if (p[1] == '\r' && p[2] == '\n') { - is->ptr = p+3; - is->mode = CAMEL_NNTP_STREAM_EOD; - *data = is->linebuf; - *len = 0; - is->linebuf[0] = 0; - - dd(printf("NNTP_STREAM_LINE(END)\n")); - - return 0; - } - p++; - } - } - - while (1) { - while (o < oe) { - c = *p++; - if (c == '\n') { - /* sentinal? */ - if (p> e) { - is->ptr = e; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } else { - is->ptr = p; - *data = is->linebuf; - *len = o - is->linebuf; - *o = 0; - - dd(printf("NNTP_STREAM_LINE(%d): '%s'\n", *len, *data)); - - return 1; - } - } else if (c != '\r') { - *o++ = c; - } - } - - /* limit this for bad server data? */ - oldlen = o - is->linebuf; - newlen = (is->lineend - is->linebuf) * 3 / 2; - is->lineptr = is->linebuf = g_realloc(is->linebuf, newlen); - is->lineend = is->linebuf + newlen; - oe = is->lineend - 1; - o = is->linebuf + oldlen; - } - - return -1; -} - -/* returns -1 on error, 0 if last lot of data, >0 if more remaining */ -int camel_nntp_stream_gets(CamelNNTPStream *is, unsigned char **start, unsigned int *len) -{ - int max; - unsigned char *end; - - *len = 0; - - max = is->end - is->ptr; - if (max == 0) { - max = stream_fill(is); - if (max <= 0) - return max; - } - - *start = is->ptr; - end = memchr(is->ptr, '\n', max); - if (end) - max = (end - is->ptr) + 1; - *start = is->ptr; - *len = max; - is->ptr += max; - - dd(printf("NNTP_STREAM_GETS(%s,%d): '%.*s'\n", end==NULL?"more":"last", *len, (int)*len, *start)); - - return end == NULL?1:0; -} - -void camel_nntp_stream_set_mode(CamelNNTPStream *is, camel_nntp_stream_mode_t mode) -{ - is->mode = mode; -} - -/* returns -1 on erorr, 0 if last data, >0 if more data left */ -int camel_nntp_stream_getd(CamelNNTPStream *is, unsigned char **start, unsigned int *len) -{ - unsigned char *p, *e, *s; - int state; - - *len = 0; - - if (is->mode == CAMEL_NNTP_STREAM_EOD) - return 0; - - if (is->mode == CAMEL_NNTP_STREAM_LINE) { - g_warning("nntp_stream reading data in line mode\n"); - return 0; - } - - state = is->state; - p = is->ptr; - e = is->end; - - while (e - p < 3) { - is->ptr = p; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } - - s = p; - - do { - switch(state) { - case 0: - /* check leading '.', ... */ - if (p[0] == '.') { - if (p[1] == '\r' && p[2] == '\n') { - is->ptr = p+3; - *len = p-s; - *start = s; - is->mode = CAMEL_NNTP_STREAM_EOD; - is->state = 0; - - dd(printf("NNTP_STREAM_GETD(%s,%d): '%.*s'\n", "last", *len, (int)*len, *start)); - - return 0; - } - - /* If at start, just skip '.', else return data upto '.' but skip it */ - if (p == s) { - s++; - p++; - } else { - is->ptr = p+1; - *len = p-s; - *start = s; - is->state = 1; - - dd(printf("NNTP_STREAM_GETD(%s,%d): '%.*s'\n", "more", *len, (int)*len, *start)); - - return 1; - } - } - state = 1; - case 1: - /* Scan for sentinal */ - while ((*p++)!='\n') - ; - - if (p > e) { - p = e; - } else { - state = 0; - } - break; - } - } while ((e-p) >= 3); - - is->state = state; - is->ptr = p; - *len = p-s; - *start = s; - - dd(printf("NNTP_STREAM_GETD(%s,%d): '%.*s'\n", "more", *len, (int)*len, *start)); - return 1; -} - diff --git a/camel/providers/nntp/camel-nntp-stream.h b/camel/providers/nntp/camel-nntp-stream.h deleted file mode 100644 index eef217cef2..0000000000 --- a/camel/providers/nntp/camel-nntp-stream.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2001 Ximian Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_NNTP_STREAM_H -#define _CAMEL_NNTP_STREAM_H - -#include <camel/camel-stream.h> - -#define CAMEL_NNTP_STREAM(obj) CAMEL_CHECK_CAST (obj, camel_nntp_stream_get_type (), CamelNNTPStream) -#define CAMEL_NNTP_STREAM_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_nntp_stream_get_type (), CamelNNTPStreamClass) -#define CAMEL_IS_NNTP_STREAM(obj) CAMEL_CHECK_TYPE (obj, camel_nntp_stream_get_type ()) - -typedef struct _CamelNNTPStreamClass CamelNNTPStreamClass; -typedef struct _CamelNNTPStream CamelNNTPStream; - -typedef enum { - CAMEL_NNTP_STREAM_LINE, - CAMEL_NNTP_STREAM_DATA, - CAMEL_NNTP_STREAM_EOD, /* end of data, acts as if end of stream */ -} camel_nntp_stream_mode_t; - -struct _CamelNNTPStream { - CamelStream parent; - - CamelStream *source; - - camel_nntp_stream_mode_t mode; - int state; - - unsigned char *buf, *ptr, *end; - unsigned char *linebuf, *lineptr, *lineend; -}; - -struct _CamelNNTPStreamClass { - CamelStreamClass parent_class; -}; - -CamelType camel_nntp_stream_get_type (void); - -CamelStream *camel_nntp_stream_new (CamelStream *source); - - -void camel_nntp_stream_set_mode (CamelNNTPStream *is, camel_nntp_stream_mode_t mode); - -int camel_nntp_stream_line (CamelNNTPStream *is, unsigned char **data, unsigned int *len); -int camel_nntp_stream_gets (CamelNNTPStream *is, unsigned char **start, unsigned int *len); -int camel_nntp_stream_getd (CamelNNTPStream *is, unsigned char **start, unsigned int *len); - -#endif /* ! _CAMEL_NNTP_STREAM_H */ diff --git a/camel/providers/nntp/camel-nntp-summary.c b/camel/providers/nntp/camel-nntp-summary.c deleted file mode 100644 index e6c02b95af..0000000000 --- a/camel/providers/nntp/camel-nntp-summary.c +++ /dev/null @@ -1,507 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- */ -/* - * Copyright (C) 2000 Ximian Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <ctype.h> -#include <sys/stat.h> -#include <sys/uio.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> - -#include "camel/camel-file-utils.h" -#include "camel/camel-mime-message.h" -#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" -#include "camel-nntp-folder.h" -#include "camel-nntp-store.h" -#include "camel-nntp-stream.h" - -#define w(x) -#define io(x) -#define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/ -#define dd(x) (camel_debug("nntp")?(x):0) - -#define CAMEL_NNTP_SUMMARY_VERSION (1) - -struct _CamelNNTPSummaryPrivate { - char *uid; - - struct _xover_header *xover; /* xoverview format */ - int xover_setup; -}; - -#define _PRIVATE(o) (((CamelNNTPSummary *)(o))->priv) - -static CamelMessageInfo * message_info_new_from_header (CamelFolderSummary *, struct _camel_header_raw *); -static int summary_header_load(CamelFolderSummary *, FILE *); -static int summary_header_save(CamelFolderSummary *, FILE *); - -static void camel_nntp_summary_class_init (CamelNNTPSummaryClass *klass); -static void camel_nntp_summary_init (CamelNNTPSummary *obj); -static void camel_nntp_summary_finalise (CamelObject *obj); -static CamelFolderSummaryClass *camel_nntp_summary_parent; - -CamelType -camel_nntp_summary_get_type(void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register(camel_folder_summary_get_type(), "CamelNNTPSummary", - sizeof (CamelNNTPSummary), - sizeof (CamelNNTPSummaryClass), - (CamelObjectClassInitFunc) camel_nntp_summary_class_init, - NULL, - (CamelObjectInitFunc) camel_nntp_summary_init, - (CamelObjectFinalizeFunc) camel_nntp_summary_finalise); - } - - return type; -} - -static void -camel_nntp_summary_class_init(CamelNNTPSummaryClass *klass) -{ - CamelFolderSummaryClass *sklass = (CamelFolderSummaryClass *) 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->summary_header_load = summary_header_load; - sklass->summary_header_save = summary_header_save; -} - -static void -camel_nntp_summary_init(CamelNNTPSummary *obj) -{ - struct _CamelNNTPSummaryPrivate *p; - struct _CamelFolderSummary *s = (CamelFolderSummary *)obj; - - p = _PRIVATE(obj) = g_malloc0(sizeof(*p)); - - /* subclasses need to set the right instance data sizes */ - s->message_info_size = sizeof(CamelMessageInfoBase); - s->content_info_size = sizeof(CamelMessageContentInfo); - - /* and a unique file version */ - s->version += CAMEL_NNTP_SUMMARY_VERSION; -} - -static void -camel_nntp_summary_finalise(CamelObject *obj) -{ - CamelNNTPSummary *cns = CAMEL_NNTP_SUMMARY(obj); - - g_free(cns->priv); -} - -CamelNNTPSummary * -camel_nntp_summary_new(struct _CamelFolder *folder, 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); - - return cns; -} - -static CamelMessageInfo * -message_info_new_from_header(CamelFolderSummary *s, struct _camel_header_raw *h) -{ - CamelMessageInfoBase *mi; - CamelNNTPSummary *cns = (CamelNNTPSummary *)s; - - /* error to call without this setup */ - if (cns->priv->uid == NULL) - return NULL; - - /* 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); - if (mi) { - mi->uid = g_strdup(cns->priv->uid); - cns->priv->uid = NULL; - } - - return (CamelMessageInfo *)mi; -} - -static int -summary_header_load(CamelFolderSummary *s, FILE *in) -{ - CamelNNTPSummary *cns = CAMEL_NNTP_SUMMARY(s); - - if (((CamelFolderSummaryClass *)camel_nntp_summary_parent)->summary_header_load(s, in) == -1) - return -1; - - /* Legacy version */ - if (s->version == 0x20c) { - camel_file_util_decode_fixed_int32(in, &cns->high); - return camel_file_util_decode_fixed_int32(in, &cns->low); - } - - if (camel_file_util_decode_fixed_int32(in, &cns->version) == -1) - return -1; - - if (cns->version > CAMEL_NNTP_SUMMARY_VERSION) { - g_warning("Unknown NNTP summary version"); - errno = EINVAL; - return -1; - } - - if (camel_file_util_decode_fixed_int32(in, &cns->high) == -1 - || camel_file_util_decode_fixed_int32(in, &cns->low) == -1) - return -1; - - return 0; -} - -static int -summary_header_save(CamelFolderSummary *s, FILE *out) -{ - CamelNNTPSummary *cns = CAMEL_NNTP_SUMMARY(s); - - if (((CamelFolderSummaryClass *)camel_nntp_summary_parent)->summary_header_save(s, out) == -1 - || camel_file_util_encode_fixed_int32(out, CAMEL_NNTP_SUMMARY_VERSION) == -1 - || camel_file_util_encode_fixed_int32(out, cns->high) == -1 - || camel_file_util_encode_fixed_int32(out, cns->low) == -1) - return -1; - - return 0; -} - -/* ********************************************************************** */ - -/* Note: This will be called from camel_nntp_command, so only use camel_nntp_raw_command */ -static int -add_range_xover(CamelNNTPSummary *cns, CamelNNTPStore *store, unsigned int high, unsigned int low, CamelFolderChangeInfo *changes, CamelException *ex) -{ - CamelFolderSummary *s; - CamelMessageInfoBase *mi; - struct _camel_header_raw *headers = NULL; - char *line, *tab; - int len, ret; - unsigned int n, count, total, size; - struct _xover_header *xover; - - s = (CamelFolderSummary *)cns; - - camel_operation_start(NULL, _("%s: Scanning new messages"), ((CamelService *)store)->url->host); - - ret = camel_nntp_raw_command_auth(store, ex, &line, "xover %r", low, high); - if (ret != 224) { - camel_operation_end(NULL); - if (ret != -1) - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Unexpected server response from xover: %s"), line); - return -1; - } - - count = 0; - total = high-low+1; - while ((ret = camel_nntp_stream_line(store->stream, (unsigned char **)&line, &len)) > 0) { - camel_operation_progress(NULL, (count * 100) / total); - count++; - n = strtoul(line, &tab, 10); - if (*tab != '\t') - continue; - tab++; - xover = store->xover; - size = 0; - for (;tab[0] && xover;xover = xover->next) { - line = tab; - tab = strchr(line, '\t'); - if (tab) - *tab++ = 0; - else - tab = line+strlen(line); - - /* do we care about this column? */ - if (xover->name) { - line += xover->skip; - if (line < tab) { - camel_header_raw_append(&headers, xover->name, line, -1); - switch(xover->type) { - case XOVER_STRING: - break; - case XOVER_MSGID: - cns->priv->uid = g_strdup_printf("%u,%s", n, line); - break; - case XOVER_SIZE: - size = strtoul(line, NULL, 10); - break; - } - } - } - } - - /* skip headers we don't care about, incase the server doesn't actually send some it said it would. */ - while (xover && xover->name == NULL) - xover = xover->next; - - /* truncated line? ignore? */ - if (xover == NULL) { - mi = (CamelMessageInfoBase *)camel_folder_summary_uid(s, cns->priv->uid); - if (mi == NULL) { - mi = (CamelMessageInfoBase *)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); - } - } - - if (cns->priv->uid) { - g_free(cns->priv->uid); - cns->priv->uid = NULL; - } - - camel_header_raw_clear(&headers); - } - - camel_operation_end(NULL); - - return ret; -} - -/* Note: This will be called from camel_nntp_command, so only use camel_nntp_raw_command */ -static int -add_range_head(CamelNNTPSummary *cns, CamelNNTPStore *store, unsigned int high, unsigned int low, CamelFolderChangeInfo *changes, CamelException *ex) -{ - CamelFolderSummary *s; - int i, ret = -1; - char *line, *msgid; - unsigned int n, count, total; - CamelMessageInfo *mi; - CamelMimeParser *mp; - - s = (CamelFolderSummary *)cns; - - mp = camel_mime_parser_new(); - - camel_operation_start(NULL, _("%s: Scanning new messages"), ((CamelService *)store)->url->host); - - count = 0; - total = high-low+1; - for (i=low;i<high+1;i++) { - camel_operation_progress(NULL, (count * 100) / total); - count++; - ret = camel_nntp_raw_command_auth(store, ex, &line, "head %u", i); - /* unknown article, ignore */ - if (ret == 423) - continue; - else if (ret == -1) - goto ioerror; - else if (ret != 221) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Unexpected server response from head: %s"), line); - goto ioerror; - } - line += 3; - n = strtoul(line, &line, 10); - if (n != i) - g_warning("retrieved message '%d' when i expected '%d'?\n", n, i); - - /* FIXME: use camel-mime-utils.c function for parsing msgid? */ - if ((msgid = strchr(line, '<')) && (line = strchr(msgid+1, '>'))){ - line[1] = 0; - cns->priv->uid = g_strdup_printf("%u,%s\n", n, msgid); - mi = camel_folder_summary_uid(s, cns->priv->uid); - if (mi == NULL) { - if (camel_mime_parser_init_with_stream(mp, (CamelStream *)store->stream) == -1) - goto error; - mi = camel_folder_summary_add_from_parser(s, mp); - while (camel_mime_parser_step(mp, NULL, NULL) != CAMEL_MIME_PARSER_STATE_EOF) - ; - if (mi == NULL) { - goto error; - } - cns->high = i; - camel_folder_change_info_add_uid(changes, camel_message_info_uid(mi)); - } else { - /* already have, ignore */ - camel_message_info_free(mi); - } - if (cns->priv->uid) { - g_free(cns->priv->uid); - cns->priv->uid = NULL; - } - } - } - - ret = 0; -error: - - if (ret == -1) { - if (errno == EINTR) - camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Use cancel")); - else - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Operation failed: %s"), strerror(errno)); - } -ioerror: - - if (cns->priv->uid) { - g_free(cns->priv->uid); - cns->priv->uid = NULL; - } - camel_object_unref((CamelObject *)mp); - - camel_operation_end(NULL); - - return ret; -} - -/* Assumes we have the stream */ -/* Note: This will be called from camel_nntp_command, so only use camel_nntp_raw_command */ -int -camel_nntp_summary_check(CamelNNTPSummary *cns, CamelNNTPStore *store, char *line, CamelFolderChangeInfo *changes, CamelException *ex) -{ - CamelFolderSummary *s; - int ret = 0, i; - unsigned int n, f, l; - int count; - char *folder = NULL; - CamelNNTPStoreInfo *si; - - s = (CamelFolderSummary *)cns; - - line +=3; - n = strtoul(line, &line, 10); - f = strtoul(line, &line, 10); - l = strtoul(line, &line, 10); - if (line[0] == ' ') { - char *tmp; - - folder = line+1; - tmp = strchr(folder, ' '); - if (tmp) - *tmp = 0; - tmp = g_alloca(strlen(folder)+1); - strcpy(tmp, folder); - folder = tmp; - } - - if (cns->low == f && cns->high == l) { - dd(printf("nntp_summary: no work to do!\n")); - goto update; - } - - /* Need to work out what to do with our messages */ - - /* Check for messages no longer on the server */ - if (cns->low != f) { - count = camel_folder_summary_count(s); - for (i = 0; i < count; i++) { - CamelMessageInfo *mi = camel_folder_summary_index(s, i); - - if (mi) { - const char *uid = camel_message_info_uid(mi); - const char *msgid; - - n = strtoul(uid, NULL, 10); - if (n < f || n > l) { - dd(printf("nntp_summary: %u is lower/higher than lowest/highest article, removed\n", n)); - /* Since we use a global cache this could prematurely remove - a cached message that might be in another folder - not that important as - it is a true cache */ - msgid = strchr(uid, ','); - if (msgid) - camel_data_cache_remove(store->cache, "cache", msgid+1, NULL); - camel_folder_change_info_remove_uid(changes, uid); - camel_folder_summary_remove(s, mi); - count--; - i--; - } - - camel_message_info_free(mi); - } - } - cns->low = f; - } - - if (cns->high < l) { - if (cns->high < f) - cns->high = f-1; - - if (store->xover) { - ret = add_range_xover(cns, store, l, cns->high+1, changes, ex); - } else { - ret = add_range_head(cns, store, l, cns->high+1, changes, ex); - } - } - - /* TODO: not from here */ - camel_folder_summary_touch(s); - camel_folder_summary_save(s); -update: - /* update store summary if we have it */ - if (folder - && (si = (CamelNNTPStoreInfo *)camel_store_summary_path((CamelStoreSummary *)store->summary, folder))) { - int unread = 0; - - count = camel_folder_summary_count(s); - for (i = 0; i < count; i++) { - CamelMessageInfoBase *mi = (CamelMessageInfoBase *)camel_folder_summary_index(s, i); - - if (mi) { - if ((mi->flags & CAMEL_MESSAGE_SEEN) == 0) - unread++; - camel_message_info_free(mi); - } - } - - if (si->info.unread != unread - || si->info.total != count - || si->first != f - || si->last != l) { - si->info.unread = unread; - si->info.total = count; - si->first = f; - si->last = l; - camel_store_summary_touch((CamelStoreSummary *)store->summary); - camel_store_summary_save((CamelStoreSummary *)store->summary); - } - camel_store_summary_info_free ((CamelStoreSummary *)store->summary, (CamelStoreInfo *)si); - } else { - if (folder) - g_warning("Group '%s' not present in summary", folder); - else - g_warning("Missing group from group response"); - } - - return ret; -} diff --git a/camel/providers/nntp/camel-nntp-summary.h b/camel/providers/nntp/camel-nntp-summary.h deleted file mode 100644 index 2aff4319e1..0000000000 --- a/camel/providers/nntp/camel-nntp-summary.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2000 Ximian Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_NNTP_SUMMARY_H -#define _CAMEL_NNTP_SUMMARY_H - -#include <camel/camel-folder-summary.h> - -struct _CamelNNTPStore; -struct _CamelFolderChangeInfo; -struct _CamelException; - -#define CAMEL_NNTP_SUMMARY(obj) CAMEL_CHECK_CAST (obj, camel_nntp_summary_get_type (), CamelNNTPSummary) -#define CAMEL_NNTP_SUMMARY_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_nntp_summary_get_type (), CamelNNTPSummaryClass) -#define CAMEL_IS_LOCAL_SUMMARY(obj) CAMEL_CHECK_TYPE (obj, camel_nntp_summary_get_type ()) - -typedef struct _CamelNNTPSummary CamelNNTPSummary; -typedef struct _CamelNNTPSummaryClass CamelNNTPSummaryClass; - -struct _CamelNNTPSummary { - CamelFolderSummary parent; - - struct _CamelNNTPSummaryPrivate *priv; - - guint32 version; - guint32 high, low; -}; - -struct _CamelNNTPSummaryClass { - CamelFolderSummaryClass parent_class; -}; - -CamelType camel_nntp_summary_get_type (void); -CamelNNTPSummary *camel_nntp_summary_new(struct _CamelFolder *folder, const char *path); - -int camel_nntp_summary_check(CamelNNTPSummary *cns, struct _CamelNNTPStore *store, char *line, struct _CamelFolderChangeInfo *changes, struct _CamelException *ex); - -#endif /* ! _CAMEL_NNTP_SUMMARY_H */ - diff --git a/camel/providers/nntp/camel-nntp-types.h b/camel/providers/nntp/camel-nntp-types.h deleted file mode 100644 index a37179c521..0000000000 --- a/camel/providers/nntp/camel-nntp-types.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-grouplist.h : getting/updating the list of newsgroups on the server. */ - -/* - * Author : Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 2000 Ximian . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_NNTP_TYPES_H -#define CAMEL_NNTP_TYPES_H 1 - -typedef struct CamelNNTPGroupList CamelNNTPGroupList; -typedef struct CamelNNTPGroupListEntry CamelNNTPGroupListEntry; -typedef struct CamelNNTPOverField CamelNNTPOverField; -typedef struct CamelNNTPStore CamelNNTPStore; -typedef struct CamelNNTPStoreClass CamelNNTPStoreClass; - -#endif /* CAMEL_NNTP_TYPES_H */ diff --git a/camel/providers/nntp/camel-nntp-utils.c b/camel/providers/nntp/camel-nntp-utils.c deleted file mode 100644 index 43cbb0eedb..0000000000 --- a/camel/providers/nntp/camel-nntp-utils.c +++ /dev/null @@ -1,299 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-utils.c : utilities used by the nntp code. */ - -/* - * Author : Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 2000 Ximian . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include "camel-folder-summary.h" -#include "camel-nntp-resp-codes.h" -#include "camel-nntp-folder.h" -#include "camel-nntp-store.h" -#include "camel-nntp-utils.h" -#include "camel-stream-mem.h" -#include "camel-exception.h" - -#include "libedataserver/md5-utils.h" - -#include <stdlib.h> -#include <string.h> - -static void -get_XOVER_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, - int first_message, int last_message, CamelException *ex) -{ - int status; - CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (folder); - char digest[16]; - - status = camel_nntp_command (nntp_store, ex, NULL, - "XOVER %d-%d", - first_message, - last_message); - - if (status == NNTP_DATA_FOLLOWS) { - gboolean done = FALSE; - - while (!done) { - char *line; - - if (camel_remote_store_recv_line (CAMEL_REMOTE_STORE (nntp_store), &line, ex) < 0) { - g_warning ("failed to recv_line while building OVER header list\n"); - break; - } - - if (*line == '.') { - done = TRUE; - g_print ("done\n"); - } - else { - CamelMessageInfo *new_info = camel_folder_summary_info_new(folder->summary); - char **split_line = g_strsplit (line, "\t", 7); - char *subject, *from, *date, *message_id, *bytes; - char *uid; - - subject = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_SUBJECT].index]; - from = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_FROM].index]; - date = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_DATE].index]; - message_id = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_MESSAGE_ID].index]; - bytes = split_line [nntp_store->overview_field [CAMEL_NNTP_OVER_BYTES].index]; - - /* if the overview format flagged this - field as "full", skip over the - preceding field name and colon */ - if (nntp_store->overview_field [ CAMEL_NNTP_OVER_SUBJECT ].full) - subject += strlen ("Subject:"); - if (nntp_store->overview_field [ CAMEL_NNTP_OVER_FROM ].full) - from += strlen ("From:"); - if (nntp_store->overview_field [ CAMEL_NNTP_OVER_DATE ].full) - date += strlen ("Date:"); - if (nntp_store->overview_field [ CAMEL_NNTP_OVER_MESSAGE_ID ].full) - message_id += strlen ("Message-ID:"); - if (nntp_store->overview_field [ CAMEL_NNTP_OVER_BYTES ].full) - bytes += strlen ("Bytes:"); - - uid = g_strdup_printf ("%s,%s", split_line[0], message_id); - camel_message_info_set_subject(new_info, g_strdup(subject)); - camel_message_info_set_from(new_info, g_strdup(from)); - camel_message_info_set_to(new_info, g_strdup(folder->name)); - camel_message_info_set_uid(new_info, uid); - - new_info->date_sent = camel_header_decode_date(date, NULL); -#if 0 - /* XXX do we need to fill in both dates? */ - new_info->headers.date_received = g_strdup(date); -#endif - new_info->size = atoi(bytes); - md5_get_digest(message_id, strlen(message_id), digest); - memcpy(new_info->message_id.id.hash, digest, sizeof(new_info->message_id.id.hash)); - - if (camel_nntp_newsrc_article_is_read (nntp_store->newsrc, - folder->name, - atoi (split_line[0]))) - new_info->flags |= CAMEL_MESSAGE_SEEN; - - camel_folder_summary_add (folder->summary, new_info); - g_strfreev (split_line); - } - g_free (line); - } - } - else { - /* XXX */ - g_warning ("weird nntp response for XOVER: %d\n", status); - } -} - -#if 0 -static GArray* -get_HEAD_headers(CamelNNTPStore *nntp_store, CamelFolder *folder, - int first_message, int last_message, CamelException *ex) -{ - int i; - int status; - - for (i = first_message; i < last_message; i ++) { - status = camel_nntp_command (nntp_store, ex, NULL, - "HEAD %d", i); - - if (status == NNTP_HEAD_FOLLOWS) { - gboolean done = FALSE; - char *buf; - int buf_len; - int buf_alloc; - int h; - CamelStream *header_stream; - GArray *header_array; - CamelStream *nntp_istream; - CamelMessageInfo *new_info = g_new0(CamelMessageInfo, 1); - - buf_alloc = 2048; - buf_len = 0; - buf = g_malloc(buf_alloc); - done = FALSE; - - buf[0] = 0; - - nntp_istream = nntp_store->istream; - - while (!done) { - char *line; - int line_length; - - line = camel_stream_buffer_read_line ( - CAMEL_STREAM_BUFFER ( nntp_istream )); - line_length = strlen ( line ); - - if (*line == '.') { - done = TRUE; - } - else { - if (buf_len + line_length > buf_alloc) { - buf_alloc *= 2; - buf = g_realloc (buf, buf_alloc); - } - strcat(buf, line); - strcat(buf, "\n"); - buf_len += strlen(line); - g_free (line); - } - } - - /* create a stream from which to parse the headers */ - header_stream = camel_stream_mem_new_with_buffer (buf, buf_len, - CAMEL_STREAM_MEM_READ); - - header_array = get_header_array_from_stream (header_stream); - - memset (&info, 0, sizeof(info)); - - for (h = 0; h < header_array->len; h ++) { - Rfc822Header *header = &((Rfc822Header*)header_array->data)[h]; - if (!g_strcasecmp(header->name, "From")) - new_info->from = g_strdup(header->value); - else if (!g_strcasecmp(header->name, "To")) - new_info->to = g_strdup(header->value); - else if (!g_strcasecmp(header->name, "Subject")) - new_info->subject = g_strdup(header->value); - else if (!g_strcasecmp(header->name, "Message-ID")) { - new_info->uid = g_strdup_printf("%d,%s", i, header->value); - new_info->message_id = g_strdup(header->value); - } - else if (!g_strcasecmp(header->name, "Date")) { - new_info->date_sent = camel_header_decode_date (header->value); -#if 0 - new_info->date_sent = g_strdup(header->value); - new_info->date_received = g_strdup(header->value); -#endif - } - } - - camel_folder_summary_add (nntp_folder->summary, new_info); - } - else if (status == CAMEL_NNTP_FAIL) { - /* nasty things are afoot */ - g_warning ("failure doing HEAD\n"); - break; - } - } -} -#endif - -static inline int -uid_num (CamelFolderSummary *summary, int index) -{ - char *tmp; - char *brk; - CamelMessageInfo *minfo; - int ret; - - minfo = camel_folder_summary_index(summary, index); - if(minfo == NULL) - return 0; - - tmp = g_strdup(camel_message_info_uid(minfo)); - camel_message_info_free(minfo); - - if((brk = strchr(tmp, ',')) == NULL) - ret = 0; - else { - *brk = 0; - ret = atoi(tmp); - } - - g_free(tmp); - - return ret; -} - -void -camel_nntp_get_headers (CamelStore *store, - CamelNNTPFolder *nntp_folder, - CamelException *ex) -{ - CamelNNTPStore *nntp_store = CAMEL_NNTP_STORE (store); - CamelFolder *folder = CAMEL_FOLDER (nntp_folder); - char *ret; - int first_message, nb_message, last_message, last_summary; - int status; - int i; - - status = camel_nntp_command (nntp_store, ex, &ret, - "GROUP %s", folder->name); - sscanf (ret, "%d %d %d", &nb_message, &first_message, &last_message); - g_free (ret); - - i = camel_folder_summary_count(folder->summary); - if(i != 0) { - last_summary = uid_num(folder->summary, i-1); - - if(last_summary < first_message) - camel_folder_summary_clear(folder->summary); - else { - while(uid_num(folder->summary, 0) < first_message) - camel_folder_summary_remove_index(folder->summary, 0); - - if(last_summary >= last_message) - return; - - first_message = last_summary; - } - } - - if (status == NNTP_NO_SUCH_GROUP) { - /* XXX throw invalid group exception */ - camel_exception_setv (ex, - CAMEL_EXCEPTION_FOLDER_INVALID, - "group %s not found on server", - folder->name); - return; - } - - - if (nntp_store->extensions & CAMEL_NNTP_EXT_OVER) { - get_XOVER_headers (nntp_store, folder, first_message, last_message, ex); - } - else { - g_warning ("need to fix get_HEAD_headers\n"); -#if 0 - get_HEAD_headers (nntp_store, folder, first_message, last_message, ex); -#endif - } - -} diff --git a/camel/providers/nntp/camel-nntp-utils.h b/camel/providers/nntp/camel-nntp-utils.h deleted file mode 100644 index 48fd7490c9..0000000000 --- a/camel/providers/nntp/camel-nntp-utils.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-nntp-utils.h : Utilities for the NNTP provider */ - -/* - * - * Author : Chris Toshok <toshok@ximian.com> - * - * Copyright (C) 1999 Ximian . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_NNTP_UTILS_H -#define CAMEL_NNTP_UTILS_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -void camel_nntp_get_headers (CamelStore *store, CamelNNTPFolder *nntp_folder, CamelException *ex); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_NNTP_UTILS_H */ diff --git a/camel/providers/nntp/libcamelnntp.urls b/camel/providers/nntp/libcamelnntp.urls deleted file mode 100644 index dee2e70f14..0000000000 --- a/camel/providers/nntp/libcamelnntp.urls +++ /dev/null @@ -1,2 +0,0 @@ -news -nntp diff --git a/camel/providers/nntp/test-newsrc.c b/camel/providers/nntp/test-newsrc.c deleted file mode 100644 index c4b985e565..0000000000 --- a/camel/providers/nntp/test-newsrc.c +++ /dev/null @@ -1,10 +0,0 @@ -#include <stdio.h> -#include <glib.h> -#include "camel-nntp-newsrc.h" - -int -main(int argc, char *argv[]) -{ - CamelNNTPNewsrc *newsrc = camel_nntp_newsrc_read_for_server (argv[1]); - camel_nntp_newsrc_write_to_file (newsrc, stdout); -} diff --git a/camel/providers/pop3/.cvsignore b/camel/providers/pop3/.cvsignore deleted file mode 100644 index ddf4c8b28d..0000000000 --- a/camel/providers/pop3/.cvsignore +++ /dev/null @@ -1,10 +0,0 @@ -Makefile -Makefile.in -.libs -.deps -*.lo -*.la -*.bb -*.bbg -*.da -*.gcov diff --git a/camel/providers/pop3/Makefile.am b/camel/providers/pop3/Makefile.am deleted file mode 100644 index 49df41e230..0000000000 --- a/camel/providers/pop3/Makefile.am +++ /dev/null @@ -1,31 +0,0 @@ -## Process this file with automake to produce Makefile.in - -camel_provider_LTLIBRARIES = libcamelpop3.la -camel_provider_DATA = libcamelpop3.urls - -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/camel \ - $(CAMEL_CFLAGS) \ - -DG_LOG_DOMAIN=\"camel-pop3-provider\" - -libcamelpop3_la_SOURCES = \ - camel-pop3-engine.c \ - camel-pop3-folder.c \ - camel-pop3-provider.c \ - camel-pop3-stream.c \ - camel-pop3-store.c - -noinst_HEADERS = \ - camel-pop3-engine.h \ - camel-pop3-folder.h \ - camel-pop3-stream.h \ - camel-pop3-store.h - -libcamelpop3_la_LDFLAGS = -avoid-version -module - -libcamelpop3_la_LIBADD = \ - $(top_builddir)/libedataserver/libedataserver-${BASE_VERSION}.la - -EXTRA_DIST = libcamelpop3.urls diff --git a/camel/providers/pop3/camel-pop3-engine.c b/camel/providers/pop3/camel-pop3-engine.c deleted file mode 100644 index e79a382359..0000000000 --- a/camel/providers/pop3/camel-pop3-engine.c +++ /dev/null @@ -1,412 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Author: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright 1999, 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <errno.h> - -#include <string.h> -#include <stdio.h> - -#include <glib.h> - -#include "camel-pop3-engine.h" -#include "camel-pop3-stream.h" -#include "camel-service.h" -#include "camel-sasl.h" -#include "camel-i18n.h" - -/* max 'outstanding' bytes in output stream, so we can't deadlock waiting - for the server to accept our data when pipelining */ -#define CAMEL_POP3_SEND_LIMIT (1024) - - -extern int camel_verbose_debug; -#define dd(x) (camel_verbose_debug?(x):0) - -static void get_capabilities(CamelPOP3Engine *pe); - -static CamelObjectClass *parent_class = NULL; - -/* Returns the class for a CamelStream */ -#define CS_CLASS(so) CAMEL_POP3_ENGINE_CLASS(CAMEL_OBJECT_GET_CLASS(so)) - -static void -camel_pop3_engine_class_init (CamelPOP3EngineClass *camel_pop3_engine_class) -{ - parent_class = camel_type_get_global_classfuncs( CAMEL_OBJECT_TYPE ); -} - -static void -camel_pop3_engine_init(CamelPOP3Engine *pe, CamelPOP3EngineClass *peclass) -{ - e_dlist_init(&pe->active); - e_dlist_init(&pe->queue); - e_dlist_init(&pe->done); - pe->state = CAMEL_POP3_ENGINE_DISCONNECT; -} - -static void -camel_pop3_engine_finalise(CamelPOP3Engine *pe) -{ - /* FIXME: Also flush/free any outstanding requests, etc */ - - if (pe->stream) - camel_object_unref(pe->stream); -} - -CamelType -camel_pop3_engine_get_type (void) -{ - static CamelType camel_pop3_engine_type = CAMEL_INVALID_TYPE; - - if (camel_pop3_engine_type == CAMEL_INVALID_TYPE) { - camel_pop3_engine_type = camel_type_register(camel_object_get_type(), - "CamelPOP3Engine", - sizeof( CamelPOP3Engine ), - sizeof( CamelPOP3EngineClass ), - (CamelObjectClassInitFunc) camel_pop3_engine_class_init, - NULL, - (CamelObjectInitFunc) camel_pop3_engine_init, - (CamelObjectFinalizeFunc) camel_pop3_engine_finalise ); - } - - return camel_pop3_engine_type; -} - -static int -read_greeting (CamelPOP3Engine *pe) -{ - extern CamelServiceAuthType camel_pop3_password_authtype; - extern CamelServiceAuthType camel_pop3_apop_authtype; - unsigned char *line, *apop, *apopend; - unsigned int len; - - /* first, read the greeting */ - if (camel_pop3_stream_line (pe->stream, &line, &len) == -1 - || strncmp (line, "+OK", 3) != 0) - return -1; - - if ((apop = strchr (line + 3, '<')) - && (apopend = strchr (apop, '>'))) { - apopend[1] = 0; - pe->apop = g_strdup (apop); - pe->capa = CAMEL_POP3_CAP_APOP; - pe->auth = g_list_append (pe->auth, &camel_pop3_apop_authtype); - } - - pe->auth = g_list_prepend (pe->auth, &camel_pop3_password_authtype); - - return 0; -} - -/** - * camel_pop3_engine_new: - * @source: source stream - * @flags: engine flags - * - * Returns a NULL stream. A null stream is always at eof, and - * always returns success for all reads and writes. - * - * Return value: the stream - **/ -CamelPOP3Engine * -camel_pop3_engine_new(CamelStream *source, guint32 flags) -{ - CamelPOP3Engine *pe; - - pe = (CamelPOP3Engine *)camel_object_new(camel_pop3_engine_get_type ()); - - pe->stream = (CamelPOP3Stream *)camel_pop3_stream_new(source); - pe->state = CAMEL_POP3_ENGINE_AUTH; - pe->flags = flags; - - if (read_greeting (pe) == -1) { - camel_object_unref (pe); - return NULL; - } - - get_capabilities (pe); - - return pe; -} - - -/** - * camel_pop3_engine_reget_capabilities: - * @engine: pop3 engine - * - * Regets server capabilities (needed after a STLS command is issued for example). - **/ -void -camel_pop3_engine_reget_capabilities (CamelPOP3Engine *engine) -{ - g_return_if_fail (CAMEL_IS_POP3_ENGINE (engine)); - - get_capabilities (engine); -} - - -/* TODO: read implementation too? - etc? */ -struct { - char *cap; - guint32 flag; -} capa[] = { - { "APOP" , CAMEL_POP3_CAP_APOP }, - { "TOP" , CAMEL_POP3_CAP_TOP }, - { "UIDL", CAMEL_POP3_CAP_UIDL }, - { "PIPELINING", CAMEL_POP3_CAP_PIPE }, - { "STLS", CAMEL_POP3_CAP_STLS }, /* STARTTLS */ -}; - -static void -cmd_capa(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data) -{ - unsigned char *line, *tok, *next; - unsigned int len; - int ret; - int i; - CamelServiceAuthType *auth; - - dd(printf("cmd_capa\n")); - - do { - ret = camel_pop3_stream_line(stream, &line, &len); - if (ret >= 0) { - if (strncmp(line, "SASL ", 5) == 0) { - tok = line+5; - dd(printf("scanning tokens '%s'\n", tok)); - while (tok) { - next = strchr(tok, ' '); - if (next) - *next++ = 0; - auth = camel_sasl_authtype(tok); - if (auth) { - dd(printf("got auth type '%s'\n", tok)); - pe->auth = g_list_prepend(pe->auth, auth); - } else { - dd(printf("unsupported auth type '%s'\n", tok)); - } - tok = next; - } - } else { - for (i=0;i<sizeof(capa)/sizeof(capa[0]);i++) { - if (strcmp(capa[i].cap, line) == 0) - pe->capa |= capa[i].flag; - } - } - } - } while (ret>0); -} - -static void -get_capabilities(CamelPOP3Engine *pe) -{ - CamelPOP3Command *pc; - - if (!(pe->flags & CAMEL_POP3_ENGINE_DISABLE_EXTENSIONS)) { - pc = camel_pop3_engine_command_new(pe, CAMEL_POP3_COMMAND_MULTI, cmd_capa, NULL, "CAPA\r\n"); - while (camel_pop3_engine_iterate(pe, pc) > 0) - ; - camel_pop3_engine_command_free(pe, pc); - - if (pe->state == CAMEL_POP3_ENGINE_TRANSACTION && !(pe->capa & CAMEL_POP3_CAP_UIDL)) { - /* check for UIDL support manually */ - pc = camel_pop3_engine_command_new (pe, CAMEL_POP3_COMMAND_SIMPLE, NULL, NULL, "UIDL 1\r\n"); - while (camel_pop3_engine_iterate (pe, pc) > 0) - ; - - if (pc->state == CAMEL_POP3_COMMAND_OK) - pe->capa |= CAMEL_POP3_CAP_UIDL; - - camel_pop3_engine_command_free (pe, pc); - } - } -} - -/* returns true if the command was sent, false if it was just queued */ -static int -engine_command_queue(CamelPOP3Engine *pe, CamelPOP3Command *pc) -{ - if (((pe->capa & CAMEL_POP3_CAP_PIPE) == 0 || (pe->sentlen + strlen(pc->data)) > CAMEL_POP3_SEND_LIMIT) - && pe->current != NULL) { - e_dlist_addtail(&pe->queue, (EDListNode *)pc); - return FALSE; - } else { - /* ??? */ - if (camel_stream_write((CamelStream *)pe->stream, pc->data, strlen(pc->data)) == -1) { - e_dlist_addtail(&pe->queue, (EDListNode *)pc); - return FALSE; - } - - pe->sentlen += strlen(pc->data); - - pc->state = CAMEL_POP3_COMMAND_DISPATCHED; - - if (pe->current == NULL) - pe->current = pc; - else - e_dlist_addtail(&pe->active, (EDListNode *)pc); - - return TRUE; - } -} - -/* returns -1 on error (sets errno), 0 when no work to do, or >0 if work remaining */ -int -camel_pop3_engine_iterate(CamelPOP3Engine *pe, CamelPOP3Command *pcwait) -{ - unsigned char *p; - unsigned int len; - CamelPOP3Command *pc, *pw, *pn; - - if (pcwait && pcwait->state >= CAMEL_POP3_COMMAND_OK) - return 0; - - pc = pe->current; - if (pc == NULL) - return 0; - - /* LOCK */ - - if (camel_pop3_stream_line(pe->stream, &pe->line, &pe->linelen) == -1) - goto ioerror; - - p = pe->line; - switch (p[0]) { - case '+': - dd(printf("Got + response\n")); - if (pc->flags & CAMEL_POP3_COMMAND_MULTI) { - pc->state = CAMEL_POP3_COMMAND_DATA; - camel_pop3_stream_set_mode(pe->stream, CAMEL_POP3_STREAM_DATA); - - if (pc->func) - pc->func(pe, pe->stream, pc->func_data); - - /* Make sure we get all data before going back to command mode */ - while (camel_pop3_stream_getd(pe->stream, &p, &len) > 0) - ; - camel_pop3_stream_set_mode(pe->stream, CAMEL_POP3_STREAM_LINE); - } else { - pc->state = CAMEL_POP3_COMMAND_OK; - } - break; - case '-': - pc->state = CAMEL_POP3_COMMAND_ERR; - break; - default: - /* what do we do now? f'knows! */ - g_warning("Bad server response: %s\n", p); - pc->state = CAMEL_POP3_COMMAND_ERR; - break; - } - - e_dlist_addtail(&pe->done, (EDListNode *)pc); - pe->sentlen -= strlen(pc->data); - - /* Set next command */ - pe->current = (CamelPOP3Command *)e_dlist_remhead(&pe->active); - - /* check the queue for sending any we can now send also */ - pw = (CamelPOP3Command *)pe->queue.head; - pn = pw->next; - while (pn) { - if (((pe->capa & CAMEL_POP3_CAP_PIPE) == 0 || (pe->sentlen + strlen(pw->data)) > CAMEL_POP3_SEND_LIMIT) - && pe->current != NULL) - break; - - if (camel_stream_write((CamelStream *)pe->stream, pw->data, strlen(pw->data)) == -1) - goto ioerror; - - e_dlist_remove((EDListNode *)pw); - - pe->sentlen += strlen(pw->data); - pw->state = CAMEL_POP3_COMMAND_DISPATCHED; - - if (pe->current == NULL) - pe->current = pw; - else - e_dlist_addtail(&pe->active, (EDListNode *)pw); - - pw = pn; - pn = pn->next; - } - - /* UNLOCK */ - - if (pcwait && pcwait->state >= CAMEL_POP3_COMMAND_OK) - return 0; - - return pe->current==NULL?0:1; -ioerror: - /* we assume all outstanding commands are gunna fail now */ - while ( (pw = (CamelPOP3Command*)e_dlist_remhead(&pe->active)) ) { - pw->state = CAMEL_POP3_COMMAND_ERR; - e_dlist_addtail(&pe->done, (EDListNode *)pw); - } - - while ( (pw = (CamelPOP3Command*)e_dlist_remhead(&pe->queue)) ) { - pw->state = CAMEL_POP3_COMMAND_ERR; - e_dlist_addtail(&pe->done, (EDListNode *)pw); - } - - if (pe->current) { - pe->current->state = CAMEL_POP3_COMMAND_ERR; - e_dlist_addtail(&pe->done, (EDListNode *)pe->current); - pe->current = NULL; - } - - return -1; -} - -CamelPOP3Command * -camel_pop3_engine_command_new(CamelPOP3Engine *pe, guint32 flags, CamelPOP3CommandFunc func, void *data, const char *fmt, ...) -{ - CamelPOP3Command *pc; - va_list ap; - - pc = g_malloc0(sizeof(*pc)); - pc->func = func; - pc->func_data = data; - pc->flags = flags; - - va_start(ap, fmt); - pc->data = g_strdup_vprintf(fmt, ap); - pc->state = CAMEL_POP3_COMMAND_IDLE; - - /* TODO: what about write errors? */ - engine_command_queue(pe, pc); - - return pc; -} - -void -camel_pop3_engine_command_free(CamelPOP3Engine *pe, CamelPOP3Command *pc) -{ - if (pe->current != pc) - e_dlist_remove((EDListNode *)pc); - g_free(pc->data); - g_free(pc); -} diff --git a/camel/providers/pop3/camel-pop3-engine.h b/camel/providers/pop3/camel-pop3-engine.h deleted file mode 100644 index 48938bbf48..0000000000 --- a/camel/providers/pop3/camel-pop3-engine.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2001 Ximian Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _CAMEL_POP3_ENGINE_H -#define _CAMEL_POP3_ENGINE_H - -#include <camel/camel-object.h> -#include "libedataserver/e-msgport.h" -#include "camel-pop3-stream.h" - -#define CAMEL_POP3_ENGINE(obj) CAMEL_CHECK_CAST (obj, camel_pop3_engine_get_type (), CamelPOP3Engine) -#define CAMEL_POP3_ENGINE_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_pop3_engine_get_type (), CamelPOP3EngineClass) -#define CAMEL_IS_POP3_ENGINE(obj) CAMEL_CHECK_TYPE (obj, camel_pop3_engine_get_type ()) - -typedef struct _CamelPOP3EngineClass CamelPOP3EngineClass; -typedef struct _CamelPOP3Engine CamelPOP3Engine; -typedef struct _CamelPOP3Command CamelPOP3Command; - -/* pop 3 connection states, actually since we're given a connected socket, we always start in auth state */ -typedef enum { - CAMEL_POP3_ENGINE_DISCONNECT = 0, - CAMEL_POP3_ENGINE_AUTH, - CAMEL_POP3_ENGINE_TRANSACTION, - CAMEL_POP3_ENGINE_UPDATE, -} camel_pop3_engine_t; - -/* state of a command */ -typedef enum { - CAMEL_POP3_COMMAND_IDLE = 0, /* command created or queued, not yet sent (e.g. non pipelined server) */ - CAMEL_POP3_COMMAND_DISPATCHED, /* command sent to server */ - - /* completion codes */ - CAMEL_POP3_COMMAND_OK, /* plain ok response */ - CAMEL_POP3_COMMAND_DATA, /* processing command response */ - CAMEL_POP3_COMMAND_ERR, /* error response */ -} camel_pop3_command_t; - -/* flags for command types */ -enum { - CAMEL_POP3_COMMAND_SIMPLE = 0, /* dont expect multiline response */ - CAMEL_POP3_COMMAND_MULTI = 1, /* expect multiline response */ -}; - -/* flags for server options */ -enum { - CAMEL_POP3_CAP_APOP = 1<<0, - CAMEL_POP3_CAP_UIDL = 1<<1, - CAMEL_POP3_CAP_SASL = 1<<2, - CAMEL_POP3_CAP_TOP = 1<<3, - CAMEL_POP3_CAP_PIPE = 1<<4, - CAMEL_POP3_CAP_STLS = 1<<5 -}; - -/* enable/disable flags for the engine itself */ -enum { - CAMEL_POP3_ENGINE_DISABLE_EXTENSIONS = 1<<0, -}; - -typedef void (*CamelPOP3CommandFunc)(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data); - -struct _CamelPOP3Command { - struct _CamelPOP3Command *next; - struct _CamelPOP3Command *prev; - - guint32 flags; - camel_pop3_command_t state; - - CamelPOP3CommandFunc func; - void *func_data; - - int data_size; - char *data; -}; - -struct _CamelPOP3Engine { - CamelObject parent; - - guint32 flags; - - camel_pop3_engine_t state; - - GList *auth; /* authtypes supported */ - - guint32 capa; /* capabilities */ - char *apop; /* apop time string */ - - unsigned char *line; /* current line buffer */ - unsigned int linelen; - - struct _CamelPOP3Stream *stream; - - unsigned int sentlen; /* data sent (so we dont overflow network buffer) */ - - EDList active; /* active commands */ - EDList queue; /* queue of waiting commands */ - EDList done; /* list of done commands, awaiting free */ - - CamelPOP3Command *current; /* currently busy (downloading) response */ -}; - -struct _CamelPOP3EngineClass { - CamelObjectClass parent_class; -}; - -CamelType camel_pop3_engine_get_type (void); - -CamelPOP3Engine *camel_pop3_engine_new (CamelStream *source, guint32 flags); - -void camel_pop3_engine_reget_capabilities (CamelPOP3Engine *engine); - -void camel_pop3_engine_command_free(CamelPOP3Engine *pe, CamelPOP3Command *pc); - -int camel_pop3_engine_iterate (CamelPOP3Engine *pe, CamelPOP3Command *pc); - -CamelPOP3Command *camel_pop3_engine_command_new (CamelPOP3Engine *pe, guint32 flags, CamelPOP3CommandFunc func, void *data, const char *fmt, ...); - -#endif /* ! _CAMEL_POP3_ENGINE_H */ diff --git a/camel/providers/pop3/camel-pop3-folder.c b/camel/providers/pop3/camel-pop3-folder.c deleted file mode 100644 index e0d91f1eff..0000000000 --- a/camel/providers/pop3/camel-pop3-folder.c +++ /dev/null @@ -1,568 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-pop3-folder.c : class for a pop3 folder */ - -/* - * Authors: - * Dan Winship <danw@ximian.com> - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <errno.h> - -#include "camel-pop3-folder.h" -#include "camel-pop3-store.h" -#include "camel-exception.h" -#include "camel-stream-mem.h" -#include "camel-stream-filter.h" -#include "camel-mime-message.h" -#include "camel-operation.h" -#include "camel-data-cache.h" -#include "camel-i18n.h" - -#include <libedataserver/md5-utils.h> - -#include <stdlib.h> -#include <string.h> - -#define d(x) - -#define CF_CLASS(o) (CAMEL_FOLDER_CLASS (CAMEL_OBJECT_GET_CLASS(o))) -static CamelFolderClass *parent_class; - -static void pop3_finalize (CamelObject *object); -static void pop3_refresh_info (CamelFolder *folder, CamelException *ex); -static void pop3_sync (CamelFolder *folder, gboolean expunge, CamelException *ex); -static gint pop3_get_message_count (CamelFolder *folder); -static GPtrArray *pop3_get_uids (CamelFolder *folder); -static CamelMimeMessage *pop3_get_message (CamelFolder *folder, const char *uid, CamelException *ex); -static gboolean pop3_set_message_flags (CamelFolder *folder, const char *uid, guint32 flags, guint32 set); - -static void -camel_pop3_folder_class_init (CamelPOP3FolderClass *camel_pop3_folder_class) -{ - CamelFolderClass *camel_folder_class = CAMEL_FOLDER_CLASS(camel_pop3_folder_class); - - parent_class = CAMEL_FOLDER_CLASS(camel_folder_get_type()); - - /* virtual method overload */ - camel_folder_class->refresh_info = pop3_refresh_info; - camel_folder_class->sync = pop3_sync; - - camel_folder_class->get_message_count = pop3_get_message_count; - camel_folder_class->get_uids = pop3_get_uids; - camel_folder_class->free_uids = camel_folder_free_shallow; - - camel_folder_class->get_message = pop3_get_message; - camel_folder_class->set_message_flags = pop3_set_message_flags; -} - -CamelType -camel_pop3_folder_get_type (void) -{ - static CamelType camel_pop3_folder_type = CAMEL_INVALID_TYPE; - - if (!camel_pop3_folder_type) { - camel_pop3_folder_type = camel_type_register (CAMEL_FOLDER_TYPE, "CamelPOP3Folder", - sizeof (CamelPOP3Folder), - sizeof (CamelPOP3FolderClass), - (CamelObjectClassInitFunc) camel_pop3_folder_class_init, - NULL, - NULL, - (CamelObjectFinalizeFunc) pop3_finalize); - } - - return camel_pop3_folder_type; -} - -static void -pop3_finalize (CamelObject *object) -{ - CamelPOP3Folder *pop3_folder = CAMEL_POP3_FOLDER (object); - CamelPOP3FolderInfo **fi = (CamelPOP3FolderInfo **)pop3_folder->uids->pdata; - CamelPOP3Store *pop3_store = (CamelPOP3Store *)((CamelFolder *)pop3_folder)->parent_store; - int i; - - if (pop3_folder->uids) { - for (i=0;i<pop3_folder->uids->len;i++,fi++) { - if (fi[0]->cmd) { - while (camel_pop3_engine_iterate(pop3_store->engine, fi[0]->cmd) > 0) - ; - camel_pop3_engine_command_free(pop3_store->engine, fi[0]->cmd); - } - - g_free(fi[0]->uid); - g_free(fi[0]); - } - - g_ptr_array_free(pop3_folder->uids, TRUE); - g_hash_table_destroy(pop3_folder->uids_uid); - } -} - -CamelFolder * -camel_pop3_folder_new (CamelStore *parent, CamelException *ex) -{ - CamelFolder *folder; - - d(printf("opening pop3 INBOX folder\n")); - - folder = CAMEL_FOLDER (camel_object_new (CAMEL_POP3_FOLDER_TYPE)); - camel_folder_construct (folder, parent, "inbox", "inbox"); - - /* mt-ok, since we dont have the folder-lock for new() */ - camel_folder_refresh_info (folder, ex);/* mt-ok */ - if (camel_exception_is_set (ex)) { - camel_object_unref (CAMEL_OBJECT (folder)); - folder = NULL; - } - - return folder; -} - -/* create a uid from md5 of 'top' output */ -static void -cmd_builduid(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data) -{ - CamelPOP3FolderInfo *fi = data; - MD5Context md5; - unsigned char digest[16]; - struct _camel_header_raw *h; - CamelMimeParser *mp; - - /* TODO; somehow work out the limit and use that for proper progress reporting - We need a pointer to the folder perhaps? */ - camel_operation_progress_count(NULL, fi->id); - - md5_init(&md5); - mp = camel_mime_parser_new(); - camel_mime_parser_init_with_stream(mp, (CamelStream *)stream); - switch (camel_mime_parser_step(mp, NULL, NULL)) { - case CAMEL_MIME_PARSER_STATE_HEADER: - case CAMEL_MIME_PARSER_STATE_MESSAGE: - case CAMEL_MIME_PARSER_STATE_MULTIPART: - h = camel_mime_parser_headers_raw(mp); - while (h) { - if (strcasecmp(h->name, "status") != 0 - && strcasecmp(h->name, "x-status") != 0) { - md5_update(&md5, h->name, strlen(h->name)); - md5_update(&md5, h->value, strlen(h->value)); - } - h = h->next; - } - default: - break; - } - camel_object_unref(mp); - md5_final(&md5, digest); - fi->uid = camel_base64_encode_simple(digest, 16); - - d(printf("building uid for id '%d' = '%s'\n", fi->id, fi->uid)); -} - -static void -cmd_list(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data) -{ - int ret; - unsigned int len, id, size; - unsigned char *line; - CamelFolder *folder = data; - CamelPOP3Store *pop3_store = CAMEL_POP3_STORE (folder->parent_store); - CamelPOP3FolderInfo *fi; - - do { - ret = camel_pop3_stream_line(stream, &line, &len); - if (ret>=0) { - if (sscanf(line, "%u %u", &id, &size) == 2) { - fi = g_malloc0(sizeof(*fi)); - fi->size = size; - fi->id = id; - fi->index = ((CamelPOP3Folder *)folder)->uids->len; - if ((pop3_store->engine->capa & CAMEL_POP3_CAP_UIDL) == 0) - fi->cmd = camel_pop3_engine_command_new(pe, CAMEL_POP3_COMMAND_MULTI, cmd_builduid, fi, "TOP %u 0\r\n", id); - g_ptr_array_add(((CamelPOP3Folder *)folder)->uids, fi); - g_hash_table_insert(((CamelPOP3Folder *)folder)->uids_id, GINT_TO_POINTER(id), fi); - } - } - } while (ret>0); -} - -static void -cmd_uidl(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data) -{ - int ret; - unsigned int len; - unsigned char *line; - char uid[1025]; - unsigned int id; - CamelPOP3FolderInfo *fi; - CamelPOP3Folder *folder = data; - - do { - ret = camel_pop3_stream_line(stream, &line, &len); - if (ret>=0) { - if (strlen(line) > 1024) - line[1024] = 0; - if (sscanf(line, "%u %s", &id, uid) == 2) { - fi = g_hash_table_lookup(folder->uids_id, GINT_TO_POINTER(id)); - if (fi) { - camel_operation_progress(NULL, (fi->index+1) * 100 / folder->uids->len); - fi->uid = g_strdup(uid); - g_hash_table_insert(folder->uids_uid, fi->uid, fi); - } else { - g_warning("ID %u (uid: %s) not in previous LIST output", id, uid); - } - } - } - } while (ret>0); -} - -static void -pop3_refresh_info (CamelFolder *folder, CamelException *ex) -{ - CamelPOP3Store *pop3_store = CAMEL_POP3_STORE (folder->parent_store); - CamelPOP3Folder *pop3_folder = (CamelPOP3Folder *) folder; - CamelPOP3Command *pcl, *pcu = NULL; - int i; - - camel_operation_start (NULL, _("Retrieving POP summary")); - - pop3_folder->uids = g_ptr_array_new (); - pop3_folder->uids_uid = g_hash_table_new(g_str_hash, g_str_equal); - /* only used during setup */ - pop3_folder->uids_id = g_hash_table_new(NULL, NULL); - - pcl = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, cmd_list, folder, "LIST\r\n"); - if (pop3_store->engine->capa & CAMEL_POP3_CAP_UIDL) { - pcu = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, cmd_uidl, folder, "UIDL\r\n"); - } - while ((i = camel_pop3_engine_iterate(pop3_store->engine, NULL)) > 0) - ; - - if (i == -1) { - if (errno == EINTR) - camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get POP summary: %s"), - g_strerror (errno)); - } - - /* TODO: check every id has a uid & commands returned OK too? */ - - camel_pop3_engine_command_free(pop3_store->engine, pcl); - - if (pop3_store->engine->capa & CAMEL_POP3_CAP_UIDL) { - camel_pop3_engine_command_free(pop3_store->engine, pcu); - } else { - for (i=0;i<pop3_folder->uids->len;i++) { - CamelPOP3FolderInfo *fi = pop3_folder->uids->pdata[i]; - if (fi->cmd) { - camel_pop3_engine_command_free(pop3_store->engine, fi->cmd); - fi->cmd = NULL; - } - if (fi->uid) - g_hash_table_insert(pop3_folder->uids_uid, fi->uid, fi); - } - } - - /* dont need this anymore */ - g_hash_table_destroy(pop3_folder->uids_id); - - camel_operation_end (NULL); - return; -} - -static void -pop3_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) -{ - CamelPOP3Folder *pop3_folder; - CamelPOP3Store *pop3_store; - int i; - CamelPOP3FolderInfo *fi; - - if (!expunge) - return; - - pop3_folder = CAMEL_POP3_FOLDER (folder); - pop3_store = CAMEL_POP3_STORE (folder->parent_store); - - camel_operation_start(NULL, _("Expunging deleted messages")); - - for (i = 0; i < pop3_folder->uids->len; i++) { - fi = pop3_folder->uids->pdata[i]; - /* busy already? wait for that to finish first */ - if (fi->cmd) { - while (camel_pop3_engine_iterate(pop3_store->engine, fi->cmd) > 0) - ; - camel_pop3_engine_command_free(pop3_store->engine, fi->cmd); - fi->cmd = NULL; - } - - if (fi->flags & CAMEL_MESSAGE_DELETED) { - fi->cmd = camel_pop3_engine_command_new(pop3_store->engine, 0, NULL, NULL, "DELE %u\r\n", fi->id); - - /* also remove from cache */ - if (pop3_store->cache && fi->uid) - camel_data_cache_remove(pop3_store->cache, "cache", fi->uid, NULL); - } - } - - for (i = 0; i < pop3_folder->uids->len; i++) { - fi = pop3_folder->uids->pdata[i]; - /* wait for delete commands to finish */ - if (fi->cmd) { - while (camel_pop3_engine_iterate(pop3_store->engine, fi->cmd) > 0) - ; - camel_pop3_engine_command_free(pop3_store->engine, fi->cmd); - fi->cmd = NULL; - } - camel_operation_progress(NULL, (i+1) * 100 / pop3_folder->uids->len); - } - - camel_operation_end(NULL); - - camel_pop3_store_expunge (pop3_store, ex); -} - -static void -cmd_tocache(CamelPOP3Engine *pe, CamelPOP3Stream *stream, void *data) -{ - CamelPOP3FolderInfo *fi = data; - char buffer[2048]; - int w = 0, n; - - /* What if it fails? */ - - /* We write an '*' to the start of the stream to say its not complete yet */ - /* This should probably be part of the cache code */ - if ((n = camel_stream_write(fi->stream, "*", 1)) == -1) - goto done; - - while ((n = camel_stream_read((CamelStream *)stream, buffer, sizeof(buffer))) > 0) { - n = camel_stream_write(fi->stream, buffer, n); - if (n == -1) - break; - - w += n; - if (w > fi->size) - w = fi->size; - if (fi->size != 0) - camel_operation_progress(NULL, (w * 100) / fi->size); - } - - /* it all worked, output a '#' to say we're a-ok */ - if (n != -1) { - camel_stream_reset(fi->stream); - n = camel_stream_write(fi->stream, "#", 1); - } -done: - if (n == -1) { - fi->err = errno; - g_warning("POP3 retrieval failed: %s", strerror(errno)); - } else { - fi->err = 0; - } - - camel_object_unref((CamelObject *)fi->stream); - fi->stream = NULL; -} - -static CamelMimeMessage * -pop3_get_message (CamelFolder *folder, const char *uid, CamelException *ex) -{ - CamelMimeMessage *message = NULL; - CamelPOP3Store *pop3_store = CAMEL_POP3_STORE (folder->parent_store); - CamelPOP3Folder *pop3_folder = (CamelPOP3Folder *)folder; - CamelPOP3Command *pcr; - CamelPOP3FolderInfo *fi; - char buffer[1]; - int ok, i, last; - CamelStream *stream = NULL; - - fi = g_hash_table_lookup(pop3_folder->uids_uid, uid); - if (fi == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, - _("No message with uid %s"), uid); - return NULL; - } - - /* Sigh, most of the crap in this function is so that the cancel button - returns the proper exception code. Sigh. */ - - camel_operation_start_transient(NULL, _("Retrieving POP message %d"), fi->id); - - /* If we have an oustanding retrieve message running, wait for that to complete - & then retrieve from cache, otherwise, start a new one, and similar */ - - if (fi->cmd != NULL) { - while ((i = camel_pop3_engine_iterate(pop3_store->engine, fi->cmd)) > 0) - ; - - if (i == -1) - fi->err = errno; - - /* getting error code? */ - ok = fi->cmd->state == CAMEL_POP3_COMMAND_DATA; - camel_pop3_engine_command_free(pop3_store->engine, fi->cmd); - fi->cmd = NULL; - - if (fi->err != 0) { - if (fi->err == EINTR) - camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get message %s: %s"), - uid, g_strerror (fi->err)); - goto fail; - } - } - - /* check to see if we have safely written flag set */ - if (pop3_store->cache == NULL - || (stream = camel_data_cache_get(pop3_store->cache, "cache", fi->uid, NULL)) == NULL - || camel_stream_read(stream, buffer, 1) != 1 - || buffer[0] != '#') { - - /* Initiate retrieval, if disk backing fails, use a memory backing */ - if (pop3_store->cache == NULL - || (stream = camel_data_cache_add(pop3_store->cache, "cache", fi->uid, NULL)) == NULL) - stream = camel_stream_mem_new(); - - /* ref it, the cache storage routine unref's when done */ - camel_object_ref((CamelObject *)stream); - fi->stream = stream; - fi->err = EIO; - pcr = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, cmd_tocache, fi, "RETR %u\r\n", fi->id); - - /* Also initiate retrieval of some of the following messages, assume we'll be receiving them */ - if (pop3_store->cache != NULL) { - /* This should keep track of the last one retrieved, also how many are still - oustanding incase of random access on large folders */ - i = fi->index+1; - last = MIN(i+10, pop3_folder->uids->len); - for (;i<last;i++) { - CamelPOP3FolderInfo *pfi = pop3_folder->uids->pdata[i]; - - if (pfi->uid && pfi->cmd == NULL) { - pfi->stream = camel_data_cache_add(pop3_store->cache, "cache", pfi->uid, NULL); - if (pfi->stream) { - pfi->err = EIO; - pfi->cmd = camel_pop3_engine_command_new(pop3_store->engine, CAMEL_POP3_COMMAND_MULTI, - cmd_tocache, pfi, "RETR %u\r\n", pfi->id); - } - } - } - } - - /* now wait for the first one to finish */ - while ((i = camel_pop3_engine_iterate(pop3_store->engine, pcr)) > 0) - ; - - if (i == -1) - fi->err = errno; - - /* getting error code? */ - ok = pcr->state == CAMEL_POP3_COMMAND_DATA; - camel_pop3_engine_command_free(pop3_store->engine, pcr); - camel_stream_reset(stream); - - /* Check to see we have safely written flag set */ - if (fi->err != 0) { - if (fi->err == EINTR) - camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get message %s: %s"), - uid, g_strerror (fi->err)); - goto done; - } - - if (camel_stream_read(stream, buffer, 1) != 1 || buffer[0] != '#') { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get message %s: %s"), uid, _("Unknown reason")); - goto done; - } - } - - message = camel_mime_message_new (); - if (camel_data_wrapper_construct_from_stream((CamelDataWrapper *)message, stream) == -1) { - if (errno == EINTR) - camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("User cancelled")); - else - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot get message %s: %s"), - uid, g_strerror (errno)); - camel_object_unref((CamelObject *)message); - message = NULL; - } -done: - camel_object_unref((CamelObject *)stream); -fail: - camel_operation_end(NULL); - - return message; -} - -static gboolean -pop3_set_message_flags (CamelFolder *folder, const char *uid, guint32 flags, guint32 set) -{ - CamelPOP3Folder *pop3_folder = CAMEL_POP3_FOLDER (folder); - CamelPOP3FolderInfo *fi; - gboolean res = FALSE; - - fi = g_hash_table_lookup(pop3_folder->uids_uid, uid); - if (fi) { - guint32 new = (fi->flags & ~flags) | (set & flags); - - if (fi->flags != new) { - fi->flags = new; - res = TRUE; - } - } - - return res; -} - -static gint -pop3_get_message_count (CamelFolder *folder) -{ - CamelPOP3Folder *pop3_folder = CAMEL_POP3_FOLDER (folder); - - return pop3_folder->uids->len; -} - -static GPtrArray * -pop3_get_uids (CamelFolder *folder) -{ - CamelPOP3Folder *pop3_folder = CAMEL_POP3_FOLDER (folder); - GPtrArray *uids = g_ptr_array_new(); - CamelPOP3FolderInfo **fi = (CamelPOP3FolderInfo **)pop3_folder->uids->pdata; - int i; - - for (i=0;i<pop3_folder->uids->len;i++,fi++) { - if (fi[0]->uid) - g_ptr_array_add(uids, fi[0]->uid); - } - - return uids; -} diff --git a/camel/providers/pop3/camel-pop3-folder.h b/camel/providers/pop3/camel-pop3-folder.h deleted file mode 100644 index 7dab07124c..0000000000 --- a/camel/providers/pop3/camel-pop3-folder.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-pop3-folder.h : Class for a POP3 folder */ - -/* - * Authors: - * Dan Winship <danw@ximian.com> - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_POP3_FOLDER_H -#define CAMEL_POP3_FOLDER_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-folder.h" - -#define CAMEL_POP3_FOLDER_TYPE (camel_pop3_folder_get_type ()) -#define CAMEL_POP3_FOLDER(obj) (CAMEL_CHECK_CAST((obj), CAMEL_POP3_FOLDER_TYPE, CamelPOP3Folder)) -#define CAMEL_POP3_FOLDER_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_POP3_FOLDER_TYPE, CamelPOP3FolderClass)) -#define CAMEL_IS_POP3_FOLDER(o) (CAMEL_CHECK_TYPE((o), CAMEL_POP3_FOLDER_TYPE)) - -typedef struct { - guint32 id; - guint32 size; - guint32 flags; - guint32 index; /* index of request */ - char *uid; - int err; - struct _CamelPOP3Command *cmd; - struct _CamelStream *stream; -} CamelPOP3FolderInfo; - -typedef struct { - CamelFolder parent_object; - - GPtrArray *uids; - GHashTable *uids_uid; /* messageinfo by uid */ - GHashTable *uids_id; /* messageinfo by id */ -} CamelPOP3Folder; - -typedef struct { - CamelFolderClass parent_class; - - /* Virtual methods */ - -} CamelPOP3FolderClass; - -/* public methods */ -CamelFolder *camel_pop3_folder_new (CamelStore *parent, CamelException *ex); - -/* Standard Camel function */ -CamelType camel_pop3_folder_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_POP3_FOLDER_H */ diff --git a/camel/providers/pop3/camel-pop3-provider.c b/camel/providers/pop3/camel-pop3-provider.c deleted file mode 100644 index 7253edfbf4..0000000000 --- a/camel/providers/pop3/camel-pop3-provider.c +++ /dev/null @@ -1,109 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-pop3-provider.c: pop3 provider registration code */ - -/* - * Authors : - * Dan Winship <danw@ximian.com> - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "camel-pop3-store.h" -#include "camel-provider.h" -#include "camel-session.h" -#include "camel-url.h" -#include "camel-sasl.h" -#include "camel-i18n.h" - -CamelProviderConfEntry pop3_conf_entries[] = { - { CAMEL_PROVIDER_CONF_SECTION_START, "storage", NULL, - N_("Message storage") }, - { CAMEL_PROVIDER_CONF_CHECKBOX, "keep_on_server", NULL, - N_("Leave messages on server"), "0" }, -#ifdef NOT_FOR_1_0 - { CAMEL_PROVIDER_CONF_CHECKSPIN, "delete_after", "UNIMPLEMENTED", - N_("Delete after %s day(s)"), "0:1:7:365" }, -#endif - { CAMEL_PROVIDER_CONF_CHECKBOX, "disable_extensions", NULL, - N_("Disable support for all POP3 extensions"), "0" }, - { CAMEL_PROVIDER_CONF_SECTION_END }, - { CAMEL_PROVIDER_CONF_END } -}; - -static CamelProvider pop3_provider = { - "pop", - - N_("POP"), - - N_("For connecting to and downloading mail from POP servers."), - - "mail", - - CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_IS_SOURCE | - CAMEL_PROVIDER_SUPPORTS_SSL, - - CAMEL_URL_NEED_USER | CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH, - - pop3_conf_entries, - - /* ... */ -}; - -CamelServiceAuthType camel_pop3_password_authtype = { - N_("Password"), - - N_("This option will connect to the POP server using a plaintext " - "password. This is the only option supported by many POP servers."), - - "", - TRUE -}; - -CamelServiceAuthType camel_pop3_apop_authtype = { - "APOP", - - N_("This option will connect to the POP server using an encrypted " - "password via the APOP protocol. This may not work for all users " - "even on servers that claim to support it."), - - "+APOP", - TRUE -}; - -void -camel_provider_module_init(void) -{ - CamelServiceAuthType *auth; - - pop3_provider.object_types[CAMEL_PROVIDER_STORE] = camel_pop3_store_get_type(); - pop3_provider.url_hash = camel_url_hash; - pop3_provider.url_equal = camel_url_equal; - - pop3_provider.authtypes = camel_sasl_authtype_list (FALSE); - auth = camel_sasl_authtype("LOGIN"); - if (auth) - pop3_provider.authtypes = g_list_prepend(pop3_provider.authtypes, auth); - pop3_provider.authtypes = g_list_prepend(pop3_provider.authtypes, &camel_pop3_apop_authtype); - pop3_provider.authtypes = g_list_prepend(pop3_provider.authtypes, &camel_pop3_password_authtype); - - camel_provider_register(&pop3_provider); -} diff --git a/camel/providers/pop3/camel-pop3-store.c b/camel/providers/pop3/camel-pop3-store.c deleted file mode 100644 index 46a1fd3fe6..0000000000 --- a/camel/providers/pop3/camel-pop3-store.c +++ /dev/null @@ -1,646 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-pop3-store.c : class for a pop3 store */ - -/* - * Authors: - * Dan Winship <danw@ximian.com> - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2000-2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -#include "camel-operation.h" - -#include "camel-pop3-store.h" -#include "camel-pop3-folder.h" -#include "camel-stream-buffer.h" -#include "camel-session.h" -#include "camel-exception.h" -#include "camel-url.h" -#include "libedataserver/md5-utils.h" -#include "camel-pop3-engine.h" -#include "camel-sasl.h" -#include "camel-data-cache.h" -#include "camel-tcp-stream.h" -#include "camel-tcp-stream-raw.h" -#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" - -static CamelStoreClass *parent_class = NULL; - -static void finalize (CamelObject *object); - -static gboolean pop3_connect (CamelService *service, CamelException *ex); -static gboolean pop3_disconnect (CamelService *service, gboolean clean, CamelException *ex); -static GList *query_auth_types (CamelService *service, CamelException *ex); - -static CamelFolder *get_folder (CamelStore *store, const char *folder_name, - guint32 flags, CamelException *ex); - -static CamelFolder *get_trash (CamelStore *store, CamelException *ex); - -static void -camel_pop3_store_class_init (CamelPOP3StoreClass *camel_pop3_store_class) -{ - CamelServiceClass *camel_service_class = - CAMEL_SERVICE_CLASS (camel_pop3_store_class); - CamelStoreClass *camel_store_class = - CAMEL_STORE_CLASS (camel_pop3_store_class); - - parent_class = CAMEL_STORE_CLASS (camel_type_get_global_classfuncs (camel_store_get_type ())); - - /* virtual method overload */ - camel_service_class->query_auth_types = query_auth_types; - camel_service_class->connect = pop3_connect; - camel_service_class->disconnect = pop3_disconnect; - - camel_store_class->get_folder = get_folder; - camel_store_class->get_trash = get_trash; -} - - - -static void -camel_pop3_store_init (gpointer object, gpointer klass) -{ - ; -} - -CamelType -camel_pop3_store_get_type (void) -{ - static CamelType camel_pop3_store_type = CAMEL_INVALID_TYPE; - - if (!camel_pop3_store_type) { - camel_pop3_store_type = camel_type_register (CAMEL_STORE_TYPE, - "CamelPOP3Store", - sizeof (CamelPOP3Store), - sizeof (CamelPOP3StoreClass), - (CamelObjectClassInitFunc) camel_pop3_store_class_init, - NULL, - (CamelObjectInitFunc) camel_pop3_store_init, - finalize); - } - - return camel_pop3_store_type; -} - -static void -finalize (CamelObject *object) -{ - CamelPOP3Store *pop3_store = CAMEL_POP3_STORE (object); - - /* force disconnect so we dont have it run later, after we've cleaned up some stuff */ - /* SIGH */ - - camel_service_disconnect((CamelService *)pop3_store, TRUE, NULL); - - if (pop3_store->engine) - camel_object_unref((CamelObject *)pop3_store->engine); - if (pop3_store->cache) - camel_object_unref((CamelObject *)pop3_store->cache); -} - -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) -{ - CamelPOP3Store *store = CAMEL_POP3_STORE (service); - CamelStream *tcp_stream; - CamelPOP3Command *pc; - guint32 flags = 0; - int clean_quit; - int ret; - - 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); - } else { - 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")); - - return FALSE; -#endif /* HAVE_SSL */ - } else { - tcp_stream = camel_tcp_stream_raw_new (); - } - - 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)); - - camel_object_unref (tcp_stream); - - return FALSE; - } - - /* parent class connect initialization */ - if (CAMEL_SERVICE_CLASS (parent_class)->connect (service, ex) == FALSE) { - camel_object_unref (tcp_stream); - return FALSE; - } - - if (camel_url_get_param (service->url, "disable_extensions")) - flags |= CAMEL_POP3_ENGINE_DISABLE_EXTENSIONS; - - 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); - return FALSE; - } - - if (ssl_mode != MODE_TLS) { - camel_object_unref (tcp_stream); - return TRUE; - } - - 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; - } - - /* as soon as we send a STLS command, all hope is lost of a clean QUIT if problems arise */ - clean_quit = FALSE; - - pc = camel_pop3_engine_command_new (store->engine, 0, NULL, NULL, "STLS\r\n"); - while (camel_pop3_engine_iterate (store->engine, NULL) > 0) - ; - - ret = pc->state == CAMEL_POP3_COMMAND_OK; - camel_pop3_engine_command_free (store->engine, pc); - - if (ret == FALSE) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to POP server %s in secure mode: %s"), - service->url->host, store->engine->line); - goto stls_exception; - } - - /* Okay, now toggle SSL/TLS mode */ - ret = camel_tcp_stream_ssl_enable_ssl (CAMEL_TCP_STREAM_SSL (tcp_stream)); - - if (ret == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to POP server %s in secure mode: %s"), - service->url->host, _("SSL negotiations failed")); - 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); - - return TRUE; - - stls_exception: - if (clean_quit) { - /* try to disconnect cleanly */ - pc = camel_pop3_engine_command_new (store->engine, 0, NULL, NULL, "QUIT\r\n"); - while (camel_pop3_engine_iterate (store->engine, NULL) > 0) - ; - camel_pop3_engine_command_free (store->engine, pc); - } - - camel_object_unref (CAMEL_OBJECT (store->engine)); - camel_object_unref (CAMEL_OBJECT (tcp_stream)); - store->engine = NULL; - - return FALSE; -} - -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 }, -}; - -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 = "pop3"; - port = POP3S_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); - } - - camel_freeaddrinfo (ai); - - return ret; -} - -extern CamelServiceAuthType camel_pop3_password_authtype; -extern CamelServiceAuthType camel_pop3_apop_authtype; - -static GList * -query_auth_types (CamelService *service, CamelException *ex) -{ - CamelPOP3Store *store = CAMEL_POP3_STORE (service); - GList *types = NULL; - - types = CAMEL_SERVICE_CLASS (parent_class)->query_auth_types (service, ex); - if (camel_exception_is_set (ex)) - return NULL; - - if (connect_to_server_wrapper (service, NULL)) { - types = g_list_concat(types, g_list_copy(store->engine->auth)); - pop3_disconnect (service, TRUE, NULL); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to POP server %s"), - service->url->host); - } - - return types; -} - -/** - * camel_pop3_store_expunge: - * @store: the store - * @ex: a CamelException - * - * Expunge messages from the store. This will result in the connection - * being closed, which may cause later commands to fail if they can't - * reconnect. - **/ -void -camel_pop3_store_expunge (CamelPOP3Store *store, CamelException *ex) -{ - CamelPOP3Command *pc; - - pc = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, "QUIT\r\n"); - while (camel_pop3_engine_iterate(store->engine, NULL) > 0) - ; - camel_pop3_engine_command_free(store->engine, pc); - - camel_service_disconnect (CAMEL_SERVICE (store), FALSE, ex); -} - -static int -try_sasl(CamelPOP3Store *store, const char *mech, CamelException *ex) -{ - CamelPOP3Stream *stream = store->engine->stream; - unsigned char *line, *resp; - CamelSasl *sasl; - unsigned int len; - int ret; - - sasl = camel_sasl_new("pop3", mech, (CamelService *)store); - if (sasl == NULL) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_URL_INVALID, - _("Unable to connect to POP server %s: " - "No support for requested authentication mechanism."), - CAMEL_SERVICE (store)->url->host); - return -1; - } - - if (camel_stream_printf((CamelStream *)stream, "AUTH %s\r\n", mech) == -1) - goto ioerror; - - while (1) { - if (camel_pop3_stream_line(stream, &line, &len) == -1) - goto ioerror; - if (strncmp(line, "+OK", 3) == 0) - break; - if (strncmp(line, "-ERR", 4) == 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("SASL `%s' Login failed for POP server %s: %s"), - mech, CAMEL_SERVICE (store)->url->host, line); - goto done; - } - /* If we dont get continuation, or the sasl object's run out of work, or we dont get a challenge, - its a protocol error, so fail, and try reset the server */ - if (strncmp(line, "+ ", 2) != 0 - || camel_sasl_authenticated(sasl) - || (resp = camel_sasl_challenge_base64(sasl, line+2, ex)) == NULL) { - camel_stream_printf((CamelStream *)stream, "*\r\n"); - camel_pop3_stream_line(stream, &line, &len); - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Cannot login to POP server %s: SASL Protocol error"), - CAMEL_SERVICE (store)->url->host); - goto done; - } - - ret = camel_stream_printf((CamelStream *)stream, "%s\r\n", resp); - g_free(resp); - if (ret == -1) - goto ioerror; - - } - camel_object_unref((CamelObject *)sasl); - return 0; - - ioerror: - if (errno == EINTR) { - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to authenticate on POP server %s: %s"), - CAMEL_SERVICE (store)->url->host, g_strerror (errno)); - } - done: - camel_object_unref((CamelObject *)sasl); - return -1; -} - -static int -pop3_try_authenticate (CamelService *service, gboolean reprompt, const char *errmsg, CamelException *ex) -{ - CamelPOP3Store *store = (CamelPOP3Store *)service; - CamelPOP3Command *pcu = NULL, *pcp = NULL; - int status; - - /* override, testing only */ - /*printf("Forcing authmech to 'login'\n"); - service->url->authmech = g_strdup("LOGIN");*/ - - if (!service->url->passwd) { - char *prompt; - guint32 flags = CAMEL_SESSION_PASSWORD_SECRET; - - if (reprompt) - flags |= CAMEL_SESSION_PASSWORD_REPROMPT; - - prompt = g_strdup_printf (_("%sPlease enter the POP password for %s on host %s"), - errmsg ? errmsg : "", - service->url->user, - service->url->host); - service->url->passwd = camel_session_get_password (camel_service_get_session (service), service, NULL, - prompt, "password", flags, ex); - g_free (prompt); - if (!service->url->passwd) - return FALSE; - } - - if (!service->url->authmech) { - /* pop engine will take care of pipelining ability */ - pcu = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, "USER %s\r\n", service->url->user); - pcp = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, "PASS %s\r\n", service->url->passwd); - } else if (strcmp(service->url->authmech, "+APOP") == 0 && store->engine->apop) { - char *secret, md5asc[33], *d; - unsigned char md5sum[16], *s; - - secret = g_alloca(strlen(store->engine->apop)+strlen(service->url->passwd)+1); - sprintf(secret, "%s%s", store->engine->apop, service->url->passwd); - md5_get_digest(secret, strlen (secret), md5sum); - - for (s = md5sum, d = md5asc; d < md5asc + 32; s++, d += 2) - sprintf (d, "%.2x", *s); - - pcp = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, "APOP %s %s\r\n", - service->url->user, md5asc); - } else { - CamelServiceAuthType *auth; - GList *l; - - l = store->engine->auth; - while (l) { - auth = l->data; - if (strcmp(auth->authproto, service->url->authmech) == 0) - return try_sasl(store, service->url->authmech, ex) == -1; - l = l->next; - } - - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_URL_INVALID, - _("Unable to connect to POP server %s: " - "No support for requested authentication mechanism."), - CAMEL_SERVICE (store)->url->host); - return FALSE; - } - - while ((status = camel_pop3_engine_iterate(store->engine, pcp)) > 0) - ; - - if (status == -1) { - if (errno == EINTR) { - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Cancelled")); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Unable to connect to POP server %s.\n" - "Error sending password: %s"), - CAMEL_SERVICE (store)->url->host, - errno ? g_strerror (errno) : _("Unknown error")); - } - } else if (pcu && pcu->state != CAMEL_POP3_COMMAND_OK) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Unable to connect to POP server %s.\n" - "Error sending username: %s"), - CAMEL_SERVICE (store)->url->host, - store->engine->line ? (char *)store->engine->line : _("Unknown error")); - } else if (pcp->state != CAMEL_POP3_COMMAND_OK) - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Unable to connect to POP server %s.\n" - "Error sending password: %s"), - CAMEL_SERVICE (store)->url->host, - store->engine->line ? (char *)store->engine->line : _("Unknown error")); - - camel_pop3_engine_command_free(store->engine, pcp); - - if (pcu) - camel_pop3_engine_command_free(store->engine, pcu); - - return status; -} - -static gboolean -pop3_connect (CamelService *service, CamelException *ex) -{ - CamelPOP3Store *store = (CamelPOP3Store *)service; - gboolean reprompt = FALSE; - CamelSession *session; - char *errbuf = NULL; - int status; - - session = camel_service_get_session (service); - - if (store->cache == NULL) { - char *root; - - root = camel_session_get_storage_path (session, service, ex); - if (root) { - store->cache = camel_data_cache_new(root, 0, ex); - g_free(root); - if (store->cache) { - /* Default cache expiry - 1 week or not visited in a day */ - camel_data_cache_set_expire_age(store->cache, 60*60*24*7); - camel_data_cache_set_expire_access(store->cache, 60*60*24); - } - } - } - - if (!connect_to_server_wrapper (service, ex)) - return FALSE; - - do { - status = pop3_try_authenticate (service, reprompt, errbuf, ex); - g_free (errbuf); - errbuf = NULL; - - /* we only re-prompt if we failed to authenticate, any other error and we just abort */ - if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE) { - errbuf = g_strdup_printf ("%s\n\n", camel_exception_get_description (ex)); - g_free (service->url->passwd); - service->url->passwd = NULL; - reprompt = TRUE; - camel_exception_clear (ex); - } - } while (status != -1 && ex->id == CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE); - - g_free (errbuf); - - if (status == -1 || camel_exception_is_set(ex)) { - camel_service_disconnect(service, TRUE, ex); - return FALSE; - } - - /* Now that we are in the TRANSACTION state, try regetting the capabilities */ - store->engine->state = CAMEL_POP3_ENGINE_TRANSACTION; - camel_pop3_engine_reget_capabilities (store->engine); - - return TRUE; -} - -static gboolean -pop3_disconnect (CamelService *service, gboolean clean, CamelException *ex) -{ - CamelPOP3Store *store = CAMEL_POP3_STORE (service); - - if (clean) { - CamelPOP3Command *pc; - - pc = camel_pop3_engine_command_new(store->engine, 0, NULL, NULL, "QUIT\r\n"); - while (camel_pop3_engine_iterate(store->engine, NULL) > 0) - ; - camel_pop3_engine_command_free(store->engine, pc); - } - - if (!CAMEL_SERVICE_CLASS (parent_class)->disconnect (service, clean, ex)) - return FALSE; - - camel_object_unref((CamelObject *)store->engine); - store->engine = NULL; - - return TRUE; -} - -static CamelFolder * -get_folder (CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex) -{ - if (g_ascii_strcasecmp (folder_name, "inbox") != 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID, - _("No such folder `%s'."), folder_name); - return NULL; - } - return camel_pop3_folder_new (store, ex); -} - -static CamelFolder * -get_trash (CamelStore *store, CamelException *ex) -{ - /* no-op */ - return NULL; -} diff --git a/camel/providers/pop3/camel-pop3-store.h b/camel/providers/pop3/camel-pop3-store.h deleted file mode 100644 index 3b9b1f7ae1..0000000000 --- a/camel/providers/pop3/camel-pop3-store.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-pop3-store.h : class for an pop3 store */ - -/* - * Authors: - * Dan Winship <danw@ximian.com> - * Michael Zucchi <notzed@ximian.com> - * - * Copyright (C) 2000-2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_POP3_STORE_H -#define CAMEL_POP3_STORE_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include <camel/camel-types.h> -#include <camel/camel-store.h> -#include "camel-pop3-engine.h" - -#define CAMEL_POP3_STORE_TYPE (camel_pop3_store_get_type ()) -#define CAMEL_POP3_STORE(obj) (CAMEL_CHECK_CAST((obj), CAMEL_POP3_STORE_TYPE, CamelPOP3Store)) -#define CAMEL_POP3_STORE_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_POP3_STORE_TYPE, CamelPOP3StoreClass)) -#define CAMEL_IS_POP3_STORE(o) (CAMEL_CHECK_TYPE((o), CAMEL_POP3_STORE_TYPE)) - - -typedef struct { - CamelStore parent_object; - - CamelPOP3Engine *engine; /* pop processing engine */ - - struct _CamelDataCache *cache; -} CamelPOP3Store; - - - -typedef struct { - CamelStoreClass parent_class; - -} CamelPOP3StoreClass; - - -/* public methods */ -void camel_pop3_store_expunge (CamelPOP3Store *store, CamelException *ex); - -/* support functions */ -enum { CAMEL_POP3_OK, CAMEL_POP3_ERR, CAMEL_POP3_FAIL }; -int camel_pop3_command (CamelPOP3Store *store, char **ret, CamelException *ex, char *fmt, ...); -char *camel_pop3_command_get_additional_data (CamelPOP3Store *store, int total, CamelException *ex); - -/* Standard Camel function */ -CamelType camel_pop3_store_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_POP3_STORE_H */ - - diff --git a/camel/providers/pop3/camel-pop3-stream.c b/camel/providers/pop3/camel-pop3-stream.c deleted file mode 100644 index cb27bece26..0000000000 --- a/camel/providers/pop3/camel-pop3-stream.c +++ /dev/null @@ -1,471 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; fill-column: 160 -*- - * - * Author: - * Michael Zucchi <notzed@ximian.com> - * - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -/* This is *identical* to the camel-nntp-stream, so should probably - work out a way to merge them */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <errno.h> - -#include <string.h> -#include <stdio.h> - -#include <glib.h> - -#include "camel-pop3-stream.h" - -extern int camel_verbose_debug; -#define dd(x) (camel_verbose_debug?(x):0) - -static CamelObjectClass *parent_class = NULL; - -/* Returns the class for a CamelStream */ -#define CS_CLASS(so) CAMEL_POP3_STREAM_CLASS(CAMEL_OBJECT_GET_CLASS(so)) - -#define CAMEL_POP3_STREAM_SIZE (4096) -#define CAMEL_POP3_STREAM_LINE (1024) /* maximum line size */ - -static int -stream_fill(CamelPOP3Stream *is) -{ - int left = 0; - - if (is->source) { - left = is->end - is->ptr; - memcpy(is->buf, is->ptr, left); - is->end = is->buf + left; - is->ptr = is->buf; - left = camel_stream_read(is->source, is->end, CAMEL_POP3_STREAM_SIZE - (is->end - is->buf)); - if (left > 0) { - is->end += left; - is->end[0] = '\n'; - return is->end - is->ptr; - } else { - dd(printf("POP3_STREAM_FILL(ERROR): '%s'\n", strerror (errno))); - return -1; - } - } - - return 0; -} - -static ssize_t -stream_read(CamelStream *stream, char *buffer, size_t n) -{ - CamelPOP3Stream *is = (CamelPOP3Stream *)stream; - char *o, *oe; - unsigned char *p, *e, c; - int state; - - if (is->mode != CAMEL_POP3_STREAM_DATA || n == 0) - return 0; - - o = buffer; - oe = buffer + n; - state = is->state; - - /* Need to copy/strip '.'s and whatnot */ - p = is->ptr; - e = is->end; - - switch(state) { - state_0: - case 0: /* start of line, always read at least 3 chars */ - while (e - p < 3) { - is->ptr = p; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } - if (p[0] == '.') { - if (p[1] == '\r' && p[2] == '\n') { - is->ptr = p+3; - is->mode = CAMEL_POP3_STREAM_EOD; - is->state = 0; - dd(printf("POP3_STREAM_READ(%d):\n%.*s\n", o-buffer, o-buffer, buffer)); - return o-buffer; - } - p++; - } - state = 1; - /* FALLS THROUGH */ - case 1: /* looking for next sol */ - while (o < oe) { - c = *p++; - if (c == '\n') { - /* end of input sentinal check */ - if (p > e) { - is->ptr = e; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } else { - *o++ = '\n'; - state = 0; - goto state_0; - } - } else if (c != '\r') { - *o++ = c; - } - } - break; - } - - is->ptr = p; - is->state = state; - - dd(printf("POP3_STREAM_READ(%d):\n%.*s\n", o-buffer, o-buffer, buffer)); - - return o-buffer; -} - -static ssize_t -stream_write(CamelStream *stream, const char *buffer, size_t n) -{ - CamelPOP3Stream *is = (CamelPOP3Stream *)stream; - - if (strncmp (buffer, "PASS ", 5) != 0) - dd(printf("POP3_STREAM_WRITE(%d):\n%.*s\n", n, (int)n, buffer)); - else - dd(printf("POP3_STREAM_WRITE(%d):\nPASS xxxxxxxx\n", n)); - - return camel_stream_write(is->source, buffer, n); -} - -static int -stream_close(CamelStream *stream) -{ - /* nop? */ - return 0; -} - -static int -stream_flush(CamelStream *stream) -{ - /* nop? */ - return 0; -} - -static gboolean -stream_eos(CamelStream *stream) -{ - CamelPOP3Stream *is = (CamelPOP3Stream *)stream; - - return is->mode != CAMEL_POP3_STREAM_DATA; -} - -static int -stream_reset(CamelStream *stream) -{ - /* nop? reset literal mode? */ - return 0; -} - -static void -camel_pop3_stream_class_init (CamelStreamClass *camel_pop3_stream_class) -{ - CamelStreamClass *camel_stream_class = (CamelStreamClass *)camel_pop3_stream_class; - - parent_class = camel_type_get_global_classfuncs( CAMEL_OBJECT_TYPE ); - - /* virtual method definition */ - camel_stream_class->read = stream_read; - camel_stream_class->write = stream_write; - camel_stream_class->close = stream_close; - camel_stream_class->flush = stream_flush; - camel_stream_class->eos = stream_eos; - camel_stream_class->reset = stream_reset; -} - -static void -camel_pop3_stream_init(CamelPOP3Stream *is, CamelPOP3StreamClass *isclass) -{ - /* +1 is room for appending a 0 if we need to for a line */ - is->ptr = is->end = is->buf = g_malloc(CAMEL_POP3_STREAM_SIZE+1); - is->lineptr = is->linebuf = g_malloc(CAMEL_POP3_STREAM_LINE+1); - is->lineend = is->linebuf + CAMEL_POP3_STREAM_LINE; - - /* init sentinal */ - is->ptr[0] = '\n'; - - is->state = 0; - is->mode = CAMEL_POP3_STREAM_LINE; -} - -static void -camel_pop3_stream_finalise(CamelPOP3Stream *is) -{ - g_free(is->buf); - g_free(is->linebuf); - if (is->source) - camel_object_unref((CamelObject *)is->source); -} - -CamelType -camel_pop3_stream_get_type (void) -{ - static CamelType camel_pop3_stream_type = CAMEL_INVALID_TYPE; - - if (camel_pop3_stream_type == CAMEL_INVALID_TYPE) { - camel_pop3_stream_type = camel_type_register( camel_stream_get_type(), - "CamelPOP3Stream", - sizeof( CamelPOP3Stream ), - sizeof( CamelPOP3StreamClass ), - (CamelObjectClassInitFunc) camel_pop3_stream_class_init, - NULL, - (CamelObjectInitFunc) camel_pop3_stream_init, - (CamelObjectFinalizeFunc) camel_pop3_stream_finalise ); - } - - return camel_pop3_stream_type; -} - -/** - * camel_pop3_stream_new: - * - * Returns a NULL stream. A null stream is always at eof, and - * always returns success for all reads and writes. - * - * Return value: the stream - **/ -CamelStream * -camel_pop3_stream_new(CamelStream *source) -{ - CamelPOP3Stream *is; - - is = (CamelPOP3Stream *)camel_object_new(camel_pop3_stream_get_type ()); - camel_object_ref((CamelObject *)source); - is->source = source; - - return (CamelStream *)is; -} - -/* Get one line from the pop3 stream */ -int -camel_pop3_stream_line(CamelPOP3Stream *is, unsigned char **data, unsigned int *len) -{ - register unsigned char c, *p, *o, *oe; - int newlen, oldlen; - unsigned char *e; - - if (is->mode == CAMEL_POP3_STREAM_EOD) { - *data = is->linebuf; - *len = 0; - return 0; - } - - o = is->linebuf; - oe = is->lineend - 1; - p = is->ptr; - e = is->end; - - /* Data mode, convert leading '..' to '.', and stop when we reach a solitary '.' */ - if (is->mode == CAMEL_POP3_STREAM_DATA) { - /* need at least 3 chars in buffer */ - while (e-p < 3) { - is->ptr = p; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } - - /* check for isolated '.\r\n' or begging of line '.' */ - if (p[0] == '.') { - if (p[1] == '\r' && p[2] == '\n') { - is->ptr = p+3; - is->mode = CAMEL_POP3_STREAM_EOD; - *data = is->linebuf; - *len = 0; - is->linebuf[0] = 0; - - dd(printf("POP3_STREAM_LINE(END)\n")); - - return 0; - } - p++; - } - } - - while (1) { - while (o < oe) { - c = *p++; - if (c == '\n') { - /* sentinal? */ - if (p> e) { - is->ptr = e; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } else { - is->ptr = p; - *data = is->linebuf; - *len = o - is->linebuf; - *o = 0; - - dd(printf("POP3_STREAM_LINE(%d): '%s'\n", *len, *data)); - - return 1; - } - } else if (c != '\r') { - *o++ = c; - } - } - - /* limit this for bad server data? */ - oldlen = o - is->linebuf; - newlen = (is->lineend - is->linebuf) * 3 / 2; - is->lineptr = is->linebuf = g_realloc(is->linebuf, newlen); - is->lineend = is->linebuf + newlen; - oe = is->lineend - 1; - o = is->linebuf + oldlen; - } - - return -1; -} - -/* returns -1 on error, 0 if last lot of data, >0 if more remaining */ -int camel_pop3_stream_gets(CamelPOP3Stream *is, unsigned char **start, unsigned int *len) -{ - int max; - unsigned char *end; - - *len = 0; - - max = is->end - is->ptr; - if (max == 0) { - max = stream_fill(is); - if (max <= 0) - return max; - } - - *start = is->ptr; - end = memchr(is->ptr, '\n', max); - if (end) - max = (end - is->ptr) + 1; - *start = is->ptr; - *len = max; - is->ptr += max; - - dd(printf("POP3_STREAM_GETS(%s,%d): '%.*s'\n", end==NULL?"more":"last", *len, (int)*len, *start)); - - return end == NULL?1:0; -} - -void camel_pop3_stream_set_mode(CamelPOP3Stream *is, camel_pop3_stream_mode_t mode) -{ - is->mode = mode; -} - -/* returns -1 on erorr, 0 if last data, >0 if more data left */ -int camel_pop3_stream_getd(CamelPOP3Stream *is, unsigned char **start, unsigned int *len) -{ - unsigned char *p, *e, *s; - int state; - - *len = 0; - - if (is->mode == CAMEL_POP3_STREAM_EOD) - return 0; - - if (is->mode == CAMEL_POP3_STREAM_LINE) { - g_warning("pop3_stream reading data in line mode\n"); - return 0; - } - - state = is->state; - p = is->ptr; - e = is->end; - - while (e - p < 3) { - is->ptr = p; - if (stream_fill(is) == -1) - return -1; - p = is->ptr; - e = is->end; - } - - s = p; - - do { - switch(state) { - case 0: - /* check leading '.', ... */ - if (p[0] == '.') { - if (p[1] == '\r' && p[2] == '\n') { - is->ptr = p+3; - *len = p-s; - *start = s; - is->mode = CAMEL_POP3_STREAM_EOD; - is->state = 0; - - dd(printf("POP3_STREAM_GETD(%s,%d): '%.*s'\n", "last", *len, (int)*len, *start)); - - return 0; - } - - /* If at start, just skip '.', else return data upto '.' but skip it */ - if (p == s) { - s++; - p++; - } else { - is->ptr = p+1; - *len = p-s; - *start = s; - is->state = 1; - - dd(printf("POP3_STREAM_GETD(%s,%d): '%.*s'\n", "more", *len, (int)*len, *start)); - - return 1; - } - } - state = 1; - case 1: - /* Scan for sentinal */ - while ((*p++)!='\n') - ; - - if (p > e) { - p = e; - } else { - state = 0; - } - break; - } - } while ((e-p) >= 3); - - is->state = state; - is->ptr = p; - *len = p-s; - *start = s; - - dd(printf("POP3_STREAM_GETD(%s,%d): '%.*s'\n", "more", *len, (int)*len, *start)); - - return 1; -} diff --git a/camel/providers/pop3/camel-pop3-stream.h b/camel/providers/pop3/camel-pop3-stream.h deleted file mode 100644 index 2a4ebc01f2..0000000000 --- a/camel/providers/pop3/camel-pop3-stream.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2002 Ximian Inc. - * - * 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 - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* This is *identical* to the camel-nntp-stream, so should probably - work out a way to merge them */ - -#ifndef _CAMEL_POP3_STREAM_H -#define _CAMEL_POP3_STREAM_H - -#include <camel/camel-stream.h> - -#define CAMEL_POP3_STREAM(obj) CAMEL_CHECK_CAST (obj, camel_pop3_stream_get_type (), CamelPOP3Stream) -#define CAMEL_POP3_STREAM_CLASS(klass) CAMEL_CHECK_CLASS_CAST (klass, camel_pop3_stream_get_type (), CamelPOP3StreamClass) -#define CAMEL_IS_POP3_STREAM(obj) CAMEL_CHECK_TYPE (obj, camel_pop3_stream_get_type ()) - -typedef struct _CamelPOP3StreamClass CamelPOP3StreamClass; -typedef struct _CamelPOP3Stream CamelPOP3Stream; - -typedef enum { - CAMEL_POP3_STREAM_LINE, - CAMEL_POP3_STREAM_DATA, - CAMEL_POP3_STREAM_EOD, /* end of data, acts as if end of stream */ -} camel_pop3_stream_mode_t; - -struct _CamelPOP3Stream { - CamelStream parent; - - CamelStream *source; - - camel_pop3_stream_mode_t mode; - int state; - - unsigned char *buf, *ptr, *end; - unsigned char *linebuf, *lineptr, *lineend; -}; - -struct _CamelPOP3StreamClass { - CamelStreamClass parent_class; -}; - -CamelType camel_pop3_stream_get_type (void); - -CamelStream *camel_pop3_stream_new (CamelStream *source); - - -void camel_pop3_stream_set_mode (CamelPOP3Stream *is, camel_pop3_stream_mode_t mode); - -int camel_pop3_stream_line (CamelPOP3Stream *is, unsigned char **data, unsigned int *len); -int camel_pop3_stream_gets (CamelPOP3Stream *is, unsigned char **start, unsigned int *len); -int camel_pop3_stream_getd (CamelPOP3Stream *is, unsigned char **start, unsigned int *len); - -#endif /* ! _CAMEL_POP3_STREAM_H */ diff --git a/camel/providers/pop3/libcamelpop3.urls b/camel/providers/pop3/libcamelpop3.urls deleted file mode 100644 index 7fffa4d861..0000000000 --- a/camel/providers/pop3/libcamelpop3.urls +++ /dev/null @@ -1 +0,0 @@ -pop diff --git a/camel/providers/sendmail/.cvsignore b/camel/providers/sendmail/.cvsignore deleted file mode 100644 index 097fdedafb..0000000000 --- a/camel/providers/sendmail/.cvsignore +++ /dev/null @@ -1,11 +0,0 @@ -Makefile -Makefile.in -.deps -.libs -*.lo -*.la -*.o -*.bb -*.bbg -*.da -*.gcov diff --git a/camel/providers/sendmail/Makefile.am b/camel/providers/sendmail/Makefile.am deleted file mode 100644 index 46e3613081..0000000000 --- a/camel/providers/sendmail/Makefile.am +++ /dev/null @@ -1,26 +0,0 @@ -## Process this file with automake to produce Makefile.in - -camel_provider_LTLIBRARIES = libcamelsendmail.la -camel_provider_DATA = libcamelsendmail.urls - -INCLUDES = \ - -I.. \ - -I$(srcdir)/.. \ - -I$(srcdir)/../../.. \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/camel \ - $(CAMEL_CFLAGS) \ - $(GNOME_INCLUDEDIR) \ - $(GTK_INCLUDEDIR) \ - -DG_LOG_DOMAIN=\"camel-sendmail-provider\" - -libcamelsendmail_la_SOURCES = \ - camel-sendmail-provider.c \ - camel-sendmail-transport.c - -noinst_HEADERS = \ - camel-sendmail-transport.h - -libcamelsendmail_la_LDFLAGS = -avoid-version -module - -EXTRA_DIST = libcamelsendmail.urls diff --git a/camel/providers/sendmail/camel-sendmail-provider.c b/camel/providers/sendmail/camel-sendmail-provider.c deleted file mode 100644 index 0aeb367cf3..0000000000 --- a/camel/providers/sendmail/camel-sendmail-provider.c +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-sendmail-provider.c: sendmail provider registration code */ - -/* - * Authors : - * Dan Winship <danw@ximian.com> - * - * Copyright (C) 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "camel-provider.h" -#include "camel-sendmail-transport.h" -#include "camel-session.h" -#include "camel-url.h" -#include "camel-i18n.h" - -static CamelProvider sendmail_provider = { - "sendmail", - N_("Sendmail"), - - N_("For delivering mail by passing it to the \"sendmail\" program " - "on the local system."), - - "mail", - - 0, /* flags */ - - 0, /* url_flags */ - - /* ... */ -}; - -void -camel_provider_module_init(void) -{ - sendmail_provider.object_types[CAMEL_PROVIDER_TRANSPORT] = camel_sendmail_transport_get_type(); - - sendmail_provider.url_hash = camel_url_hash; - sendmail_provider.url_equal = camel_url_equal; - - camel_provider_register(&sendmail_provider); -} - - - diff --git a/camel/providers/sendmail/camel-sendmail-transport.c b/camel/providers/sendmail/camel-sendmail-transport.c deleted file mode 100644 index a776b9729e..0000000000 --- a/camel/providers/sendmail/camel-sendmail-transport.c +++ /dev/null @@ -1,263 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-sendmail-transport.c: Sendmail-based transport class. */ - -/* - * - * Authors: Dan Winship <danw@ximian.com> - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <sys/wait.h> -#include <unistd.h> -#include <string.h> - -#include "camel-sendmail-transport.h" -#include "camel-mime-filter-crlf.h" -#include "camel-stream-filter.h" -#include "camel-mime-message.h" -#include "camel-data-wrapper.h" -#include "camel-stream-fs.h" -#include "camel-exception.h" -#include "camel-i18n.h" - -static char *get_name (CamelService *service, gboolean brief); - -static gboolean sendmail_send_to (CamelTransport *transport, - CamelMimeMessage *message, - CamelAddress *from, CamelAddress *recipients, - CamelException *ex); - - -static void -camel_sendmail_transport_class_init (CamelSendmailTransportClass *camel_sendmail_transport_class) -{ - CamelTransportClass *camel_transport_class = - CAMEL_TRANSPORT_CLASS (camel_sendmail_transport_class); - CamelServiceClass *camel_service_class = - CAMEL_SERVICE_CLASS (camel_sendmail_transport_class); - - /* virtual method overload */ - camel_service_class->get_name = get_name; - camel_transport_class->send_to = sendmail_send_to; -} - -CamelType -camel_sendmail_transport_get_type (void) -{ - static CamelType camel_sendmail_transport_type = CAMEL_INVALID_TYPE; - - if (camel_sendmail_transport_type == CAMEL_INVALID_TYPE) { - camel_sendmail_transport_type = - camel_type_register (CAMEL_TRANSPORT_TYPE, "CamelSendmailTransport", - sizeof (CamelSendmailTransport), - sizeof (CamelSendmailTransportClass), - (CamelObjectClassInitFunc) camel_sendmail_transport_class_init, - NULL, - (CamelObjectInitFunc) NULL, - NULL); - } - - return camel_sendmail_transport_type; -} - - -static gboolean -sendmail_send_to (CamelTransport *transport, CamelMimeMessage *message, - CamelAddress *from, CamelAddress *recipients, - CamelException *ex) -{ - struct _camel_header_raw *header, *savedbcc, *n, *tail; - const char *from_addr, *addr, **argv; - int i, len, fd[2], nullfd, wstat; - CamelStreamFilter *filter; - CamelMimeFilter *crlf; - sigset_t mask, omask; - CamelStream *out; - pid_t pid; - - if (!camel_internet_address_get (CAMEL_INTERNET_ADDRESS (from), 0, NULL, &from_addr)) - return FALSE; - - len = camel_address_length (recipients); - argv = g_malloc ((len + 6) * sizeof (char *)); - argv[0] = "sendmail"; - argv[1] = "-i"; - argv[2] = "-f"; - argv[3] = from_addr; - argv[4] = "--"; - - for (i = 0; i < len; i++) { - if (!camel_internet_address_get (CAMEL_INTERNET_ADDRESS (recipients), i, NULL, &addr)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not parse recipient list")); - g_free (argv); - return FALSE; - } - - argv[i + 5] = addr; - } - - argv[i + 5] = NULL; - - /* unlink the bcc headers */ - savedbcc = NULL; - tail = (struct _camel_header_raw *) &savedbcc; - - header = (struct _camel_header_raw *) &CAMEL_MIME_PART (message)->headers; - n = header->next; - while (n != NULL) { - if (!strcasecmp (n->name, "Bcc")) { - header->next = n->next; - tail->next = n; - n->next = NULL; - tail = n; - } else { - header = n; - } - - n = header->next; - } - - if (pipe (fd) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create pipe to sendmail: " - "%s: mail not sent"), - g_strerror (errno)); - - /* restore the bcc headers */ - header->next = savedbcc; - - return FALSE; - } - - /* Block SIGCHLD so the calling application doesn't notice - * sendmail exiting before we do. - */ - sigemptyset (&mask); - sigaddset (&mask, SIGCHLD); - sigprocmask (SIG_BLOCK, &mask, &omask); - - pid = fork (); - switch (pid) { - case -1: - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not fork sendmail: " - "%s: mail not sent"), - g_strerror (errno)); - sigprocmask (SIG_SETMASK, &omask, NULL); - g_free (argv); - - /* restore the bcc headers */ - header->next = savedbcc; - - return FALSE; - case 0: - /* Child process */ - nullfd = open ("/dev/null", O_RDWR); - dup2 (fd[0], STDIN_FILENO); - /*dup2 (nullfd, STDOUT_FILENO); - dup2 (nullfd, STDERR_FILENO);*/ - close (nullfd); - close (fd[1]); - - execv (SENDMAIL_PATH, (char **)argv); - _exit (255); - } - g_free (argv); - - /* Parent process. Write the message out. */ - close (fd[0]); - out = camel_stream_fs_new_with_fd (fd[1]); - - /* workaround for lame sendmail implementations that can't handle CRLF eoln sequences */ - filter = camel_stream_filter_new_with_stream (out); - crlf = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_DECODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); - camel_stream_filter_add (filter, crlf); - camel_object_unref (crlf); - camel_object_unref (out); - - out = (CamelStream *) filter; - if (camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), out) == -1 - || camel_stream_close (out) == -1) { - camel_object_unref (CAMEL_OBJECT (out)); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not send message: %s"), - g_strerror (errno)); - - /* Wait for sendmail to exit. */ - while (waitpid (pid, &wstat, 0) == -1 && errno == EINTR) - ; - - sigprocmask (SIG_SETMASK, &omask, NULL); - - /* restore the bcc headers */ - header->next = savedbcc; - - return FALSE; - } - - camel_object_unref (CAMEL_OBJECT (out)); - - /* Wait for sendmail to exit. */ - while (waitpid (pid, &wstat, 0) == -1 && errno == EINTR) - ; - - sigprocmask (SIG_SETMASK, &omask, NULL); - - /* restore the bcc headers */ - header->next = savedbcc; - - if (!WIFEXITED (wstat)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("sendmail exited with signal %s: " - "mail not sent."), - g_strsignal (WTERMSIG (wstat))); - return FALSE; - } else if (WEXITSTATUS (wstat) != 0) { - if (WEXITSTATUS (wstat) == 255) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not execute %s: " - "mail not sent."), - SENDMAIL_PATH); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("sendmail exited with status " - "%d: mail not sent."), - WEXITSTATUS (wstat)); - } - return FALSE; - } - - return TRUE; -} - -static char * -get_name (CamelService *service, gboolean brief) -{ - if (brief) - return g_strdup (_("sendmail")); - else - return g_strdup (_("Mail delivery via the sendmail program")); -} diff --git a/camel/providers/sendmail/camel-sendmail-transport.h b/camel/providers/sendmail/camel-sendmail-transport.h deleted file mode 100644 index 056be03bc8..0000000000 --- a/camel/providers/sendmail/camel-sendmail-transport.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-sendmail-transport.h: Sendmail-based transport class */ - -/* - * - * Author : - * Dan Winship <danw@ximian.com> - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifndef CAMEL_SENDMAIL_TRANSPORT_H -#define CAMEL_SENDMAIL_TRANSPORT_H 1 - - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus }*/ - -#include "camel-transport.h" - -#define CAMEL_SENDMAIL_TRANSPORT_TYPE (camel_sendmail_transport_get_type ()) -#define CAMEL_SENDMAIL_TRANSPORT(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SENDMAIL_TRANSPORT_TYPE, CamelSendmailTransport)) -#define CAMEL_SENDMAIL_TRANSPORT_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SENDMAIL_TRANSPORT_TYPE, CamelSendmailTransportClass)) -#define CAMEL_IS_SENDMAIL_TRANSPORT(o) (CAMEL_CHECK_TYPE((o), CAMEL_SENDMAIL_TRANSPORT_TYPE)) - - -typedef struct { - CamelTransport parent_object; - -} CamelSendmailTransport; - - -typedef struct { - CamelTransportClass parent_class; - -} CamelSendmailTransportClass; - - -/* Standard Camel function */ -CamelType camel_sendmail_transport_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SENDMAIL_TRANSPORT_H */ diff --git a/camel/providers/sendmail/libcamelsendmail.urls b/camel/providers/sendmail/libcamelsendmail.urls deleted file mode 100644 index ccad52828e..0000000000 --- a/camel/providers/sendmail/libcamelsendmail.urls +++ /dev/null @@ -1 +0,0 @@ -sendmail diff --git a/camel/providers/smtp/.cvsignore b/camel/providers/smtp/.cvsignore deleted file mode 100644 index b948585108..0000000000 --- a/camel/providers/smtp/.cvsignore +++ /dev/null @@ -1,10 +0,0 @@ -.deps -.libs -Makefile -Makefile.in -*.lo -*.la -*.bb -*.bbg -*.da -*.gcov diff --git a/camel/providers/smtp/Makefile.am b/camel/providers/smtp/Makefile.am deleted file mode 100644 index 29dc3dc44d..0000000000 --- a/camel/providers/smtp/Makefile.am +++ /dev/null @@ -1,25 +0,0 @@ -## Process this file with automake to produce Makefile.in - -camel_provider_LTLIBRARIES = libcamelsmtp.la -camel_provider_DATA = libcamelsmtp.urls - -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/intl \ - -I$(top_srcdir)/camel \ - $(CAMEL_CFLAGS) \ - -DG_LOG_DOMAIN=\"camel-smtp-provider\" - -libcamelsmtp_la_SOURCES = \ - camel-smtp-provider.c \ - camel-smtp-transport.c - -noinst_HEADERS = \ - camel-smtp-transport.h - -libcamelsmtp_la_LDFLAGS = -avoid-version -module - -libcamelsmtp_la_LIBADD = \ - $(top_builddir)/libedataserver/libedataserver-${BASE_VERSION}.la - -EXTRA_DIST = libcamelsmtp.urls diff --git a/camel/providers/smtp/camel-smtp-provider.c b/camel/providers/smtp/camel-smtp-provider.c deleted file mode 100644 index bff1d847d0..0000000000 --- a/camel/providers/smtp/camel-smtp-provider.c +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-smtp-provider.c: smtp provider registration code */ -/* - * Authors: Jeffrey Stedfast <fejj@ximian.com> - * - * Copyright 2002 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "camel-smtp-transport.h" -#include "camel-provider.h" -#include "camel-session.h" -#include "camel-url.h" -#include "camel-sasl.h" -#include "camel-i18n.h" - -static CamelProvider smtp_provider = { - "smtp", - N_("SMTP"), - - N_("For delivering mail by connecting to a remote mailhub " - "using SMTP."), - - "mail", - - CAMEL_PROVIDER_IS_REMOTE | CAMEL_PROVIDER_SUPPORTS_SSL, - - CAMEL_URL_NEED_HOST | CAMEL_URL_ALLOW_AUTH | CAMEL_URL_ALLOW_USER, - - /* ... */ -}; - -void -camel_provider_module_init(void) -{ - smtp_provider.object_types[CAMEL_PROVIDER_TRANSPORT] = camel_smtp_transport_get_type (); - smtp_provider.authtypes = g_list_append (camel_sasl_authtype_list (TRUE), camel_sasl_authtype ("LOGIN")); - smtp_provider.authtypes = g_list_append (smtp_provider.authtypes, camel_sasl_authtype ("POPB4SMTP")); - smtp_provider.url_hash = camel_url_hash; - smtp_provider.url_equal = camel_url_equal; - - camel_provider_register(&smtp_provider); -} - - - diff --git a/camel/providers/smtp/camel-smtp-transport.c b/camel/providers/smtp/camel-smtp-transport.c deleted file mode 100644 index 065d79fdac..0000000000 --- a/camel/providers/smtp/camel-smtp-transport.c +++ /dev/null @@ -1,1397 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-smtp-transport.c : class for a smtp transport */ - -/* - * Authors: Jeffrey Stedfast <fejj@ximian.com> - * - * Copyright (C) 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <unistd.h> -#undef MIN -#undef MAX -#include "camel-mime-filter-crlf.h" -#include "camel-stream-filter.h" -#include "camel-smtp-transport.h" -#include "camel-mime-message.h" -#include "camel-multipart.h" -#include "camel-mime-part.h" -#include "camel-operation.h" -#include "camel-stream-buffer.h" -#include "camel-tcp-stream.h" -#include "camel-tcp-stream-raw.h" -#ifdef HAVE_SSL -#include "camel-tcp-stream-ssl.h" -#endif -#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" - -/* camel smtp transport class prototypes */ -static gboolean smtp_send_to (CamelTransport *transport, CamelMimeMessage *message, - CamelAddress *from, CamelAddress *recipients, CamelException *ex); - -/* support prototypes */ -static void smtp_construct (CamelService *service, CamelSession *session, - CamelProvider *provider, CamelURL *url, - CamelException *ex); -static gboolean smtp_connect (CamelService *service, CamelException *ex); -static gboolean smtp_disconnect (CamelService *service, gboolean clean, CamelException *ex); -static GHashTable *esmtp_get_authtypes (const unsigned char *buffer); -static GList *query_auth_types (CamelService *service, CamelException *ex); -static char *get_name (CamelService *service, gboolean brief); - -static gboolean smtp_helo (CamelSmtpTransport *transport, CamelException *ex); -static gboolean smtp_auth (CamelSmtpTransport *transport, const char *mech, CamelException *ex); -static gboolean smtp_mail (CamelSmtpTransport *transport, const char *sender, - gboolean has_8bit_parts, CamelException *ex); -static gboolean smtp_rcpt (CamelSmtpTransport *transport, const char *recipient, CamelException *ex); -static gboolean smtp_data (CamelSmtpTransport *transport, CamelMimeMessage *message, CamelException *ex); -static gboolean smtp_rset (CamelSmtpTransport *transport, CamelException *ex); -static gboolean smtp_quit (CamelSmtpTransport *transport, CamelException *ex); - -static void smtp_set_exception (CamelSmtpTransport *transport, gboolean disconnect, const char *respbuf, - const char *message, CamelException *ex); - -/* private data members */ -static CamelTransportClass *parent_class = NULL; - -static void -camel_smtp_transport_class_init (CamelSmtpTransportClass *camel_smtp_transport_class) -{ - CamelTransportClass *camel_transport_class = - CAMEL_TRANSPORT_CLASS (camel_smtp_transport_class); - CamelServiceClass *camel_service_class = - CAMEL_SERVICE_CLASS (camel_smtp_transport_class); - - parent_class = CAMEL_TRANSPORT_CLASS (camel_type_get_global_classfuncs (camel_transport_get_type ())); - - /* virtual method overload */ - camel_service_class->construct = smtp_construct; - camel_service_class->connect = smtp_connect; - camel_service_class->disconnect = smtp_disconnect; - camel_service_class->query_auth_types = query_auth_types; - camel_service_class->get_name = get_name; - - camel_transport_class->send_to = smtp_send_to; -} - -static void -camel_smtp_transport_init (gpointer object) -{ - CamelSmtpTransport *smtp = CAMEL_SMTP_TRANSPORT (object); - - smtp->flags = 0; - smtp->connected = FALSE; -} - -CamelType -camel_smtp_transport_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (CAMEL_TRANSPORT_TYPE, - "CamelSmtpTransport", - sizeof (CamelSmtpTransport), - sizeof (CamelSmtpTransportClass), - (CamelObjectClassInitFunc) camel_smtp_transport_class_init, - NULL, - (CamelObjectInitFunc) camel_smtp_transport_init, - NULL); - } - - return type; -} - -static void -smtp_construct (CamelService *service, CamelSession *session, - CamelProvider *provider, CamelURL *url, - CamelException *ex) -{ - CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex); -} - -static const char * -smtp_error_string (int error) -{ - /* SMTP error codes grabbed from rfc821 */ - switch (error) { - case 0: - /* looks like a read problem, check errno */ - if (errno) - return g_strerror (errno); - else - return _("Unknown"); - case 500: - return _("Syntax error, command unrecognized"); - case 501: - return _("Syntax error in parameters or arguments"); - case 502: - return _("Command not implemented"); - case 504: - return _("Command parameter not implemented"); - case 211: - return _("System status, or system help reply"); - case 214: - return _("Help message"); - case 220: - return _("Service ready"); - case 221: - return _("Service closing transmission channel"); - case 421: - return _("Service not available, closing transmission channel"); - case 250: - return _("Requested mail action okay, completed"); - case 251: - return _("User not local; will forward to <forward-path>"); - case 450: - return _("Requested mail action not taken: mailbox unavailable"); - case 550: - return _("Requested action not taken: mailbox unavailable"); - case 451: - return _("Requested action aborted: error in processing"); - case 551: - return _("User not local; please try <forward-path>"); - case 452: - return _("Requested action not taken: insufficient system storage"); - case 552: - return _("Requested mail action aborted: exceeded storage allocation"); - case 553: - return _("Requested action not taken: mailbox name not allowed"); - case 354: - return _("Start mail input; end with <CRLF>.<CRLF>"); - case 554: - return _("Transaction failed"); - - /* AUTH error codes: */ - case 432: - return _("A password transition is needed"); - case 534: - return _("Authentication mechanism is too weak"); - case 538: - return _("Encryption required for requested authentication mechanism"); - case 454: - return _("Temporary authentication failure"); - case 530: - return _("Authentication required"); - - default: - return _("Unknown"); - } -} - -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) -{ - CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service); - CamelStream *tcp_stream; - char *respbuf = NULL; - int ret; - - if (!CAMEL_SERVICE_CLASS (parent_class)->connect (service, ex)) - return FALSE; - - /* set some smtp transport defaults */ - transport->flags = 0; - transport->authtypes = NULL; - - 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); - } -#else - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s: %s"), - service->url->host, _("SSL unavailable")); - - return FALSE; -#endif /* HAVE_SSL */ - } else { - tcp_stream = camel_tcp_stream_raw_new (); - } - - 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)); - - camel_object_unref (tcp_stream); - - return FALSE; - } - - transport->connected = TRUE; - - /* get the localaddr - needed later by smtp_helo */ - transport->localaddr = camel_tcp_stream_get_local_address (CAMEL_TCP_STREAM (tcp_stream), &transport->localaddrlen); - - transport->ostream = tcp_stream; - transport->istream = camel_stream_buffer_new (tcp_stream, CAMEL_STREAM_BUFFER_READ); - - /* Read the greeting, note whether the server is ESMTP or not. */ - do { - /* Check for "220" */ - g_free (respbuf); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - if (!respbuf || strncmp (respbuf, "220", 3)) { - smtp_set_exception (transport, FALSE, respbuf, _("Welcome response error"), ex); - g_free (respbuf); - return FALSE; - } - } while (*(respbuf+3) == '-'); /* if we got "220-" then loop again */ - g_free (respbuf); - - /* Try sending EHLO */ - transport->flags |= CAMEL_SMTP_TRANSPORT_IS_ESMTP; - if (!smtp_helo (transport, ex)) { - if (!transport->connected) - return FALSE; - - /* Fall back to HELO */ - camel_exception_clear (ex); - transport->flags &= ~CAMEL_SMTP_TRANSPORT_IS_ESMTP; - if (!smtp_helo (transport, ex) && !transport->connected) - return FALSE; - } - - /* 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; - } - - 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; - } - - 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, - _("STARTTLS command failed: %s"), - g_strerror (errno)); - goto exception_cleanup; - } - - respbuf = NULL; - - do { - /* Check for "220 Ready for TLS" */ - g_free (respbuf); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - if (!respbuf || strncmp (respbuf, "220", 3)) { - smtp_set_exception (transport, FALSE, respbuf, _("STARTTLS command failed"), ex); - g_free (respbuf); - goto exception_cleanup; - } - } while (*(respbuf+3) == '-'); /* if we got "220-" then loop again */ - - /* Okay, now toggle SSL/TLS mode */ - if (camel_tcp_stream_ssl_enable_ssl (CAMEL_TCP_STREAM_SSL (tcp_stream)) == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to connect to SMTP server %s in secure mode: %s"), - service->url->host, g_strerror (errno)); - goto exception_cleanup; - } - - /* We are supposed to re-EHLO after a successful STARTTLS to - re-fetch any supported extensions. */ - if (!smtp_helo (transport, ex) && !transport->connected) - return FALSE; - - return TRUE; - - exception_cleanup: - - camel_object_unref (transport->istream); - transport->istream = NULL; - camel_object_unref (transport->ostream); - transport->ostream = NULL; - - transport->connected = FALSE; - - return FALSE; -} - -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; - } - - 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) - 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; -} - -static gboolean -smtp_connect (CamelService *service, CamelException *ex) -{ - CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service); - gboolean has_authtypes; - - /* We (probably) need to check popb4smtp before we connect ... */ - if (service->url->authmech && !strcmp (service->url->authmech, "POPB4SMTP")) { - int truth; - GByteArray *chal; - CamelSasl *sasl; - - sasl = camel_sasl_new ("smtp", "POPB4SMTP", service); - chal = camel_sasl_challenge (sasl, NULL, ex); - truth = camel_sasl_authenticated (sasl); - if (chal) - g_byte_array_free (chal, TRUE); - camel_object_unref (sasl); - - if (!truth) - return FALSE; - - return connect_to_server_wrapper (service, ex); - } - - if (!connect_to_server_wrapper (service, ex)) - return FALSE; - - /* check to see if AUTH is required, if so...then AUTH ourselves */ - has_authtypes = transport->authtypes ? g_hash_table_size (transport->authtypes) > 0 : FALSE; - if (service->url->authmech && (transport->flags & CAMEL_SMTP_TRANSPORT_IS_ESMTP) && has_authtypes) { - CamelSession *session = camel_service_get_session (service); - CamelServiceAuthType *authtype; - gboolean authenticated = FALSE; - char *errbuf = NULL; - - if (!g_hash_table_lookup (transport->authtypes, service->url->authmech)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("SMTP server %s does not support requested " - "authentication type %s."), - service->url->host, service->url->authmech); - camel_service_disconnect (service, TRUE, NULL); - return FALSE; - } - - authtype = camel_sasl_authtype (service->url->authmech); - if (!authtype) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("No support for authentication type %s"), - service->url->authmech); - camel_service_disconnect (service, TRUE, NULL); - return FALSE; - } - - if (!authtype->need_password) { - /* authentication mechanism doesn't need a password, - so if it fails there's nothing we can do */ - authenticated = smtp_auth (transport, authtype->authproto, ex); - if (!authenticated) { - camel_service_disconnect (service, TRUE, NULL); - return FALSE; - } - } - - /* keep trying to login until either we succeed or the user cancels */ - while (!authenticated) { - if (errbuf) { - /* We need to un-cache the password before prompting again */ - camel_session_forget_password (session, service, NULL, "password", NULL); - g_free (service->url->passwd); - service->url->passwd = NULL; - } - - if (!service->url->passwd) { - char *prompt; - - prompt = g_strdup_printf (_("%sPlease enter the SMTP password for %s on host %s"), - errbuf ? errbuf : "", service->url->user, - service->url->host); - - service->url->passwd = camel_session_get_password (session, service, NULL, - prompt, "password", CAMEL_SESSION_PASSWORD_SECRET, ex); - - g_free (prompt); - g_free (errbuf); - errbuf = NULL; - - if (!service->url->passwd) { - camel_service_disconnect (service, TRUE, NULL); - return FALSE; - } - } - - authenticated = smtp_auth (transport, authtype->authproto, ex); - if (!authenticated) { - errbuf = g_strdup_printf (_("Unable to authenticate " - "to SMTP server.\n%s\n\n"), - camel_exception_get_description (ex)); - camel_exception_clear (ex); - } - } - } - - return TRUE; -} - -static void -authtypes_free (gpointer key, gpointer value, gpointer data) -{ - g_free (value); -} - -static gboolean -smtp_disconnect (CamelService *service, gboolean clean, CamelException *ex) -{ - CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service); - - /*if (!service->connected) - * return TRUE; - */ - - if (transport->connected && clean) { - /* send the QUIT command to the SMTP server */ - smtp_quit (transport, ex); - } - - if (!CAMEL_SERVICE_CLASS (parent_class)->disconnect (service, clean, ex)) - return FALSE; - - if (transport->authtypes) { - g_hash_table_foreach (transport->authtypes, authtypes_free, NULL); - g_hash_table_destroy (transport->authtypes); - transport->authtypes = NULL; - } - - if (transport->istream) { - camel_object_unref (transport->istream); - transport->istream = NULL; - } - - if (transport->ostream) { - camel_object_unref (transport->ostream); - transport->ostream = NULL; - } - - g_free(transport->localaddr); - transport->localaddr = NULL; - - transport->connected = FALSE; - - return TRUE; -} - -static GHashTable * -esmtp_get_authtypes (const unsigned char *buffer) -{ - const unsigned char *start, *end; - GHashTable *table = NULL; - - /* advance to the first token */ - start = buffer; - while (isspace ((int) *start) || *start == '=') - start++; - - if (!*start) - return NULL; - - table = g_hash_table_new (g_str_hash, g_str_equal); - - for ( ; *start; ) { - char *type; - - /* advance to the end of the token */ - end = start; - while (*end && !isspace ((int) *end)) - end++; - - type = g_strndup (start, end - start); - g_hash_table_insert (table, type, type); - - /* advance to the next token */ - start = end; - while (isspace ((int) *start)) - start++; - } - - return table; -} - -static GList * -query_auth_types (CamelService *service, CamelException *ex) -{ - CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service); - CamelServiceAuthType *authtype; - GList *types, *t, *next; - - if (!connect_to_server_wrapper (service, ex)) - return NULL; - - types = g_list_copy (service->provider->authtypes); - for (t = types; t; t = next) { - authtype = t->data; - next = t->next; - - if (!g_hash_table_lookup (transport->authtypes, authtype->authproto)) { - types = g_list_remove_link (types, t); - g_list_free_1 (t); - } - } - - smtp_disconnect (service, TRUE, NULL); - - return types; -} - -static char * -get_name (CamelService *service, gboolean brief) -{ - if (brief) - return g_strdup_printf (_("SMTP server %s"), service->url->host); - else { - return g_strdup_printf (_("SMTP mail delivery via %s"), - service->url->host); - } -} - -static gboolean -smtp_send_to (CamelTransport *transport, CamelMimeMessage *message, - CamelAddress *from, CamelAddress *recipients, - CamelException *ex) -{ - CamelSmtpTransport *smtp_transport = CAMEL_SMTP_TRANSPORT (transport); - const CamelInternetAddress *cia; - gboolean has_8bit_parts; - const char *addr; - int i, len; - - if (!smtp_transport->connected) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_NOT_CONNECTED, - _("Cannot send message: service not connected.")); - return FALSE; - } - - if (!camel_internet_address_get (CAMEL_INTERNET_ADDRESS (from), 0, NULL, &addr)) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot send message: sender address not valid.")); - return FALSE; - } - - camel_operation_start (NULL, _("Sending message")); - - /* find out if the message has 8bit mime parts */ - has_8bit_parts = camel_mime_message_has_8bit_parts (message); - - /* rfc1652 (8BITMIME) requires that you notify the ESMTP daemon that - you'll be sending an 8bit mime message at "MAIL FROM:" time. */ - if (!smtp_mail (smtp_transport, addr, has_8bit_parts, ex)) { - camel_operation_end (NULL); - return FALSE; - } - - len = camel_address_length (recipients); - if (len == 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot send message: no recipients defined.")); - camel_operation_end (NULL); - return FALSE; - } - - cia = CAMEL_INTERNET_ADDRESS (recipients); - for (i = 0; i < len; i++) { - char *enc; - - if (!camel_internet_address_get (cia, i, NULL, &addr)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot send message: one or more invalid recipients")); - camel_operation_end (NULL); - return FALSE; - } - - enc = camel_internet_address_encode_address(NULL, NULL, addr); - if (!smtp_rcpt (smtp_transport, enc, ex)) { - g_free(enc); - camel_operation_end (NULL); - return FALSE; - } - g_free(enc); - } - - if (!smtp_data (smtp_transport, message, ex)) { - camel_operation_end (NULL); - return FALSE; - } - - /* reset the service for our next transfer session */ - if (!smtp_rset (smtp_transport, ex)) - camel_exception_clear (ex); - - camel_operation_end (NULL); - - return TRUE; -} - -static const char * -smtp_next_token (const char *buf) -{ - const unsigned char *token; - - token = (const unsigned char *) buf; - while (*token && !isspace ((int) *token)) - token++; - - while (*token && isspace ((int) *token)) - token++; - - return (const char *) token; -} - -#define HEXVAL(c) (isdigit (c) ? (c) - '0' : (c) - 'A' + 10) - -/** - * example (rfc2034): - * 5.1.1 Mailbox "nosuchuser" does not exist - * - * The human-readable status code is what we want. Since this text - * could possibly be encoded, we must decode it. - * - * "xtext" is formally defined as follows: - * - * xtext = *( xchar / hexchar / linear-white-space / comment ) - * - * xchar = any ASCII CHAR between "!" (33) and "~" (126) inclusive, - * except for "+", "\" and "(". - * - * "hexchar"s are intended to encode octets that cannot be represented - * as plain text, either because they are reserved, or because they are - * non-printable. However, any octet value may be represented by a - * "hexchar". - * - * hexchar = ASCII "+" immediately followed by two upper case - * hexadecimal digits - **/ -static char * -smtp_decode_status_code (const char *in, size_t len) -{ - unsigned char *inptr, *outptr; - const unsigned char *inend; - char *outbuf; - - outptr = outbuf = g_malloc (len + 1); - - inptr = (unsigned char *) in; - inend = inptr + len; - while (inptr < inend) { - if (*inptr == '+') { - if (isxdigit (inptr[1]) && isxdigit (inptr[2])) { - *outptr++ = HEXVAL (inptr[1]) * 16 + HEXVAL (inptr[2]); - inptr += 3; - } else - *outptr++ = *inptr++; - } else - *outptr++ = *inptr++; - } - - *outptr = '\0'; - - return outbuf; -} - -static void -smtp_set_exception (CamelSmtpTransport *transport, gboolean disconnect, const char *respbuf, const char *message, CamelException *ex) -{ - const char *token, *rbuf = respbuf; - char *buffer = NULL; - GString *string; - int error; - - if (!respbuf || !(transport->flags & CAMEL_SMTP_TRANSPORT_ENHANCEDSTATUSCODES)) { - fake_status_code: - error = respbuf ? atoi (respbuf) : 0; - camel_exception_setv (ex, error == 0 && errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM, - "%s: %s", message, smtp_error_string (error)); - } else { - string = g_string_new (""); - do { - token = smtp_next_token (rbuf + 4); - if (*token == '\0') { - g_free (buffer); - g_string_free (string, TRUE); - goto fake_status_code; - } - - g_string_append (string, token); - if (*(rbuf + 3) == '-') { - g_free (buffer); - buffer = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - g_string_append_c (string, '\n'); - } else { - g_free (buffer); - buffer = NULL; - } - - rbuf = buffer; - } while (rbuf); - - buffer = smtp_decode_status_code (string->str, string->len); - g_string_free (string, TRUE); - if (!buffer) - goto fake_status_code; - - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - "%s: %s", message, buffer); - - g_free (buffer); - } - - if (!respbuf) { - /* we got disconnected */ - if (disconnect) - camel_service_disconnect ((CamelService *) transport, FALSE, NULL); - else - transport->connected = FALSE; - } -} - -static gboolean -smtp_helo (CamelSmtpTransport *transport, CamelException *ex) -{ - /* say hello to the server */ - char *name = NULL, *cmdbuf = NULL, *respbuf = NULL; - const char *token, *numeric = NULL; - - /* these are flags that we set, so unset them in case we - are being called a second time (ie, after a STARTTLS) */ - transport->flags &= ~(CAMEL_SMTP_TRANSPORT_8BITMIME | - CAMEL_SMTP_TRANSPORT_ENHANCEDSTATUSCODES | - CAMEL_SMTP_TRANSPORT_STARTTLS); - - if (transport->authtypes) { - g_hash_table_foreach (transport->authtypes, authtypes_free, NULL); - g_hash_table_destroy (transport->authtypes); - transport->authtypes = NULL; - } - - camel_operation_start_transient (NULL, _("SMTP Greeting")); - - /* force name resolution first, fallback to numerical, we need to know when it falls back */ - if (camel_getnameinfo(transport->localaddr, transport->localaddrlen, &name, NULL, NI_NAMEREQD, NULL) != 0) { - if (camel_getnameinfo(transport->localaddr, transport->localaddrlen, &name, NULL, NI_NUMERICHOST, NULL) != 0) - name = g_strdup("localhost.localdomain"); - else { - if (transport->localaddr->sa_family == AF_INET6) - numeric = "IPv6:"; - else - numeric = ""; - } - } - - /* hiya server! how are you today? */ - token = (transport->flags & CAMEL_SMTP_TRANSPORT_IS_ESMTP) ? "EHLO" : "HELO"; - if (numeric) - cmdbuf = g_strdup_printf("%s [%s%s]\r\n", token, numeric, name); - else - cmdbuf = g_strdup_printf("%s %s\r\n", token, name); - g_free (name); - - d(fprintf (stderr, "sending : %s", cmdbuf)); - if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) { - g_free (cmdbuf); - camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM, - _("HELO command failed: %s"), g_strerror (errno)); - camel_operation_end (NULL); - - camel_service_disconnect ((CamelService *) transport, FALSE, NULL); - - return FALSE; - } - g_free (cmdbuf); - - do { - /* Check for "250" */ - g_free (respbuf); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - if (!respbuf || strncmp (respbuf, "250", 3)) { - smtp_set_exception (transport, FALSE, respbuf, _("HELO command failed"), ex); - camel_operation_end (NULL); - g_free (respbuf); - - return FALSE; - } - - token = respbuf + 4; - - if (transport->flags & CAMEL_SMTP_TRANSPORT_IS_ESMTP) { - if (!strncmp (token, "8BITMIME", 8)) { - d(fprintf (stderr, "This server supports 8bit MIME\n")); - transport->flags |= CAMEL_SMTP_TRANSPORT_8BITMIME; - } else if (!strncmp (token, "ENHANCEDSTATUSCODES", 19)) { - d(fprintf (stderr, "This server supports enhanced status codes\n")); - transport->flags |= CAMEL_SMTP_TRANSPORT_ENHANCEDSTATUSCODES; - } else if (!strncmp (token, "STARTTLS", 8)) { - d(fprintf (stderr, "This server supports STARTTLS\n")); - transport->flags |= CAMEL_SMTP_TRANSPORT_STARTTLS; - } else if (!strncmp (token, "AUTH", 4)) { - if (!transport->authtypes || transport->flags & CAMEL_SMTP_TRANSPORT_AUTH_EQUAL) { - /* Don't bother parsing any authtypes if we already have a list. - * Some servers will list AUTH twice, once the standard way and - * once the way Microsoft Outlook requires them to be: - * - * 250-AUTH LOGIN PLAIN DIGEST-MD5 CRAM-MD5 - * 250-AUTH=LOGIN PLAIN DIGEST-MD5 CRAM-MD5 - * - * Since they can come in any order, parse each list that we get - * until we parse an authtype list that does not use the AUTH= - * format. We want to let the standard way have priority over the - * broken way. - **/ - - if (token[4] == '=') - transport->flags |= CAMEL_SMTP_TRANSPORT_AUTH_EQUAL; - else - transport->flags &= ~CAMEL_SMTP_TRANSPORT_AUTH_EQUAL; - - /* parse for supported AUTH types */ - token += 5; - - if (transport->authtypes) { - g_hash_table_foreach (transport->authtypes, authtypes_free, NULL); - g_hash_table_destroy (transport->authtypes); - } - - transport->authtypes = esmtp_get_authtypes (token); - } - } - } - } while (*(respbuf+3) == '-'); /* if we got "250-" then loop again */ - g_free (respbuf); - - camel_operation_end (NULL); - - return TRUE; -} - -static gboolean -smtp_auth (CamelSmtpTransport *transport, const char *mech, CamelException *ex) -{ - char *cmdbuf, *respbuf = NULL, *challenge; - gboolean auth_challenge = FALSE; - CamelSasl *sasl = NULL; - - camel_operation_start_transient (NULL, _("SMTP Authentication")); - - sasl = camel_sasl_new ("smtp", mech, CAMEL_SERVICE (transport)); - if (!sasl) { - camel_operation_end (NULL); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Error creating SASL authentication object.")); - return FALSE; - } - - challenge = camel_sasl_challenge_base64 (sasl, NULL, ex); - if (challenge) { - auth_challenge = TRUE; - cmdbuf = g_strdup_printf ("AUTH %s %s\r\n", mech, challenge); - g_free (challenge); - } else { - cmdbuf = g_strdup_printf ("AUTH %s\r\n", mech); - } - - d(fprintf (stderr, "sending : %s", cmdbuf)); - if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) { - g_free (cmdbuf); - camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM, - _("AUTH command failed: %s"), g_strerror (errno)); - goto lose; - } - g_free (cmdbuf); - - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - while (!camel_sasl_authenticated (sasl)) { - if (!respbuf) { - camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM, - _("AUTH command failed: %s"), g_strerror (errno)); - goto lose; - } - - /* the server challenge/response should follow a 334 code */ - if (strncmp (respbuf, "334", 3) != 0) { - smtp_set_exception (transport, FALSE, respbuf, _("AUTH command failed"), ex); - g_free (respbuf); - goto lose; - } - - if (FALSE) { - broken_smtp_server: - d(fprintf (stderr, "Your SMTP server's implementation of the %s SASL\n" - "authentication mechanism is broken. Please report this to the\n" - "appropriate vendor and suggest that they re-read rfc2554 again\n" - "for the first time (specifically Section 4).\n", - mech)); - } - - /* eat whtspc */ - for (challenge = respbuf + 4; isspace (*challenge); challenge++); - - challenge = camel_sasl_challenge_base64 (sasl, challenge, ex); - g_free (respbuf); - if (challenge == NULL) - goto break_and_lose; - - /* send our challenge */ - cmdbuf = g_strdup_printf ("%s\r\n", challenge); - g_free (challenge); - d(fprintf (stderr, "sending : %s", cmdbuf)); - if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) { - g_free (cmdbuf); - goto lose; - } - g_free (cmdbuf); - - /* get the server's response */ - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - } - - /* check that the server says we are authenticated */ - if (!respbuf || strncmp (respbuf, "235", 3)) { - if (respbuf && auth_challenge && !strncmp (respbuf, "334", 3)) { - /* broken server, but lets try and work around it anyway... */ - goto broken_smtp_server; - } - g_free (respbuf); - goto lose; - } - - camel_object_unref (sasl); - camel_operation_end (NULL); - - return TRUE; - - break_and_lose: - /* Get the server out of "waiting for continuation data" mode. */ - d(fprintf (stderr, "sending : *\n")); - camel_stream_write (transport->ostream, "*\r\n", 3); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - lose: - if (!camel_exception_is_set (ex)) { - camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE, - _("Bad authentication response from server.\n")); - } - - camel_object_unref (sasl); - camel_operation_end (NULL); - - return FALSE; -} - -static gboolean -smtp_mail (CamelSmtpTransport *transport, const char *sender, gboolean has_8bit_parts, CamelException *ex) -{ - /* we gotta tell the smtp server who we are. (our email addy) */ - char *cmdbuf, *respbuf = NULL; - - if (transport->flags & CAMEL_SMTP_TRANSPORT_8BITMIME && has_8bit_parts) - cmdbuf = g_strdup_printf ("MAIL FROM:<%s> BODY=8BITMIME\r\n", sender); - else - cmdbuf = g_strdup_printf ("MAIL FROM:<%s>\r\n", sender); - - d(fprintf (stderr, "sending : %s", cmdbuf)); - - if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) { - g_free (cmdbuf); - camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM, - _("MAIL FROM command failed: %s: mail not sent"), - g_strerror (errno)); - - camel_service_disconnect ((CamelService *) transport, FALSE, NULL); - - return FALSE; - } - g_free (cmdbuf); - - do { - /* Check for "250 Sender OK..." */ - g_free (respbuf); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - if (!respbuf || strncmp (respbuf, "250", 3)) { - smtp_set_exception (transport, TRUE, respbuf, _("MAIL FROM command failed"), ex); - g_free (respbuf); - return FALSE; - } - } while (*(respbuf+3) == '-'); /* if we got "250-" then loop again */ - g_free (respbuf); - - return TRUE; -} - -static gboolean -smtp_rcpt (CamelSmtpTransport *transport, const char *recipient, CamelException *ex) -{ - /* we gotta tell the smtp server who we are going to be sending - * our email to */ - char *cmdbuf, *respbuf = NULL; - - cmdbuf = g_strdup_printf ("RCPT TO:<%s>\r\n", recipient); - - d(fprintf (stderr, "sending : %s", cmdbuf)); - - if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) { - g_free (cmdbuf); - camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM, - _("RCPT TO command failed: %s: mail not sent"), - g_strerror (errno)); - - camel_service_disconnect ((CamelService *) transport, FALSE, NULL); - - return FALSE; - } - g_free (cmdbuf); - - do { - /* Check for "250 Recipient OK..." */ - g_free (respbuf); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - if (!respbuf || strncmp (respbuf, "250", 3)) { - char *message; - - message = g_strdup_printf (_("RCPT TO <%s> failed"), recipient); - smtp_set_exception (transport, TRUE, respbuf, message, ex); - g_free (message); - g_free (respbuf); - return FALSE; - } - } while (*(respbuf+3) == '-'); /* if we got "250-" then loop again */ - g_free (respbuf); - - return TRUE; -} - -static gboolean -smtp_data (CamelSmtpTransport *transport, CamelMimeMessage *message, CamelException *ex) -{ - CamelBestencEncoding enctype = CAMEL_BESTENC_8BIT; - struct _camel_header_raw *header, *savedbcc, *n, *tail; - char *cmdbuf, *respbuf = NULL; - CamelStreamFilter *filtered_stream; - CamelMimeFilter *crlffilter; - int ret; - - /* If the server doesn't support 8BITMIME, set our required encoding to be 7bit */ - if (!(transport->flags & CAMEL_SMTP_TRANSPORT_8BITMIME)) - enctype = CAMEL_BESTENC_7BIT; - - /* FIXME: should we get the best charset too?? */ - /* Changes the encoding of all mime parts to fit within our required - encoding type and also force any text parts with long lines (longer - than 998 octets) to wrap by QP or base64 encoding them. */ - camel_mime_message_set_best_encoding (message, CAMEL_BESTENC_GET_ENCODING, enctype); - - cmdbuf = g_strdup ("DATA\r\n"); - - d(fprintf (stderr, "sending : %s", cmdbuf)); - - if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) { - g_free (cmdbuf); - camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM, - _("DATA command failed: %s: mail not sent"), - g_strerror (errno)); - - camel_service_disconnect ((CamelService *) transport, FALSE, NULL); - - return FALSE; - } - g_free (cmdbuf); - - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - if (!respbuf || strncmp (respbuf, "354", 3)) { - /* we should have gotten instructions on how to use the DATA command: - * 354 Enter mail, end with "." on a line by itself - */ - smtp_set_exception (transport, TRUE, respbuf, _("DATA command failed"), ex); - g_free (respbuf); - return FALSE; - } - - g_free (respbuf); - respbuf = NULL; - - /* setup stream filtering */ - crlffilter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, CAMEL_MIME_FILTER_CRLF_MODE_CRLF_DOTS); - filtered_stream = camel_stream_filter_new_with_stream (transport->ostream); - camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (crlffilter)); - camel_object_unref (crlffilter); - - /* unlink the bcc headers */ - savedbcc = NULL; - tail = (struct _camel_header_raw *) &savedbcc; - - header = (struct _camel_header_raw *) &CAMEL_MIME_PART (message)->headers; - n = header->next; - while (n != NULL) { - if (!g_ascii_strcasecmp (n->name, "Bcc")) { - header->next = n->next; - tail->next = n; - n->next = NULL; - tail = n; - } else { - header = n; - } - - n = header->next; - } - - /* write the message */ - ret = camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), CAMEL_STREAM (filtered_stream)); - - /* restore the bcc headers */ - header->next = savedbcc; - - if (ret == -1) { - camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM, - _("DATA command failed: %s: mail not sent"), - g_strerror (errno)); - - camel_object_unref (filtered_stream); - - camel_service_disconnect ((CamelService *) transport, FALSE, NULL); - - return FALSE; - } - - camel_stream_flush (CAMEL_STREAM (filtered_stream)); - camel_object_unref (filtered_stream); - - /* terminate the message body */ - - d(fprintf (stderr, "sending : \\r\\n.\\r\\n\n")); - - if (camel_stream_write (transport->ostream, "\r\n.\r\n", 5) == -1) { - camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM, - _("DATA command failed: %s: mail not sent"), - g_strerror (errno)); - - camel_service_disconnect ((CamelService *) transport, FALSE, NULL); - - return FALSE; - } - - do { - /* Check for "250 Sender OK..." */ - g_free (respbuf); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - if (!respbuf || strncmp (respbuf, "250", 3)) { - smtp_set_exception (transport, TRUE, respbuf, _("DATA command failed"), ex); - g_free (respbuf); - return FALSE; - } - } while (*(respbuf+3) == '-'); /* if we got "250-" then loop again */ - g_free (respbuf); - - return TRUE; -} - -static gboolean -smtp_rset (CamelSmtpTransport *transport, CamelException *ex) -{ - /* we are going to reset the smtp server (just to be nice) */ - char *cmdbuf, *respbuf = NULL; - - cmdbuf = g_strdup ("RSET\r\n"); - - d(fprintf (stderr, "sending : %s", cmdbuf)); - - if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) { - g_free (cmdbuf); - camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM, - _("RSET command failed: %s"), g_strerror (errno)); - - camel_service_disconnect ((CamelService *) transport, FALSE, NULL); - - return FALSE; - } - g_free (cmdbuf); - - do { - /* Check for "250" */ - g_free (respbuf); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - if (!respbuf || strncmp (respbuf, "250", 3)) { - smtp_set_exception (transport, TRUE, respbuf, _("RSET command failed"), ex); - g_free (respbuf); - return FALSE; - } - } while (*(respbuf+3) == '-'); /* if we got "250-" then loop again */ - g_free (respbuf); - - return TRUE; -} - -static gboolean -smtp_quit (CamelSmtpTransport *transport, CamelException *ex) -{ - /* we are going to reset the smtp server (just to be nice) */ - char *cmdbuf, *respbuf = NULL; - - cmdbuf = g_strdup ("QUIT\r\n"); - - d(fprintf (stderr, "sending : %s", cmdbuf)); - - if (camel_stream_write (transport->ostream, cmdbuf, strlen (cmdbuf)) == -1) { - g_free (cmdbuf); - camel_exception_setv (ex, errno == EINTR ? CAMEL_EXCEPTION_USER_CANCEL : CAMEL_EXCEPTION_SYSTEM, - _("QUIT command failed: %s"), g_strerror (errno)); - - return FALSE; - } - g_free (cmdbuf); - - do { - /* Check for "221" */ - g_free (respbuf); - respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (transport->istream)); - - d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); - - if (!respbuf || strncmp (respbuf, "221", 3)) { - smtp_set_exception (transport, FALSE, respbuf, _("QUIT command failed"), ex); - g_free (respbuf); - return FALSE; - } - } while (*(respbuf+3) == '-'); /* if we got "221-" then loop again */ - g_free (respbuf); - - return TRUE; -} diff --git a/camel/providers/smtp/camel-smtp-transport.h b/camel/providers/smtp/camel-smtp-transport.h deleted file mode 100644 index 7b5ad88f12..0000000000 --- a/camel/providers/smtp/camel-smtp-transport.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-smtp-transport.h : class for an smtp transfer */ - -/* - * Authors: - * Jeffrey Stedfast <fejj@stampede.org> - * - * Copyright (C) 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifndef CAMEL_SMTP_TRANSPORT_H -#define CAMEL_SMTP_TRANSPORT_H 1 - -#ifdef __cplusplus -extern "C" { -#pragma } -#endif /* __cplusplus */ - -#include "camel-transport.h" -#include "camel-tcp-stream.h" - -#define CAMEL_SMTP_TRANSPORT_TYPE (camel_smtp_transport_get_type ()) -#define CAMEL_SMTP_TRANSPORT(obj) (CAMEL_CHECK_CAST((obj), CAMEL_SMTP_TRANSPORT_TYPE, CamelSmtpTransport)) -#define CAMEL_SMTP_TRANSPORT_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_SMTP_TRANSPORT_TYPE, CamelSmtpTransportClass)) -#define CAMEL_IS_SMTP_TRANSPORT(o) (CAMEL_CHECK_TYPE((o), CAMEL_SMTP_TRANSPORT_TYPE)) - -#define CAMEL_SMTP_TRANSPORT_IS_ESMTP (1 << 0) -#define CAMEL_SMTP_TRANSPORT_8BITMIME (1 << 1) -#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= */ - -typedef struct { - CamelTransport parent_object; - - CamelStream *istream, *ostream; - - guint32 flags; - - gboolean connected; - struct sockaddr *localaddr; - socklen_t localaddrlen; - - GHashTable *authtypes; -} CamelSmtpTransport; - -typedef struct { - CamelTransportClass parent_class; - -} CamelSmtpTransportClass; - -/* Standard Camel function */ -CamelType camel_smtp_transport_get_type (void); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_SMTP_TRANSPORT_H */ diff --git a/camel/providers/smtp/libcamelsmtp.urls b/camel/providers/smtp/libcamelsmtp.urls deleted file mode 100644 index ec2fc0fc16..0000000000 --- a/camel/providers/smtp/libcamelsmtp.urls +++ /dev/null @@ -1 +0,0 @@ -smtp |