diff options
Diffstat (limited to 'camel/providers/imap')
-rw-r--r-- | camel/providers/imap/camel-imap-folder.c | 60 | ||||
-rw-r--r-- | camel/providers/imap/camel-imap-store.c | 19 | ||||
-rw-r--r-- | camel/providers/imap/camel-imap-store.h | 2 |
3 files changed, 53 insertions, 28 deletions
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c index 894b7a0865..5a157a037c 100644 --- a/camel/providers/imap/camel-imap-folder.c +++ b/camel/providers/imap/camel-imap-folder.c @@ -548,18 +548,15 @@ imap_append_message (CamelFolder *folder, CamelMimeMessage *message, const Camel { CamelStore *store = CAMEL_STORE (folder->parent_store); CamelURL *url = CAMEL_SERVICE (store)->url; - CamelStreamMem *mem; - gchar *result, *folder_path, *dir_sep, *flagstr = NULL; + CamelStream *memstream; + GByteArray *ba; + gchar *result, *cmdid, *dir_sep; + gchar *folder_path, *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_DATA_WRAPPER (message)->stream); - - mem->buffer = g_byte_array_append (mem->buffer, g_strdup ("\r\n"), 3); - + dir_sep = CAMEL_IMAP_STORE (folder->parent_store)->dir_sep; if (url && url->path && *(url->path + 1) && strcmp (folder->full_name, "INBOX")) @@ -577,31 +574,52 @@ imap_append_message (CamelFolder *folder, CamelMimeMessage *message, const Camel *(flagstr + strlen (flagstr) - 1) = ')'; } - /* FIXME: len isn't really correct I don't think, we need to crlf/dot filter */ - /* FIXME: Dont copy the message ANOTHER TIME, its already in memory entirely - copied, thats bad enough */ - status = camel_imap_command_extended (CAMEL_IMAP_STORE (folder->parent_store), - folder, &result, "APPEND %s%s {%d}\r\n%s", - folder_path, flagstr ? flagstr : "", - mem->buffer->len - 1, mem->buffer->data); + ba = g_byte_array_new (); + memstream = camel_stream_mem_new_with_byte_array (ba); + /* FIXME: we need to crlf/dot filter */ + camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), memstream); + camel_stream_write_string (memstream, "\r\n"); + camel_stream_reset (memstream); - if (status != CAMEL_IMAP_OK) { + status = camel_imap_command_preliminary (CAMEL_IMAP_STORE (folder->parent_store), + &result, &cmdid, "APPEND %s%s {%d}", + folder_path, flagstr ? flagstr : "", ba->len - 2); + + if (status != CAMEL_IMAP_PLUS) { CamelService *service = CAMEL_SERVICE (folder->parent_store); camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, "Could not APPEND message to IMAP server %s: %s.", - service->url->host, - status != CAMEL_IMAP_FAIL && result ? result : - "Unknown error"); + service->url->host, result ? result : "Unknown error"); + g_free (result); + g_free (cmdid); g_free (folder_path); return; } - /* FIXME: we should close/free the mem stream */ - g_free (result); g_free (folder_path); + /* send the rest of our data - the mime message */ + status = camel_imap_command_continuation (CAMEL_IMAP_STORE (folder->parent_store), + &result, cmdid, memstream); + + if (status != CAMEL_IMAP_OK) { + CamelService *service = CAMEL_SERVICE (folder->parent_store); + camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, + "Could not APPEND message to IMAP server %s: %s.", + service->url->host, result ? result : "Unknown error"); + + camel_object_unref (CAMEL_OBJECT (memstream)); + g_free (result); + g_free (cmdid); + return; + } + + camel_object_unref (CAMEL_OBJECT (memstream)); + g_free (cmdid); + g_free (result); + camel_imap_folder_changed (folder, 1, ex); } diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c index 6eb03e9db4..d5985bb9ea 100644 --- a/camel/providers/imap/camel-imap-store.c +++ b/camel/providers/imap/camel-imap-store.c @@ -1023,6 +1023,7 @@ camel_imap_command_preliminary (CamelImapStore *store, char **ret, char **cmdid, if (respbuf) { switch (*respbuf) { case '+': + /* continuation request */ status = CAMEL_IMAP_PLUS; break; default: @@ -1050,6 +1051,9 @@ camel_imap_command_preliminary (CamelImapStore *store, char **ret, char **cmdid, * * This method is for sending continuing responses to the IMAP server. Meant * to be used as a followup to camel_imap_command_preliminary. + * camel_imap_command_continuation will set @ret 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 (command requires additional data), * CAMEL_IMAP_OK (command executed successfully), @@ -1059,7 +1063,7 @@ camel_imap_command_preliminary (CamelImapStore *store, char **ret, char **cmdid, * of the result of the command.) **/ gint -camel_imap_command_continuation (CamelImapStore *store, char *cmdid, char **ret, CamelStream *cstream) +camel_imap_command_continuation (CamelImapStore *store, char **ret, char *cmdid, CamelStream *cstream) { gint len = 0, status = CAMEL_IMAP_OK; gchar *respbuf; @@ -1069,19 +1073,22 @@ camel_imap_command_continuation (CamelImapStore *store, char *cmdid, char **ret, d(fprintf (stderr, "sending continuation stream\r\n")); if (camel_stream_write_to_stream (cstream, store->ostream) == -1) { + d(fprintf (stderr, "failed to send continuation stream\r\n")); + *ret = g_strdup (strerror (errno)); return CAMEL_IMAP_FAIL; } + d(fprintf (stderr, "okie dokie...\r\n")); data = g_ptr_array_new (); - while (TRUE) { + while (1) { 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 */ + /* IMAP's last response starts with our command id or a continuation request */ d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); break; @@ -1094,14 +1101,14 @@ camel_imap_command_continuation (CamelImapStore *store, char *cmdid, char **ret, } if (respbuf) { + g_ptr_array_add (data, respbuf); + len += strlen (respbuf) + 1; + 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 { diff --git a/camel/providers/imap/camel-imap-store.h b/camel/providers/imap/camel-imap-store.h index ce572ff45d..678cf83a1d 100644 --- a/camel/providers/imap/camel-imap-store.h +++ b/camel/providers/imap/camel-imap-store.h @@ -88,7 +88,7 @@ gint camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, ch /* 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); +gint camel_imap_command_continuation (CamelImapStore *store, char **ret, char *cmdid, CamelStream *cstream); /* Standard Camel function */ CamelType camel_imap_store_get_type (void); |