--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- *
+ *
+ * Author: 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 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 <stdlib.h>
+#include <string.h>
+
+#include "camel-debug.h"
+
+int camel_verbose_debug;
+
+static GHashTable *debug_table = NULL;
+
+/**
+ * camel_debug_init:
+ * @void:
+ *
+ * Init camel debug. Maintain legacy CAMEL_VERBOSE_DEBUG as well as the
+ * new CAMEL_DEBUG based environment variable interfaces.
+ *
+ * CAMEL_VERBOSE_DEBUG is set to a number to turn debug on.
+ *
+ * CAMEL_DEBUG is set to a comma separated list of modules to debug.
+ * The modules can contain module-specific specifiers after a ':', or
+ * just act as a wildcard for the module or even specifier. e.g. 'imap'
+ * for imap debug, or 'imap:folder' for imap folder debug. Additionaly,
+ * ':folder' can be used for a wildcard for any folder operations.
+ **/
+void camel_debug_init(void)
+{
+ char *d;
+
+ d = getenv("CAMEL_VERBOSE_DEBUG");
+ if (d)
+ camel_verbose_debug = atoi(d);
+
+ d = g_strdup(getenv("CAMEL_DEBUG"));
+ if (d) {
+ char *p;
+
+ debug_table = g_hash_table_new(g_str_hash, g_str_equal);
+ p = d;
+ while (*p) {
+ while (*p && *p != ',')
+ p++;
+ if (*p)
+ *p++ = 0;
+ g_hash_table_insert(debug_table, d, d);
+ d = p;
+ }
+
+ if (g_hash_table_lookup(debug_table, "all"))
+ camel_verbose_debug = 1;
+ }
+}
+
+/**
+ * camel_debug:
+ * @mode:
+ *
+ * Check to see if a debug mode is activated. @mode takes one of two forms,
+ * a fully qualified 'module:target', or a wildcard 'module' name. It
+ * returns a boolean to indicate if the module or module and target is
+ * currently activated for debug output.
+ *
+ * Return value:
+ **/
+gboolean camel_debug(const char *mode)
+{
+ if (camel_verbose_debug)
+ return TRUE;
+
+ if (debug_table) {
+ char *colon;
+ char *fallback;
+
+ if (g_hash_table_lookup(debug_table, mode))
+ return TRUE;
+
+ /* Check for fully qualified debug */
+ colon = strchr(mode, ':');
+ if (colon) {
+ fallback = g_alloca(strlen(mode)+1);
+ strcpy(fallback, mode);
+ colon = (colon-mode) + fallback;
+ /* Now check 'module[:*]' */
+ *colon = 0;
+ if (g_hash_table_lookup(debug_table, fallback))
+ return TRUE;
+ /* Now check ':subsystem' */
+ *colon = ':';
+ if (g_hash_table_lookup(debug_table, colon))
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- *
+ *
+ * Author: 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 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_DEBUG_H
+#define CAMEL_DEBUG_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus }*/
+
+#include <glib.h>
+
+/* This is how the basic debug checking strings should be done */
+#define CAMEL_DEBUG_IMAP "imap"
+#define CAMEL_DEBUG_IMAP_FOLDER "imap:folder"
+
+void camel_debug_init(void);
+gboolean camel_debug(const char *mode);
+
+/* This interface is deprecated */
+extern int camel_verbose_debug;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* CAMEL_DEBUG_H */
CamelMessageInfo *mi;
CamelMimeMessage *msg;
CamelStream *stream = NULL;
-
+ int retry;
+
/* If the server doesn't support IMAP4rev1, or we already have
* the whole thing cached, fetch it in one piece.
*/
_("Cannot get message: %s\n %s"), uid, _("No such message"));
return NULL;
}
-
- /* If the message is small, fetch it in one piece. */
- if (mi->size < IMAP_SMALL_BODY_SIZE) {
- camel_folder_summary_info_free (folder->summary, mi);
- return get_message_simple (imap_folder, uid, NULL, ex);
- }
-
- /* 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.)
- */
- if (content_info_incomplete (mi->content)) {
- 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"));
- return NULL;
- }
-
- response = camel_imap_command (store, folder, ex,
- "UID FETCH %s BODY", uid);
- if (!response) {
- camel_folder_summary_info_free (folder->summary, mi);
- return NULL;
- }
-
- 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;
+
+ /* 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 {
+ msg = NULL;
+ 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, fetch it in one piece. */
+ if (mi->size < IMAP_SMALL_BODY_SIZE) {
+ msg = get_message_simple (imap_folder, uid, NULL, ex);
+ } else if (content_info_incomplete (mi->content)) {
+
+ /* For larger messages, fetch the structure and build a message
+ * with offline parts. (We check mi->content->type rather than
+ * mi->content because camel_folder_summary_info_new always creates
+ * 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;
}
- }
- if (body)
- imap_parse_body ((const char **) &body, folder, mi->content);
+ 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 (fetch_data)
- g_datalist_clear (&fetch_data);
+ if (body)
+ imap_parse_body ((const char **) &body, folder, mi->content);
- camel_imap_response_free (store, response);
+ if (fetch_data)
+ g_datalist_clear (&fetch_data);
- if (content_info_incomplete (mi->content)) {
- /* 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.
- */
- camel_folder_summary_info_free (folder->summary, mi);
- return get_message_simple (imap_folder, uid, NULL, ex);
+ camel_imap_response_free (store, response);
+
+ /* 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->content))
+ msg = get_message_simple (imap_folder, uid, NULL, ex);
+ else
+ msg = get_message (imap_folder, uid, "", mi->content, ex);
+ }
}
- }
-
- msg = get_message (imap_folder, uid, "", mi->content, ex);
+ } while (msg == NULL
+ && retry < 2
+ && camel_exception_get_id(ex) == CAMEL_EXCEPTION_SERVICE_UNAVAILABLE);
+
/* FIXME, this shouldn't be done this way. */
- camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Source",
- store->base_url);
+ if (msg)
+ camel_medium_set_header (CAMEL_MEDIUM (msg), "X-Evolution-Source", store->base_url);
+fail:
camel_folder_summary_info_free (folder->summary, mi);
return msg;