diff options
author | Dan Winship <danw@src.gnome.org> | 2000-10-04 04:06:14 +0800 |
---|---|---|
committer | Dan Winship <danw@src.gnome.org> | 2000-10-04 04:06:14 +0800 |
commit | 00f2a8d64eca2fdaf0f1569d9ccda5c869ab9cfb (patch) | |
tree | 98d3681d5e029b277fb83dd15e6bbbae07edfc53 /camel/providers/imap/camel-imap-folder.c | |
parent | 9a0fc2bc8d97cba38a3d1417d80e16bb9de165ce (diff) | |
download | gsoc2013-evolution-00f2a8d64eca2fdaf0f1569d9ccda5c869ab9cfb.tar.gz gsoc2013-evolution-00f2a8d64eca2fdaf0f1569d9ccda5c869ab9cfb.tar.zst gsoc2013-evolution-00f2a8d64eca2fdaf0f1569d9ccda5c869ab9cfb.zip |
New file containing camel_imap_command and friends. Major
* providers/imap/camel-imap-command.c: New file containing
camel_imap_command and friends. Major camel_imap_command rewrite
to remove duplicated code, make the parsing of literals be
more safe/correct, deal with RECENT/EXPUNGE responses more
consistently, and make it possible to implement the AUTHENTICATE
command.
* providers/imap/camel-imap-utils.c (imap_parse_nstring): New
function, to parse an IMAP "nstring".
* providers/imap/camel-imap-store.c: Move command stuff to
camel-imap-command.c. Update for camel_imap_command changes.
* providers/imap/camel-imap-folder.c: Update for
camel_imap_command changes.
(imap_append_message): CRLF filter the message before sending it.
* providers/imap/Makefile.am: Add camel-imap-command.[ch], remove
camel-imap-stream.[ch] for now.
svn path=/trunk/; revision=5693
Diffstat (limited to 'camel/providers/imap/camel-imap-folder.c')
-rw-r--r-- | camel/providers/imap/camel-imap-folder.c | 372 |
1 files changed, 134 insertions, 238 deletions
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c index ab2d7f88b9..21f4d3bfc2 100644 --- a/camel/providers/imap/camel-imap-folder.c +++ b/camel/providers/imap/camel-imap-folder.c @@ -37,6 +37,7 @@ #include <gal/util/e-util.h> #include "camel-imap-folder.h" +#include "camel-imap-command.h" #include "camel-imap-store.h" #include "camel-imap-stream.h" #include "camel-imap-utils.h" @@ -236,6 +237,7 @@ imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) { CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); + CamelImapResponse *response; gint i, max; if (expunge) { @@ -249,20 +251,20 @@ imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) for (i = 0; i < max; i++) { CamelMessageInfo *info; - info = (CamelMessageInfo *) g_ptr_array_index (imap_folder->summary, i); + info = g_ptr_array_index (imap_folder->summary, i); if (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) { char *flags; flags = imap_create_flag_list (info->flags); if (flags) { - gint s; - - s = camel_imap_command_extended (store, folder, NULL, ex, - "UID STORE %s FLAGS.SILENT %s", - info->uid, flags); - if (s != CAMEL_IMAP_OK) - return; + response = camel_imap_command ( + store, folder, ex, + "UID STORE %s FLAGS.SILENT %s", + info->uid, flags); g_free (flags); + if (!response) + return; + camel_imap_response_free (response); } info->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED; } @@ -273,30 +275,32 @@ imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex) static void imap_expunge (CamelFolder *folder, CamelException *ex) { + CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); + CamelImapResponse *response; + imap_sync (folder, FALSE, ex); - camel_imap_command_extended (CAMEL_IMAP_STORE (folder->parent_store), folder, NULL, ex, "EXPUNGE"); + response = camel_imap_command (store, folder, ex, "EXPUNGE"); + camel_imap_response_free (response); } static gint imap_get_message_count_internal (CamelFolder *folder, CamelException *ex) { CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - gchar *result, *msg_count, *folder_path; - GPtrArray *response; - gint status, count = 0; + char *result, *msg_count, *folder_path; + CamelImapResponse *response; + int count = 0; folder_path = camel_imap_store_folder_path (store, folder->full_name); - if (store->has_status_capability) - status = camel_imap_command_extended (store, folder, &response, ex, - "STATUS \"%s\" (MESSAGES)", folder_path); + response = camel_imap_command (store, folder, ex, + "STATUS \"%s\" (MESSAGES)", + folder_path); else - status = camel_imap_command_extended (store, folder, &response, ex, - "EXAMINE \"%s\"", folder_path); - + response = camel_imap_command (store, folder, ex, + "EXAMINE \"%s\"", folder_path); g_free (folder_path); - - if (status != CAMEL_IMAP_OK) + if (!response) return 0; /* parse out the message count */ @@ -368,14 +372,16 @@ imap_get_unread_message_count (CamelFolder *folder) } static void -imap_append_message (CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, CamelException *ex) +imap_append_message (CamelFolder *folder, CamelMimeMessage *message, + const CamelMessageInfo *info, CamelException *ex) { CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); + CamelImapResponse *response; CamelStream *memstream; + CamelMimeFilter *crlf_filter; + CamelStreamFilter *streamfilter; GByteArray *ba; - gchar *cmdid; - gchar *folder_path, *flagstr; - gint status; + char *folder_path, *flagstr, *result; folder_path = camel_imap_store_folder_path (store, folder->full_name); @@ -384,74 +390,83 @@ imap_append_message (CamelFolder *folder, CamelMimeMessage *message, const Camel flagstr = imap_create_flag_list (info->flags); else flagstr = NULL; - + + /* FIXME: We could avoid this if we knew how big the message was. */ + memstream = camel_stream_mem_new (); 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); - - status = camel_imap_command_preliminary (store, &cmdid, ex, "APPEND %s%s%s {%d}", - folder_path, flagstr ? " " : "", - flagstr ? flagstr : "", ba->len - 2); + 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 %s%s%s {%d}", + folder_path, flagstr ? " " : "", + flagstr ? flagstr : "", ba->len); g_free (folder_path); g_free (flagstr); - if (status != CAMEL_IMAP_PLUS) { - g_free (cmdid); - camel_object_unref (CAMEL_OBJECT (memstream)); + if (!response) { + g_byte_array_free (ba, TRUE); return; } - + result = camel_imap_response_extract_continuation (response, ex); + if (!result) { + g_byte_array_free (ba, TRUE); + return; + } + g_free (result); + /* send the rest of our data - the mime message */ - status = camel_imap_command_continuation_with_stream (store, NULL, cmdid, memstream, ex); - g_free (cmdid); - - if (status != CAMEL_IMAP_OK) + g_byte_array_append (ba, "\0", 3); + response = camel_imap_command_continuation (store, ex, ba->data); + g_byte_array_free (ba, TRUE); + if (!response) return; - - camel_object_unref (CAMEL_OBJECT (memstream)); - camel_imap_folder_changed (folder, 1, NULL, ex); + camel_imap_response_free (response); } static void -imap_copy_message_to (CamelFolder *source, const char *uid, CamelFolder *destination, CamelException *ex) +imap_copy_message_to (CamelFolder *source, const char *uid, + CamelFolder *destination, CamelException *ex) { CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store); + CamelImapResponse *response; char *folder_path; - int status; folder_path = camel_imap_store_folder_path (store, destination->full_name); - status = camel_imap_command_extended (store, source, NULL, ex, - "UID COPY %s %s", uid, folder_path); + response = camel_imap_command (store, source, ex, "UID COPY %s %s", + uid, folder_path); + camel_imap_response_free (response); g_free (folder_path); - - if (status != CAMEL_IMAP_OK) - return; - - camel_imap_folder_changed (destination, 1, NULL, ex); } /* FIXME: Duplication of code! */ static void -imap_move_message_to (CamelFolder *source, const char *uid, CamelFolder *destination, CamelException *ex) +imap_move_message_to (CamelFolder *source, const char *uid, + CamelFolder *destination, CamelException *ex) { CamelImapStore *store = CAMEL_IMAP_STORE (source->parent_store); + CamelImapResponse *response; char *folder_path; - int status; - + folder_path = camel_imap_store_folder_path (store, destination->full_name); - status = camel_imap_command_extended (store, source, NULL, ex, - "UID COPY %s %s", uid, folder_path); + response = camel_imap_command (store, source, ex, "UID COPY %s %s", + uid, folder_path); + camel_imap_response_free (response); g_free (folder_path); - - if (status != CAMEL_IMAP_OK) + + if (camel_exception_is_set (ex)) return; - + camel_folder_delete_message (source, uid); - - camel_imap_folder_changed (destination, 1, NULL, ex); } static GPtrArray * @@ -480,142 +495,41 @@ static CamelMimeMessage * imap_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex) { CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - CamelStream *msgstream = NULL; - CamelMimeMessage *msg = NULL; - gchar *result, *header, *body, *mesg, *p, *q, *data_item; - int status, part_len; - - if (store->server_level >= IMAP_LEVEL_IMAP4REV1) - data_item = "BODY.PEEK[HEADER]"; - else - data_item = "RFC822.HEADER"; - - status = camel_imap_fetch_command (store, folder, &result, ex, - "UID FETCH %s %s", uid, data_item); - - if (!result || status != CAMEL_IMAP_OK) - return NULL; - - /* parse out the message part */ - for (p = result; *p && *p != '{' && *p != '"' && *p != '\n'; p++); - switch (*p) { - case '"': - /* a quoted string - section 4.3 */ - p++; - for (q = p; *q && *q != '"' && *q != '\n'; q++); - part_len = (gint) (q - p); - - break; - case '{': - /* a literal string - section 4.3 */ - part_len = atoi (p + 1); - for ( ; *p && *p != '\n'; p++); - if (*p != '\n') { - g_free (result); - return NULL; - } - - /* advance to the beginning of the actual data */ - p++; - - /* calculate the new part-length */ - for (q = p; *q && (q - p) <= part_len; q++) { - if (*q == '\n') - part_len--; - } - - /* FIXME: This is a hack for IMAP daemons that send us a UID at the end of each FETCH */ - for ( ; q > p && *(q-1) != '\n'; q--, part_len--); - part_len++; - - break; - default: - /* Bad input */ - g_free (result); + CamelImapResponse *response; + CamelStream *msgstream; + CamelMimeMessage *msg; + char *result, *mesg, *p; + int len; + + response = camel_imap_command (store, folder, ex, + "UID FETCH %s RFC822", uid); + if (!response) return NULL; - } - - header = g_strndup (p, part_len); - - g_free (result); - d(fprintf (stderr, "*** We got the header ***\n")); - - if (store->server_level >= IMAP_LEVEL_IMAP4REV1) - data_item = "BODY[TEXT]"; - else - data_item = "RFC822.TEXT"; - - status = camel_imap_fetch_command (store, folder, &result, ex, - "UID FETCH %s %s", uid, data_item); - - if (!result || status != CAMEL_IMAP_OK) { - g_free (header); + result = camel_imap_response_extract (response, "FETCH", ex); + if (!result) return NULL; + + p = strstr (result, "RFC822"); + if (p) { + p += 7; + mesg = imap_parse_nstring (&p, &len); } - - /* parse out the message part */ - for (p = result; *p && *p != '{' && *p != '"' && *p != '\n'; p++); - switch (*p) { - case '"': - /* a quoted string - section 4.3 */ - p++; - for (q = p; *q && *q != '"' && *q != '\n'; q++); - part_len = (gint) (q - p); - - break; - case '{': - /* a literal string - section 4.3 */ - part_len = atoi (p + 1); - for ( ; *p && *p != '\n'; p++); - if (*p != '\n') { - g_free (result); - g_free (header); - return NULL; - } - - /* advance to the beginning of the actual data */ - p++; - - /* calculate the new part-length */ - for (q = p; *q && (q - p) <= part_len; q++) { - if (*q == '\n') - part_len--; - } - - /* FIXME: This is a hack for IMAP daemons that send us a UID at the end of each FETCH */ - for ( ; q > p && *(q-1) != '\n'; q--, part_len--); - part_len++; - - break; - default: - /* Bad input */ + if (!p) { + camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, + "Could not find message body in FETCH " + "response."); g_free (result); - g_free (header); return NULL; } - - body = g_strndup (p, part_len); - g_free (result); - d(fprintf (stderr, "*** We got the body ***\n")); - - mesg = g_strdup_printf ("%s\n%s", header, body); - g_free (header); - g_free (body); - d(fprintf (stderr, "*** We got the mesg ***\n")); - - d(fprintf (stderr, "Message:\n%s\n", mesg)); - - msgstream = camel_stream_mem_new_with_buffer (mesg, strlen (mesg) + 1); + + msgstream = camel_stream_mem_new_with_buffer (mesg, len); msg = camel_mime_message_new (); - d(fprintf (stderr, "*** We created the camel_mime_message ***\n")); - - camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), msgstream); + camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), + msgstream); camel_object_unref (CAMEL_OBJECT (msgstream)); - - d(fprintf (stderr, "*** We're returning... ***\n")); - g_free (mesg); + return msg; } @@ -673,7 +587,8 @@ imap_protocol_get_summary_specifier (CamelImapStore *store) sect_end = ""; } - return g_strdup_printf ("UID FLAGS %s (%s)%s", sect_begin, headers_wanted, sect_end); + return g_strdup_printf ("UID FLAGS %s (%s)%s", sect_begin, + headers_wanted, sect_end); } static GPtrArray * @@ -682,10 +597,11 @@ imap_get_summary_internal (CamelFolder *folder, CamelException *ex) /* This ALWAYS updates the summary except on fail */ CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); + CamelImapResponse *response; GPtrArray *summary = NULL, *headers = NULL; GHashTable *hash = NULL; - gint num, i, j, status = 0; - char *result, *q, *node; + int num, i, j; + char *q; const char *received; char *summary_specifier; struct _header_raw *h = NULL, *tail = NULL; @@ -706,17 +622,18 @@ imap_get_summary_internal (CamelFolder *folder, CamelException *ex) } summary_specifier = imap_protocol_get_summary_specifier (store); - if (num == 1) { - status = camel_imap_fetch_command (store, folder, &result, ex, - "FETCH 1 (%s)", summary_specifier); + response = camel_imap_command (store, folder, ex, + "FETCH 1 (%s)", + summary_specifier); } else { - status = camel_imap_fetch_command (store, folder, &result, ex, - "FETCH 1:%d (%s)", num, summary_specifier); + response = camel_imap_command (store, folder, ex, + "FETCH 1:%d (%s)", num, + summary_specifier); } g_free (summary_specifier); - if (status != CAMEL_IMAP_OK) { + if (!response) { if (!imap_folder->summary) { imap_folder->summary = g_ptr_array_new (); imap_folder->summary_hash = g_hash_table_new (g_str_hash, g_str_equal); @@ -724,32 +641,12 @@ imap_get_summary_internal (CamelFolder *folder, CamelException *ex) return imap_folder->summary; } - + headers = response->untagged; + /* initialize our new summary-to-be */ summary = g_ptr_array_new (); hash = g_hash_table_new (g_str_hash, g_str_equal); - /* create our array of headers from the server response */ - headers = g_ptr_array_new (); - node = result; - for (i = 1; node; i++) { - char *end; - - if ((end = strstr (node + 2, "\n*"))) { - g_ptr_array_add (headers, g_strndup (node, (gint)(end - node))); - } else { - g_ptr_array_add (headers, g_strdup (node)); - } - node = end; - } - if (i < num) { - d(fprintf (stderr, "IMAP server didn't respond with as many headers as we expected...\n")); - /* should we error?? */ - } - - g_free (result); - result = NULL; - for (i = 0; i < headers->len; i++) { CamelMessageInfo *info; char *uid, *flags, *header; @@ -834,10 +731,7 @@ imap_get_summary_internal (CamelFolder *folder, CamelException *ex) g_ptr_array_add (summary, info); g_hash_table_insert (hash, info->uid, info); } - - for (i = 0; i < headers->len; i++) - g_free (headers->pdata[i]); - g_ptr_array_free (headers, TRUE); + camel_imap_response_free (response); /* clean up any previous summary data */ imap_folder_summary_free (imap_folder); @@ -861,22 +755,24 @@ static CamelMessageInfo * imap_get_message_info_internal (CamelFolder *folder, guint id, CamelException *ex) { CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); + CamelImapResponse *response; CamelMessageInfo *info = NULL; struct _header_raw *h, *tail = NULL; const char *received; char *result, *uid, *flags, *header, *q; char *summary_specifier; - int j, status; + int j; /* we don't have a cached copy, so fetch it */ summary_specifier = imap_protocol_get_summary_specifier (store); - - status = camel_imap_fetch_command (store, folder, &result, ex, - "FETCH %d (%s)", id, summary_specifier); - + response = camel_imap_command (store, folder, ex, + "FETCH %d (%s)", id, summary_specifier); g_free (summary_specifier); - - if (status != CAMEL_IMAP_OK) + + if (!response) + return NULL; + result = camel_imap_response_extract (response, "FETCH", ex); + if (!result) return NULL; /* lets grab the UID... */ @@ -977,9 +873,9 @@ imap_get_message_info (CamelFolder *folder, const char *uid) static GPtrArray * imap_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex) { - GPtrArray *response, *uids = NULL; + CamelImapResponse *response; + GPtrArray *uids = NULL; char *result, *sexp, *p; - int status; d(fprintf (stderr, "camel sexp: '%s'\n", expression)); sexp = imap_translate_sexp (expression); @@ -992,12 +888,12 @@ imap_search_by_expression (CamelFolder *folder, const char *expression, CamelExc return uids; } - status = camel_imap_command_extended (CAMEL_IMAP_STORE (folder->parent_store), folder, - &response, NULL, "UID SEARCH %s", sexp); + response = camel_imap_command (CAMEL_IMAP_STORE (folder->parent_store), + folder, NULL, "UID SEARCH %s", sexp); g_free (sexp); - - if (status != CAMEL_IMAP_OK) + if (!response) return uids; + result = camel_imap_response_extract (response, "SEARCH", NULL); if (!result) return uids; |