aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog8
-rw-r--r--camel/providers/imap/camel-imap-folder.c53
-rw-r--r--camel/providers/imap/camel-imap-store.c177
-rw-r--r--camel/providers/imap/camel-imap-store.h12
4 files changed, 217 insertions, 33 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 8576606d12..e4ba89390a 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,11 @@
+2000-08-11 Jeffrey Stedfast <fejj@helixcode.com>
+
+ * providers/imap/camel-imap-store.c
+ (camel_imap_command_preliminary): New convenience function for
+ multi-transactional commands (opening request)
+ (camel_imap_command_continuation): New convenience function for
+ multi-transactional commands (followup data)
+
2000-08-11 Christopher James Lahey <clahey@helixcode.com>
* providers/mh/camel-mh-folder.c: Fixed a warning.
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index a752bee56f..894b7a0865 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -141,12 +141,12 @@ camel_imap_folder_init (gpointer object, gpointer klass)
{
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object);
CamelFolder *folder = CAMEL_FOLDER (object);
-
+
folder->can_hold_messages = TRUE;
folder->can_hold_folders = TRUE;
folder->has_summary_capability = TRUE;
- folder->has_search_capability = FALSE; /* FIXME: this should be TRUE but it's not yet implemented */
-
+ folder->has_search_capability = TRUE;
+
imap_folder->summary = NULL;
imap_folder->summary_hash = NULL;
imap_folder->lsub = NULL;
@@ -213,7 +213,7 @@ imap_summary_free (GPtrArray **summary)
g_free (info);
info = NULL;
}
-
+
g_ptr_array_free (array, TRUE);
*summary = NULL;
}
@@ -238,10 +238,10 @@ imap_finalize (CamelObject *object)
gint max, i;
imap_folder_summary_free (imap_folder);
-
+
if (imap_folder->lsub) {
max = imap_folder->lsub->len;
-
+
for (i = 0; i < max; i++) {
g_free (imap_folder->lsub->pdata[i]);
imap_folder->lsub->pdata[i] = NULL;
@@ -261,13 +261,13 @@ imap_init (CamelFolder *folder, CamelStore *parent_store, CamelFolder *parent_fo
parent_class->init (folder, parent_store, parent_folder, name, separator, path_begins_with_sep, ex);
if (camel_exception_get_id (ex))
return;
-
+
/* we assume that the parent init
method checks for the existance of @folder */
folder->can_hold_messages = TRUE;
folder->can_hold_folders = TRUE;
folder->has_summary_capability = TRUE;
- folder->has_search_capability = TRUE; /* FIXME: this should be TRUE 'cept it ain't implemented yet */
+ folder->has_search_capability = TRUE;
/* some IMAP daemons support user-flags *
* I would not, however, rely on this feature as *
@@ -301,7 +301,7 @@ imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
max = imap_folder->summary->len;
for (i = 0; i < max; i++) {
CamelMessageInfo *info;
-
+
info = (CamelMessageInfo *) g_ptr_array_index (imap_folder->summary, i);
if (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) {
char *flags;
@@ -347,9 +347,9 @@ imap_expunge (CamelFolder *folder, CamelException *ex)
CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder);
gchar *node, *result;
gint i, status, recent = -1;
-
+
g_return_if_fail (folder != NULL);
-
+
imap_sync (folder, FALSE, ex);
status = camel_imap_command_extended (CAMEL_IMAP_STORE (folder->parent_store), folder,
@@ -365,7 +365,7 @@ imap_expunge (CamelFolder *folder, CamelException *ex)
g_free (result);
return;
}
-
+
/* determine which messages were successfully expunged */
node = result;
for (i = 0; node; i++) {
@@ -438,8 +438,6 @@ imap_expunge (CamelFolder *folder, CamelException *ex)
}
g_free (result);
-
- /*imap_folder_summary_free (imap_folder);*/
camel_imap_folder_changed (folder, recent, ex);
}
@@ -527,13 +525,13 @@ imap_get_unread_message_count (CamelFolder *folder)
CamelMessageInfo *info;
GPtrArray *infolist;
gint i, count = 0;
-
+
g_return_val_if_fail (folder != NULL, 0);
-
+
/* If we don't have a message count, return 0 */
if (!imap_folder->summary)
return 0;
-
+
infolist = imap_get_summary (folder);
for (i = 0; i < infolist->len; i++) {
@@ -541,7 +539,7 @@ imap_get_unread_message_count (CamelFolder *folder)
if (!(info->flags & CAMEL_MESSAGE_SEEN))
count++;
}
-
+
return count;
}
@@ -553,21 +551,12 @@ imap_append_message (CamelFolder *folder, CamelMimeMessage *message, const Camel
CamelStreamMem *mem;
gchar *result, *folder_path, *dir_sep, *flagstr = NULL;
gint status;
-
+
g_return_if_fail (folder != NULL);
g_return_if_fail (message != NULL);
-
+
/* write the message to a CamelStreamMem so we can get it's size */
- mem = CAMEL_STREAM_MEM (camel_stream_mem_new ());
- if (camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), CAMEL_STREAM (mem)) == -1) {
- CamelService *service = CAMEL_SERVICE (folder->parent_store);
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- "Could not APPEND message to IMAP server %s: %s.",
- service->url->host,
- g_strerror (errno));
-
- return;
- }
+ mem = CAMEL_STREAM_MEM (CAMEL_DATA_WRAPPER (message)->stream);
mem->buffer = g_byte_array_append (mem->buffer, g_strdup ("\r\n"), 3);
@@ -1516,7 +1505,7 @@ imap_set_message_flags (CamelFolder *folder, const char *uid, guint32 flags, gui
info->flags = (info->flags & ~flags) | (set & flags) | CAMEL_MESSAGE_FOLDER_FLAGGED;
/*gtk_signal_emit_by_name (GTK_OBJECT (folder), "message_changed", uid);*/
- camel_object_trigger_event (CAMEL_OBJECT (folder), "message_changed", (char *) uid);
+ camel_object_trigger_event (CAMEL_OBJECT (folder), "message_changed", (gpointer *) uid);
}
static gboolean
@@ -1529,7 +1518,7 @@ static void
imap_set_message_user_flag (CamelFolder *folder, const char *uid, const char *name, gboolean value)
{
/*gtk_signal_emit_by_name (GTK_OBJECT (folder), "message_changed", uid);*/
- camel_object_trigger_event (CAMEL_OBJECT (folder), "message_changed", (char *) uid);
+ camel_object_trigger_event (CAMEL_OBJECT (folder), "message_changed", (gpointer *) uid);
}
void
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index 374107250d..6eb03e9db4 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -968,3 +968,180 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char **
return status;
}
+
+/**
+ * camel_imap_command_preliminary: Send a preliminary command to the
+ * IMAP server.
+ * @store: the IMAP store
+ * @ret: a pointer to return the full server response in
+ * @cmdid: a pointer to return the command identifier (for use in
+ * camel_imap_command_continuation)
+ * @fmt: a printf-style format string, followed by arguments
+ *
+ * This camel method sends a preliminary IMAP command specified by
+ * @fmt and the following arguments to the IMAP store specified by
+ * @store. This function is meant for use with multi-transactional
+ * IMAP communications like Kerberos authentication and APPEND.
+ *
+ * If the caller passed a non-NULL pointer for @ret,
+ * camel_imap_command_preliminary will set it to point to a buffer
+ * containing the rest of the response from the IMAP server. The
+ * caller function is responsible for freeing @ret.
+ *
+ * Return value: one of CAMEL_IMAP_PLUS or CAMEL_IMAP_FAIL
+ *
+ * Note: on success (CAMEL_IMAP_PLUS), you will need to follow up with
+ * a camel_imap_command_continuation call.
+ **/
+gint
+camel_imap_command_preliminary (CamelImapStore *store, char **ret, char **cmdid, char *fmt, ...)
+{
+ gchar *cmdbuf, *respbuf;
+ gint status = CAMEL_IMAP_OK;
+ va_list app;
+
+ /* Create the command */
+ *cmdid = g_strdup_printf ("A%.5d", store->command++);
+ va_start (app, fmt);
+ cmdbuf = g_strdup_vprintf (fmt, app);
+ va_end (app);
+
+ d(fprintf (stderr, "sending : %s %s\r\n", *cmdid, cmdbuf));
+
+ if (camel_stream_printf (store->ostream, "%s %s\r\n", *cmdid, cmdbuf) == -1) {
+ g_free (cmdbuf);
+
+ if (ret)
+ *ret = g_strdup (strerror (errno));
+
+ return CAMEL_IMAP_FAIL;
+ }
+ g_free (cmdbuf);
+
+ respbuf = camel_stream_buffer_read_line (CAMEL_STREAM_BUFFER (store->istream));
+
+ if (respbuf) {
+ switch (*respbuf) {
+ case '+':
+ status = CAMEL_IMAP_PLUS;
+ break;
+ default:
+ status = camel_imap_status (*cmdid, respbuf);
+ }
+
+ if (ret)
+ *ret = g_strdup (imap_next_word (respbuf));
+ } else {
+ status = CAMEL_IMAP_FAIL;
+ if (ret)
+ *ret = NULL;
+ }
+
+ return status;
+}
+
+/**
+ * camel_imap_command_continuation: Handle another transaction with the IMAP
+ * server and possibly get a multi-line response.
+ * @store: the IMAP store
+ * @cmdid: The command identifier returned from camel_imap_command_preliminary
+ * @ret: a pointer to return the full server response in
+ * @cstream: a CamelStream containing a continuation response.
+ *
+ * This method is for sending continuing responses to the IMAP server. Meant
+ * to be used as a followup to camel_imap_command_preliminary.
+ *
+ * Return value: one of CAMEL_IMAP_PLUS (command requires additional data),
+ * CAMEL_IMAP_OK (command executed successfully),
+ * CAMEL_IMAP_NO (operational error message),
+ * CAMEL_IMAP_BAD (error message from the server), or
+ * CAMEL_IMAP_FAIL (a protocol-level error occurred, and Camel is uncertain
+ * of the result of the command.)
+ **/
+gint
+camel_imap_command_continuation (CamelImapStore *store, char *cmdid, char **ret, CamelStream *cstream)
+{
+ gint len = 0, status = CAMEL_IMAP_OK;
+ gchar *respbuf;
+ GPtrArray *data;
+ int i;
+
+ d(fprintf (stderr, "sending continuation stream\r\n"));
+
+ if (camel_stream_write_to_stream (cstream, store->ostream) == -1) {
+ *ret = g_strdup (strerror (errno));
+
+ return CAMEL_IMAP_FAIL;
+ }
+
+ data = g_ptr_array_new ();
+
+ while (TRUE) {
+ CamelStreamBuffer *stream = CAMEL_STREAM_BUFFER (store->istream);
+
+ respbuf = camel_stream_buffer_read_line (stream);
+ if (!respbuf || *respbuf == '+' || !strncmp (respbuf, cmdid, strlen (cmdid))) {
+ /* IMAP's last response starts with our command id */
+ d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)"));
+
+ break;
+ }
+
+ d(fprintf (stderr, "received: %s\n", respbuf));
+
+ g_ptr_array_add (data, respbuf);
+ len += strlen (respbuf) + 1;
+ }
+
+ if (respbuf) {
+ switch (*respbuf) {
+ case '+':
+ status = CAMEL_IMAP_PLUS;
+ break;
+ default:
+ g_ptr_array_add (data, respbuf);
+ len += strlen (respbuf) + 1;
+
+ status = camel_imap_status (cmdid, respbuf);
+ }
+ } else {
+ status = CAMEL_IMAP_FAIL;
+ }
+
+ if (status == CAMEL_IMAP_OK || status == CAMEL_IMAP_PLUS) {
+ char *p;
+
+ *ret = g_malloc0 (len + 1);
+
+ for (i = 0, p = *ret; i < data->len; i++) {
+ char *ptr, *datap;
+
+ datap = (char *) data->pdata[i];
+ ptr = (*datap == '.') ? datap + 1 : datap;
+ len = strlen (ptr);
+ memcpy (p, ptr, len);
+ p += len;
+ *p++ = '\n';
+ }
+ *p = '\0';
+ } else {
+ if (status != CAMEL_IMAP_FAIL && respbuf) {
+ char *word;
+
+ word = imap_next_word (respbuf);
+
+ if (*respbuf == '-')
+ *ret = g_strdup (word);
+ else
+ *ret = g_strdup (imap_next_word (word));
+ } else {
+ *ret = NULL;
+ }
+ }
+
+ for (i = 0; i < data->len; i++)
+ g_free (data->pdata[i]);
+ g_ptr_array_free (data, TRUE);
+
+ return status;
+}
diff --git a/camel/providers/imap/camel-imap-store.h b/camel/providers/imap/camel-imap-store.h
index a860fb84bd..ce572ff45d 100644
--- a/camel/providers/imap/camel-imap-store.h
+++ b/camel/providers/imap/camel-imap-store.h
@@ -75,11 +75,21 @@ void camel_imap_store_close (CamelImapStore *store, gboolean expunge, CamelExcep
/* support functions */
-enum { CAMEL_IMAP_OK = 0, CAMEL_IMAP_NO, CAMEL_IMAP_BAD, CAMEL_IMAP_FAIL };
+enum {
+ CAMEL_IMAP_OK = 0,
+ CAMEL_IMAP_NO,
+ CAMEL_IMAP_BAD,
+ CAMEL_IMAP_PLUS,
+ CAMEL_IMAP_FAIL
+};
gint camel_imap_command (CamelImapStore *store, CamelFolder *folder, char **ret, char *fmt, ...);
gint camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char **ret, char *fmt, ...);
+/* multi-transactional commands... */
+gint camel_imap_command_preliminary (CamelImapStore *store, char **ret, char **cmdid, char *fmt, ...);
+gint camel_imap_command_continuation (CamelImapStore *store, char *cmdid, char **ret, CamelStream *cstream);
+
/* Standard Camel function */
CamelType camel_imap_store_get_type (void);