From 0d82053015309f173335c41052356f20ef1c6227 Mon Sep 17 00:00:00 2001 From: NotZed Date: Sat, 22 Apr 2000 05:22:20 +0000 Subject: Ref the folder after setting it in the new message. 2000-04-22 NotZed * providers/mbox/camel-mbox-folder.c (_get_message_by_uid): Ref the folder after setting it in the new message. * camel-mime-part.c (my_set_content_object): Have the headers follow the content-type change here too. (my_write_to_stream): Dont write content-type here, automatically stored in the headers ... (my_write_to_stream): Use header_disposition_format() to format the content-disposition header. (my_write_to_stream): Removed old code, all headers are now stored in the camel-medium level, always. Need to do the same with camel-mime-message i suppose ... * camel-mime-utils.c (header_content_type_is): Handle empty types. * gmime-content-field.c (gmime_content_field_write_to_stream): Use header_content_type_format() to format it. 2000-04-21 NotZed * camel-mime-utils.h: Add prototype for header_param_list_free. * camel-recipient.c: New function to remove all the types of a recipient list. I think this whole object needs a major review. * camel-mime-message.c (camel_mime_message_class_init): Removed parse_header_pair override, override add_header instead. (_parse_header_pair): Renamed to add_header. (remove_header): Add this method, to make sure we keep upto date with removed headers too. (_set_field): If given a NULL value, clear it out. (_set_recipient_list_from_string): Constify. (set_header): Override set_header from camel_medium. (process_header): Local function to handle set/add/remove of each header we know about. * camel-mime-part.c (camel_mime_part_class_init): Removed parse_header_pair setup. (my_parse_header_pair): Moved into add_header(), removed. (my_set_disposition): Allow a NULL disposition to clear it. (my_set_content_id): Allow NULL content id to clear it. (remove_header): Track removed headers. (my_set_description): Allow NULL description to clear it. (my_set_content_MD5): Make sure we copy the md5 value, and allow a NULL value to reset it. (my_set_filename): Copy the filename. (my_set_header_lines): Removed. Nothing uses it, it doesn't actually serve any purpose. (camel_mime_part_set_header_lines): Ditto. (my_get_header_lines): Ditto. (camel_mime_part_get_header_lines): Ditto. (camel_mime_part_class_init): Remove *_header_lines setup. (camel_mime_part_init): Remove header_lines init. (my_finalize): Remove header_lines finalise. (my_write_to_stream): Write the headers here. This is just WRONG, camel_medium should be doing this. (my_get_output_stream): Kill a warning. (camel_mime_part_encoding_to_string): Ditto. (camel_mime_part_set_description): Unvirtualiase, use add_header() to do the processing. (my_set_description): Removed. (set_disposition): Renamed from my_set_disposition. (camel_mime_part_get_description): Get the descriptionf rom the get_header method. (my_get_description): Removed. (my_set_filename): Removed. (camel_mime_part_get_filename): Get the parameter from the disposition. (camel_mime_part_encoding_from_string): Handle NULL string. (camel_mime_part_init): Remove reference to filename. (my_finalize): Dont free filename. * camel-mime-part.h (CamelMimePartClass): Removed parse_header_pair() method, it doesn't add anything that add_header() can't be used for. (CamelMimePartClass): Remove *_header_lines methods. (struct _CamelMimePart): Remove header_lines list. (struct _CamelMimePart): Removed filename attribute. * camel-medium.c (camel_medium_init): Init headers to null, not a hashtable. (add_header): Append the headers as a list. (remove_header): Remove headers as a list. (get_header): Likewise for lookup. (free_header): Removed, no longer needed. (finalize): Free headers using header_raw_clear(). (camel_medium_set_header): New function, to reset and override all values of a header with a new value. * camel-medium.h (struct _CamelMedium): Changed to use a header_raw struct rather than a hash table, to store headers (many headers can occur multiple times). * camel-mime-utils.c (header_raw_find_next): New function, allows you to find multi-valued header fields. (header_disposition_format): New function to format/create content-disposition header string. (header_param_list_format_append): Function to format parameter lists into a GString. (header_content_type_format): Function to format content-type into a usable format. (header_set_param): allow NULL value to remove the parameter. (decode_token): Renamed from header_decode_token. (header_decode_token): New interface for external use. (quoted_decode): Made static to kill annoying warnings. (g_strdup_len): Killed, replaced with calls to g_strndup(). (rfc2047_decode_word): Made static to kill warnings. (decode_coded_string): Terminated. (g_string_append_len): Made static to kill warnings. (header_decode_text): Made static to kill warnings. (header_decode_text): Constify. (rfc2047_decode_word): Constify. (header_param): Constify. (header_content_type_new): Copy the type/subtype strings. (header_param_list_decode): Made static. (header_param_list_format_append): Made static. (quoted_decode): Constify. (g_string_append_len): Constify. (header_token_decode): New function to decode a single token. * providers/mbox/camel-mbox-summary.c (header_write): Append a trailing \n when writing headers. (strdup_trim): Killed a warning. (camel_mbox_summary_set_uid): Make sure the next uid is at least 1 higher than any existing one. (header_evolution_decode): Use header_token_decode to get the token. * camel-mime-parser.c (folder_scan_header): Strip the trailing \n of the end of all header lines. svn path=/trunk/; revision=2551 --- camel/ChangeLog | 133 ++++++++ camel/camel-medium.c | 86 ++--- camel/camel-medium.h | 31 +- camel/camel-mime-message.c | 93 ++++-- camel/camel-mime-parser.c | 4 + camel/camel-mime-part.c | 538 +++++++++++------------------- camel/camel-mime-part.h | 55 +-- camel/camel-mime-utils.c | 202 ++++++++--- camel/camel-mime-utils.h | 20 +- camel/camel-recipient.c | 28 +- camel/camel-recipient.h | 3 +- camel/gmime-content-field.c | 21 +- camel/providers/mbox/camel-mbox-folder.c | 1 + camel/providers/mbox/camel-mbox-summary.c | 17 +- 14 files changed, 655 insertions(+), 577 deletions(-) diff --git a/camel/ChangeLog b/camel/ChangeLog index 3575fe6f52..bc276d86a1 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,136 @@ +2000-04-22 NotZed + + * providers/mbox/camel-mbox-folder.c (_get_message_by_uid): Ref + the folder after setting it in the new message. + + * camel-mime-part.c (my_set_content_object): Have the headers + follow the content-type change here too. + (my_write_to_stream): Dont write content-type here, automatically + stored in the headers ... + (my_write_to_stream): Use header_disposition_format() to format + the content-disposition header. + (my_write_to_stream): Removed old code, all headers are now stored + in the camel-medium level, always. Need to do the same with + camel-mime-message i suppose ... + + * camel-mime-utils.c (header_content_type_is): Handle empty types. + + * gmime-content-field.c (gmime_content_field_write_to_stream): Use + header_content_type_format() to format it. + +2000-04-21 NotZed + + * camel-mime-utils.h: Add prototype for header_param_list_free. + + * camel-recipient.c: New function to remove all the types of a + recipient list. I think this whole object needs a major review. + + * camel-mime-message.c (camel_mime_message_class_init): Removed + parse_header_pair override, override add_header instead. + (_parse_header_pair): Renamed to add_header. + (remove_header): Add this method, to make sure we keep upto date + with removed headers too. + (_set_field): If given a NULL value, clear it out. + (_set_recipient_list_from_string): Constify. + (set_header): Override set_header from camel_medium. + (process_header): Local function to handle set/add/remove of each + header we know about. + + * camel-mime-part.c (camel_mime_part_class_init): Removed + parse_header_pair setup. + (my_parse_header_pair): Moved into add_header(), removed. + (my_set_disposition): Allow a NULL disposition to clear it. + (my_set_content_id): Allow NULL content id to clear it. + (remove_header): Track removed headers. + (my_set_description): Allow NULL description to clear it. + (my_set_content_MD5): Make sure we copy the md5 value, and allow a + NULL value to reset it. + (my_set_filename): Copy the filename. + (my_set_header_lines): Removed. Nothing uses it, it doesn't + actually serve any purpose. + (camel_mime_part_set_header_lines): Ditto. + (my_get_header_lines): Ditto. + (camel_mime_part_get_header_lines): Ditto. + (camel_mime_part_class_init): Remove *_header_lines setup. + (camel_mime_part_init): Remove header_lines init. + (my_finalize): Remove header_lines finalise. + (my_write_to_stream): Write the headers here. This is just WRONG, + camel_medium should be doing this. + (my_get_output_stream): Kill a warning. + (camel_mime_part_encoding_to_string): Ditto. + (camel_mime_part_set_description): Unvirtualiase, use add_header() + to do the processing. + (my_set_description): Removed. + (set_disposition): Renamed from my_set_disposition. + (camel_mime_part_get_description): Get the descriptionf rom the + get_header method. + (my_get_description): Removed. + (my_set_filename): Removed. + (camel_mime_part_get_filename): Get the parameter from the + disposition. + (camel_mime_part_encoding_from_string): Handle NULL string. + (camel_mime_part_init): Remove reference to filename. + (my_finalize): Dont free filename. + + * camel-mime-part.h (CamelMimePartClass): Removed + parse_header_pair() method, it doesn't add anything that + add_header() can't be used for. + (CamelMimePartClass): Remove *_header_lines methods. + (struct _CamelMimePart): Remove header_lines list. + (struct _CamelMimePart): Removed filename attribute. + + * camel-medium.c (camel_medium_init): Init headers to null, not a + hashtable. + (add_header): Append the headers as a list. + (remove_header): Remove headers as a list. + (get_header): Likewise for lookup. + (free_header): Removed, no longer needed. + (finalize): Free headers using header_raw_clear(). + (camel_medium_set_header): New function, to reset and override all + values of a header with a new value. + + * camel-medium.h (struct _CamelMedium): Changed to use a + header_raw struct rather than a hash table, to store headers + (many headers can occur multiple times). + + * camel-mime-utils.c (header_raw_find_next): New function, allows + you to find multi-valued header fields. + (header_disposition_format): New function to format/create + content-disposition header string. + (header_param_list_format_append): Function to format parameter + lists into a GString. + (header_content_type_format): Function to format content-type into + a usable format. + (header_set_param): allow NULL value to remove the parameter. + (decode_token): Renamed from header_decode_token. + (header_decode_token): New interface for external use. + (quoted_decode): Made static to kill annoying warnings. + (g_strdup_len): Killed, replaced with calls to g_strndup(). + (rfc2047_decode_word): Made static to kill warnings. + (decode_coded_string): Terminated. + (g_string_append_len): Made static to kill warnings. + (header_decode_text): Made static to kill warnings. + (header_decode_text): Constify. + (rfc2047_decode_word): Constify. + (header_param): Constify. + (header_content_type_new): Copy the type/subtype strings. + (header_param_list_decode): Made static. + (header_param_list_format_append): Made static. + (quoted_decode): Constify. + (g_string_append_len): Constify. + (header_token_decode): New function to decode a single token. + + * providers/mbox/camel-mbox-summary.c (header_write): Append a + trailing \n when writing headers. + (strdup_trim): Killed a warning. + (camel_mbox_summary_set_uid): Make sure the next uid is at least 1 + higher than any existing one. + (header_evolution_decode): Use header_token_decode to get the + token. + + * camel-mime-parser.c (folder_scan_header): Strip the trailing \n + of the end of all header lines. + 2000-04-20 NotZed * providers/mbox/camel-mbox-utils.[ch]: Removed. diff --git a/camel/camel-medium.c b/camel/camel-medium.c index 1fd77c28ad..fe87911b14 100644 --- a/camel/camel-medium.c +++ b/camel/camel-medium.c @@ -3,8 +3,8 @@ /* * - * Author : - * Bertrand Guiheneuf + * Authors: Bertrand Guiheneuf + * Michael Zucchi * * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com) * @@ -40,6 +40,7 @@ static CamelDataWrapperClass *parent_class = NULL; static void add_header (CamelMedium *medium, const gchar *header_name, const gchar *header_value); +static void set_header (CamelMedium *medium, const gchar *header_name, const gchar *header_value); static void remove_header (CamelMedium *medium, const gchar *header_name); static const gchar *get_header (CamelMedium *medium, const gchar *header_name); @@ -61,6 +62,7 @@ camel_medium_class_init (CamelMediumClass *camel_medium_class) /* virtual method definition */ camel_medium_class->add_header = add_header; + camel_medium_class->set_header = set_header; camel_medium_class->remove_header = remove_header; camel_medium_class->get_header = get_header; @@ -75,8 +77,7 @@ camel_medium_init (gpointer object, gpointer klass) { CamelMedium *camel_medium = CAMEL_MEDIUM (object); - camel_medium->headers = g_hash_table_new (g_strcase_hash, - g_strcase_equal); + camel_medium->headers = NULL; camel_medium->content = NULL; } @@ -105,23 +106,12 @@ camel_medium_get_type (void) return camel_medium_type; } - -static void -free_header (gpointer key, gpointer value, gpointer data) -{ - g_free (key); - g_free (value); -} - static void finalize (GtkObject *object) { CamelMedium *medium = CAMEL_MEDIUM (object); - if (medium->headers) { - g_hash_table_foreach (medium->headers, free_header, NULL); - g_hash_table_destroy (medium->headers); - } + header_raw_clear(&medium->headers); if (medium->content) gtk_object_unref (GTK_OBJECT (medium->content)); @@ -129,24 +119,11 @@ finalize (GtkObject *object) GTK_OBJECT_CLASS (parent_class)->finalize (object); } - - static void add_header (CamelMedium *medium, const gchar *header_name, const gchar *header_value) { - gpointer old_name; - gpointer old_value; - - /* FIXME: This only allows each header to occur once. */ - if (g_hash_table_lookup_extended (medium->headers, header_name, - &old_name, &old_value)) { - g_hash_table_remove (medium->headers, old_name); - g_free (old_name); - g_free (old_value); - } - g_hash_table_insert (medium->headers, g_strdup (header_name), - g_strdup (header_value)); + header_raw_append(&medium->headers, header_name, header_value, -1); } /** @@ -159,7 +136,7 @@ add_header (CamelMedium *medium, const gchar *header_name, * * FIXME: Where does it add it? We need to be able to prepend and * append headers, and also be able to insert them relative to other - * headers. + * headers. No we dont, order isn't important! Z **/ void camel_medium_add_header (CamelMedium *medium, const gchar *header_name, @@ -172,20 +149,35 @@ camel_medium_add_header (CamelMedium *medium, const gchar *header_name, CM_CLASS (medium)->add_header (medium, header_name, header_value); } +static void +set_header (CamelMedium *medium, const gchar *header_name, const gchar *header_value) +{ + header_raw_replace(&medium->headers, header_name, header_value, -1); +} + +/** + * camel_medium_set_header: + * @medium: a CamelMedium + * @header_name: name of the header + * @header_value: value of the header + * + * Sets the value of a header. Any other occurances of the header + * will be removed. + **/ +void +camel_medium_set_header (CamelMedium *medium, const gchar *header_name, const gchar *header_value) +{ + g_return_if_fail (CAMEL_IS_MEDIUM (medium)); + g_return_if_fail (header_name != NULL); + g_return_if_fail (header_value != NULL); + + CM_CLASS (medium)->add_header (medium, header_name, header_value); +} static void remove_header (CamelMedium *medium, const gchar *header_name) { - gpointer old_name; - gpointer old_value; - - /* FIXME: This only allows each header to occur once. */ - if (g_hash_table_lookup_extended (medium->headers, header_name, - &old_name, &old_value)) { - g_hash_table_remove (medium->headers, header_name); - g_free (old_name); - g_free (old_value); - } + header_raw_remove(&medium->headers, header_name); } /** @@ -193,10 +185,8 @@ remove_header (CamelMedium *medium, const gchar *header_name) * @medium: a medium * @header_name: the name of the header * - * Removes the named header from the medium. - * - * FIXME: If there are multiple occurrences of the header, which - * gets/get removed? + * Removes the named header from the medium. All occurances of the + * header are removed. **/ void camel_medium_remove_header (CamelMedium *medium, const gchar *header_name) @@ -211,11 +201,7 @@ camel_medium_remove_header (CamelMedium *medium, const gchar *header_name) static const gchar * get_header (CamelMedium *medium, const gchar *header_name) { - gchar *header_value; - - header_value = (gchar *)g_hash_table_lookup (medium->headers, - header_name); - return header_value; + return header_raw_find(&medium->headers, header_name, NULL); } /** diff --git a/camel/camel-medium.h b/camel/camel-medium.h index 7c85bd2ed7..91693439e2 100644 --- a/camel/camel-medium.h +++ b/camel/camel-medium.h @@ -3,8 +3,8 @@ /* * - * Author : - * Bertrand Guiheneuf + * Authors: Bertrand Guiheneuf + * Michael Zucchi * * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com) * @@ -35,8 +35,9 @@ extern "C" { #endif /* __cplusplus }*/ #include -#include "camel-types.h" -#include "camel-data-wrapper.h" +#include +#include +#include #define CAMEL_MEDIUM_TYPE (camel_medium_get_type ()) #define CAMEL_MEDIUM(obj) (GTK_CHECK_CAST((obj), CAMEL_MEDIUM_TYPE, CamelMedium)) @@ -48,7 +49,7 @@ struct _CamelMedium { CamelDataWrapper parent_object; - GHashTable *headers; + struct _header_raw *headers; /* The content of the medium, as opposed to our parent * CamelDataWrapper, which wraps both the headers and the @@ -64,15 +65,13 @@ typedef struct { CamelDataWrapperClass parent_class; /* Virtual methods */ - void (*add_header) (CamelMedium *medium, const gchar *header_name, - const gchar *header_value); + void (*add_header) (CamelMedium *medium, const gchar *header_name, const gchar *header_value); + void (*set_header) (CamelMedium *medium, const gchar *header_name, const gchar *header_value); void (*remove_header) (CamelMedium *medium, const gchar *header_name); - const gchar * (*get_header) (CamelMedium *medium, - const gchar *header_name); + const gchar * (*get_header) (CamelMedium *medium, const gchar *header_name); CamelDataWrapper * (*get_content_object) (CamelMedium *medium); - void (*set_content_object) (CamelMedium *medium, - CamelDataWrapper *content); + void (*set_content_object) (CamelMedium *medium, CamelDataWrapper *content); } CamelMediumClass; @@ -83,12 +82,10 @@ GtkType camel_medium_get_type (void); /* public methods */ -void camel_medium_add_header (CamelMedium *medium, const gchar *header_name, - const gchar *header_value); -void camel_medium_remove_header (CamelMedium *medium, - const gchar *header_name); -const gchar *camel_medium_get_header (CamelMedium *medium, - const gchar *header_name); +void camel_medium_add_header (CamelMedium *medium, const gchar *header_name, const gchar *header_value); +void camel_medium_set_header (CamelMedium *medium, const gchar *header_name, const gchar *header_value); +void camel_medium_remove_header (CamelMedium *medium, const gchar *header_name); +const gchar *camel_medium_get_header (CamelMedium *medium, const gchar *header_name); CamelDataWrapper *camel_medium_get_content_object (CamelMedium *medium); diff --git a/camel/camel-mime-message.c b/camel/camel-mime-message.c index 88a0828973..7ae14766d5 100644 --- a/camel/camel-mime-message.c +++ b/camel/camel-mime-message.c @@ -72,8 +72,10 @@ static GList *_get_flag_list (CamelMimeMessage *mime_message); static void _set_message_number (CamelMimeMessage *mime_message, guint number); static guint _get_message_number (CamelMimeMessage *mime_message); static void _write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream); -static gboolean _parse_header_pair (CamelMimePart *mime_part, gchar *header_name, gchar *header_value); static void _finalize (GtkObject *object); +static void add_header (CamelMedium *medium, const char *header_name, const char *header_value); +static void set_header (CamelMedium *medium, const char *header_name, const char *header_value); +static void remove_header (CamelMedium *medium, const char *header_name); /* Returns the class for a CamelMimeMessage */ #define CMM_CLASS(so) CAMEL_MIME_MESSAGE_CLASS (GTK_OBJECT(so)->klass) @@ -97,8 +99,9 @@ static void camel_mime_message_class_init (CamelMimeMessageClass *camel_mime_message_class) { CamelDataWrapperClass *camel_data_wrapper_class = CAMEL_DATA_WRAPPER_CLASS (camel_mime_message_class); - CamelMimePartClass *camel_mime_part_class = CAMEL_MIME_PART_CLASS (camel_mime_message_class); + /*CamelMimePartClass *camel_mime_part_class = CAMEL_MIME_PART_CLASS (camel_mime_message_class);*/ GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (camel_mime_message_class); + CamelMediumClass *camel_medium_class = CAMEL_MEDIUM_CLASS (camel_mime_message_class); parent_class = gtk_type_class (camel_mime_part_get_type ()); _init_header_name_table(); @@ -130,7 +133,10 @@ camel_mime_message_class_init (CamelMimeMessageClass *camel_mime_message_class) /* virtual method overload */ camel_data_wrapper_class->write_to_stream = _write_to_stream; - camel_mime_part_class->parse_header_pair = _parse_header_pair; + + camel_medium_class->add_header = add_header; + camel_medium_class->set_header = set_header; + camel_medium_class->remove_header = remove_header; gtk_object_class->finalize = _finalize; } @@ -223,7 +229,10 @@ _set_field (CamelMimeMessage *mime_message, gchar *name, const gchar *value, gch { if (variable) { g_free (*variable); - *variable = g_strdup (value); + if (value) + *variable = g_strdup (value); + else + *variable = NULL; } } @@ -579,6 +588,7 @@ _write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) { CamelMimeMessage *mm = CAMEL_MIME_MESSAGE (data_wrapper); +#warning each header should be stored in the raw headers WHPT (stream, "From", mm->from); WHPT (stream, "Reply-To", mm->reply_to); _write_recipients_to_stream (mm, stream); @@ -595,11 +605,13 @@ _write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) /*******************************/ /* mime message header parsing */ +/* FIXME: This is totally totally broken */ static void -_set_recipient_list_from_string (CamelMimeMessage *message, gchar *recipient_type, gchar *recipients_string) +_set_recipient_list_from_string (CamelMimeMessage *message, const char *recipient_type, const char *recipients_string) { GList *recipients_list; +#warning need to parse receipient lists properly - BROKEN!!! recipients_list = string_split ( recipients_string, ',', "\t ", STRING_TRIM_STRIP_TRAILING | STRING_TRIM_STRIP_LEADING); @@ -608,54 +620,69 @@ _set_recipient_list_from_string (CamelMimeMessage *message, gchar *recipient_typ } +/* FIXME: check format of fields. */ static gboolean -_parse_header_pair (CamelMimePart *mime_part, gchar *header_name, gchar *header_value) +process_header(CamelMedium *medium, const char *header_name, const char *header_value) { CamelHeaderType header_type; - CamelMimeMessage *message = CAMEL_MIME_MESSAGE (mime_part); - gboolean header_handled = FALSE; - - + CamelMimeMessage *message = CAMEL_MIME_MESSAGE (medium); + header_type = (CamelHeaderType) g_hash_table_lookup (header_name_table, header_name); switch (header_type) { - case HEADER_FROM: camel_mime_message_set_from (message, header_value); - header_handled = TRUE; break; - case HEADER_REPLY_TO: camel_mime_message_set_reply_to (message, header_value); - header_handled = TRUE; break; - case HEADER_SUBJECT: camel_mime_message_set_subject (message, header_value); - header_handled = TRUE; break; - case HEADER_TO: - _set_recipient_list_from_string (message, "To", header_value); - header_handled = TRUE; + if (header_value) + _set_recipient_list_from_string (message, "To", header_value); + else + camel_recipient_table_remove_type (message->recipients, "To"); break; - case HEADER_CC: - _set_recipient_list_from_string (message, "Cc", header_value); - header_handled = TRUE; + if (header_value) + _set_recipient_list_from_string (message, "Cc", header_value); + else + camel_recipient_table_remove_type (message->recipients, "Cc"); break; - case HEADER_BCC: - _set_recipient_list_from_string (message, "Bcc", header_value); - header_handled = TRUE; + if (header_value) + _set_recipient_list_from_string (message, "Bcc", header_value); + else + camel_recipient_table_remove_type (message->recipients, "Bcc"); break; - - + default: + return FALSE; } - if (header_handled) { - return TRUE; - } else - return parent_class->parse_header_pair (mime_part, header_name, header_value); - - + return TRUE; +} + +static void +set_header(CamelMedium *medium, const char *header_name, const char *header_value) +{ + process_header(medium, header_name, header_value); + parent_class->parent_class.set_header (medium, header_name, header_value); +} + +static void +add_header(CamelMedium *medium, const char *header_name, const char *header_value) +{ + /* if we process it, then it must be forced unique as well ... */ + if (process_header(medium, header_name, header_value)) + parent_class->parent_class.set_header (medium, header_name, header_value); + else + parent_class->parent_class.add_header (medium, header_name, header_value); +} + +static void +remove_header(CamelMedium *medium, const char *header_name) +{ + process_header(medium, header_name, NULL); + parent_class->parent_class.remove_header (medium, header_name); } diff --git a/camel/camel-mime-parser.c b/camel/camel-mime-parser.c index cee6454707..3ed9dde427 100644 --- a/camel/camel-mime-parser.c +++ b/camel/camel-mime-parser.c @@ -613,6 +613,8 @@ retry: goto header_done; } + if (s->outptr[0] == '\n' && s->outptr>s->outbuf) + s->outptr--; s->outptr[0] = 0; d(printf("header %.10s at %d\n", s->outbuf, s->header_start)); @@ -674,6 +676,8 @@ header_truncated: memcpy(s->outptr, start, headerlen); s->outptr += headerlen; } + if (s->outptr[0] == '\n' && s->outptr>s->outbuf) + s->outptr--; s->outptr[0] = 0; if (s->header_start == -1) diff --git a/camel/camel-mime-part.c b/camel/camel-mime-part.c index 67be67d248..bda4f932ed 100644 --- a/camel/camel-mime-part.c +++ b/camel/camel-mime-part.c @@ -1,11 +1,9 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* camelMimePart.c : Abstract class for a mime_part */ - /* - * - * Author : - * Bertrand Guiheneuf + * Authors: Bertrand Guiheneuf + * Michael Zucchi * * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com) * @@ -25,9 +23,6 @@ * USA */ - - - #include #include #include "camel-mime-part.h" @@ -42,7 +37,7 @@ #include "camel-seekable-substream.h" #include "camel-stream-filter.h" #include "camel-mime-filter-basic.h" - +#include typedef enum { HEADER_UNKNOWN, @@ -64,6 +59,7 @@ static CamelMediumClass *parent_class=NULL; /* Returns the class for a CamelMimePart */ #define CMP_CLASS(so) CAMEL_MIME_PART_CLASS (GTK_OBJECT(so)->klass) #define CDW_CLASS(so) CAMEL_DATA_WRAPPER_CLASS (GTK_OBJECT(so)->klass) +#define CMD_CLASS(so) CAMEL_MEDIUM_CLASS (GTK_OBJECT(so)->klass) /* from GtkObject */ static void my_finalize (GtkObject *object); @@ -79,49 +75,16 @@ static CamelStream * my_get_output_stream (CamelDataWrapper *data_w /* from CamelMedia */ -static void my_add_header (CamelMedium *medium, - gchar *header_name, - gchar *header_value); +static void add_header (CamelMedium *medium, const char *header_name, const char *header_value); +static void set_header (CamelMedium *medium, const char *header_name, const char *header_value); +static void remove_header (CamelMedium *medium, const char *header_name); static void my_set_content_object (CamelMedium *medium, CamelDataWrapper *content); static CamelDataWrapper *my_get_content_object (CamelMedium *medium); - - -/* from CamelMimePart */ -static void my_set_description (CamelMimePart *mime_part, - const gchar *description); -static const gchar * my_get_description (CamelMimePart *mime_part); -static void my_set_disposition (CamelMimePart *mime_part, - const gchar *disposition); -static const gchar * my_get_disposition (CamelMimePart *mime_part); -static void my_set_filename (CamelMimePart *mime_part, - gchar *filename); -static const gchar * my_get_filename (CamelMimePart *mime_part); -static void my_set_content_id (CamelMimePart *mime_part, - gchar *content_id); -static const gchar * my_get_content_id (CamelMimePart *mime_part); -static void my_set_content_MD5 (CamelMimePart *mime_part, - gchar *content_MD5); -static const gchar * my_get_content_MD5 (CamelMimePart *mime_part); -static void my_set_encoding (CamelMimePart *mime_part, - CamelMimePartEncodingType encoding); -static CamelMimePartEncodingType my_get_encoding (CamelMimePart *mime_part); -static void my_set_content_languages (CamelMimePart *mime_part, - GList *content_languages); -static const GList * my_get_content_languages (CamelMimePart *mime_part); -static void my_set_header_lines (CamelMimePart *mime_part, - GList *header_lines); -static const GList * my_get_header_lines (CamelMimePart *mime_part); -static void my_set_content_type (CamelMimePart *mime_part, - const gchar *content_type); -static GMimeContentField *my_get_content_type (CamelMimePart *mime_part); - -static gboolean my_parse_header_pair (CamelMimePart *mime_part, - gchar *header_name, - gchar *header_value); - +/* forward references */ +static void set_disposition (CamelMimePart *mime_part, const gchar *disposition); /* loads in a hash table the set of header names we */ @@ -150,30 +113,10 @@ camel_mime_part_class_init (CamelMimePartClass *camel_mime_part_class) parent_class = gtk_type_class (camel_medium_get_type ()); my_init_header_name_table(); - /* virtual method definition */ - camel_mime_part_class->set_description = my_set_description; - camel_mime_part_class->get_description = my_get_description; - camel_mime_part_class->set_disposition = my_set_disposition; - camel_mime_part_class->get_disposition = my_get_disposition; - camel_mime_part_class->set_filename = my_set_filename; - camel_mime_part_class->get_filename = my_get_filename; - camel_mime_part_class->set_content_id = my_set_content_id; - camel_mime_part_class->get_content_id = my_get_content_id; - camel_mime_part_class->set_content_MD5 = my_set_content_MD5; - camel_mime_part_class->get_content_MD5 = my_get_content_MD5; - camel_mime_part_class->set_encoding = my_set_encoding; - camel_mime_part_class->get_encoding = my_get_encoding; - camel_mime_part_class->set_content_languages = my_set_content_languages; - camel_mime_part_class->get_content_languages = my_get_content_languages; - camel_mime_part_class->set_header_lines = my_set_header_lines; - camel_mime_part_class->get_header_lines = my_get_header_lines; - camel_mime_part_class->set_content_type = my_set_content_type; - camel_mime_part_class->get_content_type = my_get_content_type; - - camel_mime_part_class->parse_header_pair = my_parse_header_pair; - /* virtual method overload */ - camel_medium_class->add_header = my_add_header; + camel_medium_class->add_header = add_header; + camel_medium_class->set_header = set_header; + camel_medium_class->remove_header = remove_header; camel_medium_class->set_content_object = my_set_content_object; camel_medium_class->get_content_object = my_get_content_object; @@ -197,8 +140,6 @@ camel_mime_part_init (gpointer object, gpointer klass) camel_mime_part->content_MD5 = NULL; camel_mime_part->content_languages = NULL; camel_mime_part->encoding = CAMEL_MIME_PART_ENCODING_DEFAULT; - camel_mime_part->filename = NULL; - camel_mime_part->header_lines = NULL; camel_mime_part->temp_message_buffer = NULL; camel_mime_part->content_input_stream = NULL; @@ -241,9 +182,7 @@ my_finalize (GtkObject *object) g_free (mime_part->content_id); g_free (mime_part->content_MD5); string_list_free (mime_part->content_languages); - g_free (mime_part->filename); header_disposition_unref(mime_part->disposition); - if (mime_part->header_lines) string_list_free (mime_part->header_lines); if (mime_part->content_type) gmime_content_field_unref (mime_part->content_type); if (mime_part->temp_message_buffer) g_byte_array_free (mime_part->temp_message_buffer, TRUE); @@ -253,323 +192,277 @@ my_finalize (GtkObject *object) GTK_OBJECT_CLASS (parent_class)->finalize (object); } - /* **** */ -static void -my_add_header (CamelMedium *medium, gchar *header_name, gchar *header_value) +static gboolean +process_header(CamelMedium *medium, const char *header_name, const char *header_value) { CamelMimePart *mime_part = CAMEL_MIME_PART (medium); - + CamelHeaderType header_type; + char *text; + /* Try to parse the header pair. If it corresponds to something */ /* known, the job is done in the parsing routine. If not, */ /* we simply add the header in a raw fashion */ - if (! CMP_CLASS(mime_part)->parse_header_pair (mime_part, header_name, header_value) ) - parent_class->add_header (medium, header_name, header_value); + + /* FIXMME: MUST check fields for validity before adding them! */ + + header_type = (CamelHeaderType) g_hash_table_lookup (header_name_table, header_name); + switch (header_type) { + case HEADER_DESCRIPTION: /* raw header->utf8 conversion */ + text = header_decode_string(header_value); + g_free(mime_part->description); + mime_part->description = text; + break; + case HEADER_DISPOSITION: + set_disposition (mime_part, header_value); + break; + case HEADER_CONTENT_ID: + text = header_msgid_decode(header_value); + g_free(mime_part->content_id); + mime_part->content_id = text; + break; + case HEADER_ENCODING: + text = header_token_decode(header_value); + camel_mime_part_set_encoding(mime_part, camel_mime_part_encoding_from_string (text)); + g_free(text); + break; + case HEADER_CONTENT_MD5: + g_free(mime_part->content_MD5); + mime_part->content_MD5 = g_strdup(header_value); + break; + case HEADER_CONTENT_TYPE: + gmime_content_field_construct_from_string (mime_part->content_type, header_value); + break; + default: + return FALSE; + } + return TRUE; } +static void +set_header (CamelMedium *medium, const char *header_name, const char *header_value) +{ + process_header(medium, header_name, header_value); + parent_class->set_header (medium, header_name, header_value); +} +static void +add_header (CamelMedium *medium, const char *header_name, const char *header_value) +{ + /* Try to parse the header pair. If it corresponds to something */ + /* known, the job is done in the parsing routine. If not, */ + /* we simply add the header in a raw fashion */ + /* FIXMME: MUST check fields for validity before adding them! */ + /* If it was one of the headers we handled, it must be unique, set it instead of add */ + if (process_header(medium, header_name, header_value)) + parent_class->set_header (medium, header_name, header_value); + else + parent_class->add_header (medium, header_name, header_value); +} static void -my_set_description (CamelMimePart *mime_part, const gchar *description) +remove_header (CamelMedium *medium, const char *header_name) { - g_free (mime_part->description); - mime_part->description = g_strdup (description); + process_header(medium, header_name, NULL); + parent_class->remove_header (medium, header_name); } + +/* **** Content-Description */ void camel_mime_part_set_description (CamelMimePart *mime_part, const gchar *description) { - CMP_CLASS(mime_part)->set_description (mime_part, description); -} - - - -/* **** */ + char *text; + /* FIXME: convert header, internationalise, etc. */ + text = g_strdup(description); + /* text = header_encode_string(description); */ + g_free(mime_part->description); + mime_part->description = text; -static const gchar * -my_get_description (CamelMimePart *mime_part) -{ - return mime_part->description; + parent_class->set_header ((CamelMedium *)mime_part, "Content-Description", text); } const gchar * camel_mime_part_get_description (CamelMimePart *mime_part) { - return CMP_CLASS(mime_part)->get_description (mime_part); + return mime_part->description; } - - -/* **** */ - +/* **** Content-Disposition */ static void -my_set_disposition (CamelMimePart *mime_part, const gchar *disposition) +set_disposition (CamelMimePart *mime_part, const gchar *disposition) { header_disposition_unref(mime_part->disposition); - mime_part->disposition = header_disposition_decode(disposition); + if (disposition) + mime_part->disposition = header_disposition_decode(disposition); + else + mime_part->disposition = NULL; } void camel_mime_part_set_disposition (CamelMimePart *mime_part, const gchar *disposition) { - CMP_CLASS(mime_part)->set_disposition (mime_part, disposition); -} - - -/* **** */ + char *text; + /* we poke in a new disposition (so we dont lose 'filename', etc) */ + if (mime_part->disposition == NULL) { + set_disposition(mime_part, disposition); + } + if (mime_part->disposition != NULL) { + g_free(mime_part->disposition->disposition); + mime_part->disposition->disposition = g_strdup(disposition); + } + text = header_disposition_format(mime_part->disposition); + parent_class->set_header ((CamelMedium *)mime_part, "Content-Description", text); -static const gchar * -my_get_disposition (CamelMimePart *mime_part) -{ - if (!mime_part->disposition) return NULL; - return (mime_part->disposition)->disposition; + g_free(text); } - const gchar * camel_mime_part_get_disposition (CamelMimePart *mime_part) { - return CMP_CLASS(mime_part)->get_disposition (mime_part); + if (mime_part->disposition) + return (mime_part->disposition)->disposition; + else + return NULL; } - -static void -my_set_filename (CamelMimePart *mime_part, gchar *filename) -{ - g_free(mime_part->filename); - mime_part->filename = filename; -} - +/* **** Content-Disposition: filename="xxx" */ void camel_mime_part_set_filename (CamelMimePart *mime_part, gchar *filename) { - CMP_CLASS(mime_part)->set_filename (mime_part, filename); -} - + char *str; + if (mime_part->disposition == NULL) + mime_part->disposition = header_disposition_decode("attachment"); + header_set_param(&mime_part->disposition->params, "filename", filename); + str = header_disposition_format(mime_part->disposition); -/* **** */ - - -static const gchar * -my_get_filename (CamelMimePart *mime_part) -{ - return mime_part->filename; + /* we dont want to override what we just created ... */ + parent_class->set_header ((CamelMedium *)mime_part, "Content-Disposition", str); + g_free(str); } - const gchar * camel_mime_part_get_filename (CamelMimePart *mime_part) { - return CMP_CLASS(mime_part)->get_filename (mime_part); + if (mime_part->disposition) + return header_param(mime_part->disposition->params, "filename"); + return NULL; } -/* **** */ - +/* **** Content-ID: */ -/* this routine must not be public */ -static void -my_set_content_id (CamelMimePart *mime_part, gchar *content_id) +void +camel_mime_part_set_content_id (CamelMimePart *mime_part, const char *contentid) { - g_free(mime_part->content_id); - mime_part->content_id = g_strdup(content_id); -} + char *text; - -static const gchar * -my_get_content_id (CamelMimePart *mime_part) -{ - return mime_part->content_id; + /* perform a syntax check, just 'cause we can */ + text = header_msgid_decode(contentid); + if (text == NULL) { + g_warning("Invalid content id being set: '%s'", contentid); + } else { + g_free(text); + } + g_free(mime_part->content_id); + mime_part->content_id = g_strdup(contentid); + parent_class->set_header ((CamelMedium *)mime_part, "Content-ID", contentid); } - -/* **** */ - - const gchar * camel_mime_part_get_content_id (CamelMimePart *mime_part) { - return CMP_CLASS(mime_part)->get_content_id (mime_part); + return mime_part->content_id; } +/* **** Content-MD5: */ -/* this routine must not be public */ -static void -my_set_content_MD5 (CamelMimePart *mime_part, gchar *content_MD5) +void +camel_mime_part_set_content_MD5 (CamelMimePart *mime_part, const char *md5) { g_free(mime_part->content_MD5); - mime_part->content_MD5 = content_MD5; -} - - -/* **** */ - - -static const gchar * -my_get_content_MD5 (CamelMimePart *mime_part) -{ - return mime_part->content_MD5; + mime_part->content_MD5 = g_strdup(md5); + parent_class->set_header ((CamelMedium *)mime_part, "Content-MD5", md5); } const gchar * camel_mime_part_get_content_MD5 (CamelMimePart *mime_part) { - return CMP_CLASS(mime_part)->get_content_MD5 (mime_part); + return mime_part->content_MD5; } - -/* **** */ - - - -static void -my_set_encoding (CamelMimePart *mime_part, CamelMimePartEncodingType encoding) -{ - mime_part->encoding = encoding; -} +/* **** Content-Transfer-Encoding: */ void camel_mime_part_set_encoding (CamelMimePart *mime_part, CamelMimePartEncodingType encoding) { - CMP_CLASS(mime_part)->set_encoding (mime_part, encoding); -} - - -/* **** */ - + const char *text; + mime_part->encoding = encoding; + text = camel_mime_part_encoding_to_string (encoding); + if (text[0]) + text = g_strdup(text); + else + text = NULL; -static CamelMimePartEncodingType -my_get_encoding (CamelMimePart *mime_part) -{ - return mime_part->encoding; + parent_class->set_header ((CamelMedium *)mime_part, "Content-Transfer-Encoding", text); } const CamelMimePartEncodingType camel_mime_part_get_encoding (CamelMimePart *mime_part) { - return CMP_CLASS(mime_part)->get_encoding (mime_part); + return mime_part->encoding; } - - -/* **** */ - - - -static void -my_set_content_languages (CamelMimePart *mime_part, GList *content_languages) -{ - if (mime_part->content_languages) string_list_free (mime_part->content_languages); - mime_part->content_languages = content_languages; -} +/* FIXME: do something with this stuff ... */ void camel_mime_part_set_content_languages (CamelMimePart *mime_part, GList *content_languages) { - CMP_CLASS(mime_part)->set_content_languages (mime_part, content_languages); -} - - -/* **** */ - - + if (mime_part->content_languages) string_list_free (mime_part->content_languages); + mime_part->content_languages = content_languages; -static const GList * -my_get_content_languages (CamelMimePart *mime_part) -{ - return mime_part->content_languages; + /* FIXME: translate to a header and set it */ } - const GList * camel_mime_part_get_content_languages (CamelMimePart *mime_part) { - return CMP_CLASS(mime_part)->get_content_languages (mime_part); -} - - -/* **** */ - - - -static void -my_set_header_lines (CamelMimePart *mime_part, GList *header_lines) -{ - if (mime_part->header_lines) string_list_free (mime_part->header_lines); - mime_part->header_lines = header_lines; -} - -void -camel_mime_part_set_header_lines (CamelMimePart *mime_part, GList *header_lines) -{ - CMP_CLASS(mime_part)->set_header_lines (mime_part, header_lines); -} - - -/* **** */ - - - -static const GList * -my_get_header_lines (CamelMimePart *mime_part) -{ - return mime_part->header_lines; -} - - - -const GList * -camel_mime_part_get_header_lines (CamelMimePart *mime_part) -{ - return CMP_CLASS(mime_part)->get_header_lines (mime_part); + return mime_part->content_languages; } /* **** */ - - -static void -my_set_content_type (CamelMimePart *mime_part, const gchar *content_type) -{ - g_assert (content_type); - gmime_content_field_construct_from_string (mime_part->content_type, content_type); -} +/* **** Content-Type: */ void camel_mime_part_set_content_type (CamelMimePart *mime_part, gchar *content_type) { - CMP_CLASS(mime_part)->set_content_type (mime_part, content_type); -} - -/* **** */ - - -static GMimeContentField * -my_get_content_type (CamelMimePart *mime_part) -{ - return mime_part->content_type; + /* FIXME: need a way to specify content-type parameters without putting them + in a string ... */ + gmime_content_field_construct_from_string (mime_part->content_type, content_type); + parent_class->set_header ((CamelMedium *)mime_part, "Content-Type", content_type); } GMimeContentField * camel_mime_part_get_content_type (CamelMimePart *mime_part) { - return CMP_CLASS(mime_part)->get_content_type (mime_part); + return mime_part->content_type; } /*********/ @@ -585,9 +478,15 @@ my_set_content_object (CamelMedium *medium, CamelDataWrapper *content) parent_class->set_content_object (medium, content); object_content_field = camel_data_wrapper_get_mime_type_field (content); - if (mime_part->content_type && (mime_part->content_type != object_content_field)) + if (mime_part->content_type && (mime_part->content_type != object_content_field)) { + char *txt; + gmime_content_field_unref (mime_part->content_type); + txt = header_content_type_format(object_content_field?object_content_field->content_type:NULL); + parent_class->set_header ((CamelMedium *)mime_part, "Content-Type", txt); + } mime_part->content_type = object_content_field; + gmime_content_field_ref (object_content_field); } @@ -604,19 +503,14 @@ my_get_content_object (CamelMedium *medium) decoded_stream = stream; switch (mime_part->encoding) { - - case CAMEL_MIME_PART_ENCODING_DEFAULT: - case CAMEL_MIME_PART_ENCODING_7BIT: - case CAMEL_MIME_PART_ENCODING_8BIT: - break; - case CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE: mf = (CamelMimeFilter *)camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_QP_DEC); break; - case CAMEL_MIME_PART_ENCODING_BASE64: mf = (CamelMimeFilter *)camel_mime_filter_basic_new_type(CAMEL_MIME_FILTER_BASIC_BASE64_DEC); break; + default: + break; } if (mf) { @@ -689,7 +583,7 @@ my_write_content_to_stream (CamelMimePart *mime_part, CamelStream *stream) /* encode the data wrapper output stream in the filtered encoding */ wrapper_stream = camel_data_wrapper_get_output_stream (content); camel_stream_reset (wrapper_stream); - stream_encode = camel_stream_filter_new_with_stream (wrapper_stream); + stream_encode = (CamelStream *)camel_stream_filter_new_with_stream (wrapper_stream); camel_stream_filter_add((CamelStreamFilter *)stream_encode, mf); /* ... and write it to the output stream in a blocking way */ @@ -704,6 +598,7 @@ my_write_content_to_stream (CamelMimePart *mime_part, CamelStream *stream) +/* FIXME: this is just totally broken broken broken broken */ static void my_write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) @@ -711,91 +606,24 @@ my_write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) CamelMimePart *mp = CAMEL_MIME_PART (data_wrapper); CamelMedium *medium = CAMEL_MEDIUM (data_wrapper); - if (mp->disposition) { - struct _header_param *p; + /* FIXME: something needs to be done about this ... */ + gmime_write_header_with_glist_to_stream (stream, "Content-Language", mp->content_languages,", "); - camel_stream_write_strings(stream, "Content-Disposition: ", mp->disposition->disposition, NULL); - /* FIXME: use proper quoting rules here ... */ - p = mp->disposition->params; - while (p) { - camel_stream_write_strings (stream, ";\n ", p->name, "= \"", p->value, "\"", NULL); - p = p->next; +#warning This class should NOT BE WRITING the headers out + if (medium->headers) { + struct _header_raw *h = medium->headers; + while (h) { + camel_stream_write_strings (stream, h->name, isspace(h->value[0])?":":": ", h->value, "\n", NULL); + h = h->next; } - camel_stream_write_string (stream, "\n"); } - WHPT (stream, "Content-Transfer-Encoding", - camel_mime_part_encoding_to_string (mp->encoding)); - WHPT (stream, "Content-Description", mp->description); - WHPT (stream, "Content-MD5", mp->content_MD5); - WHPT (stream, "Content-id", mp->content_id); - gmime_write_header_with_glist_to_stream (stream, "Content-Language", mp->content_languages,", "); - gmime_write_header_table_to_stream (stream, medium->headers); - gmime_content_field_write_to_stream (mp->content_type, stream); - + camel_stream_write_string(stream,"\n"); my_write_content_to_stream (mp, stream); } -/*******************************/ -/* mime part parsing */ - -static gboolean -my_parse_header_pair (CamelMimePart *mime_part, gchar *header_name, gchar *header_value) -{ - CamelHeaderType header_type; - gboolean header_handled = FALSE; - - - header_type = (CamelHeaderType) g_hash_table_lookup (header_name_table, header_name); - switch (header_type) { - - case HEADER_DESCRIPTION: - camel_mime_part_set_description (mime_part, header_value); - header_handled = TRUE; - break; - - case HEADER_DISPOSITION: - camel_mime_part_set_disposition (mime_part, header_value); - header_handled = TRUE; - break; - - case HEADER_CONTENT_ID: - CMP_CLASS(mime_part)->set_content_id (mime_part, header_value); - header_handled = TRUE; - break; - - case HEADER_ENCODING: - camel_mime_part_set_encoding - (mime_part, - camel_mime_part_encoding_from_string (header_value)); - header_handled = TRUE; - break; - - case HEADER_CONTENT_MD5: - CMP_CLASS(mime_part)->set_content_MD5 (mime_part, header_value); - header_handled = TRUE; - break; - - case HEADER_CONTENT_TYPE: - gmime_content_field_construct_from_string (mime_part->content_type, header_value); - header_handled = TRUE; - break; - - - } - - - if (header_handled) { - return TRUE; - } else return FALSE; - -} - - - - static void my_construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) { @@ -871,6 +699,8 @@ my_get_output_stream (CamelDataWrapper *data_wrapper) case CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE: return input_stream; + default: + break; } return NULL; @@ -890,6 +720,8 @@ camel_mime_part_encoding_to_string (CamelMimePartEncodingType encoding) return "base64"; case CAMEL_MIME_PART_ENCODING_QUOTEDPRINTABLE: return "quoted-printable"; + default: + break; } return ""; } @@ -900,7 +732,9 @@ camel_mime_part_encoding_to_string (CamelMimePartEncodingType encoding) CamelMimePartEncodingType camel_mime_part_encoding_from_string (const gchar *string) { - if (strcmp (string, "7bit") == 0) + if (string == NULL) + return CAMEL_MIME_PART_ENCODING_DEFAULT; + else if (strcmp (string, "7bit") == 0) return CAMEL_MIME_PART_ENCODING_7BIT; else if (strcmp (string, "8bit") == 0) return CAMEL_MIME_PART_ENCODING_8BIT; diff --git a/camel/camel-mime-part.h b/camel/camel-mime-part.h index 37118c8384..89409dab5f 100644 --- a/camel/camel-mime-part.h +++ b/camel/camel-mime-part.h @@ -69,8 +69,6 @@ struct _CamelMimePart gchar *content_MD5; GList *content_languages; CamelMimePartEncodingType encoding; - gchar *filename; - GList *header_lines; GByteArray *temp_message_buffer; GMimeContentField *content_type; @@ -84,29 +82,6 @@ typedef struct { CamelMediumClass parent_class; /* Virtual methods */ - void (*set_description) (CamelMimePart *mime_part, const gchar *description); - const gchar * (*get_description) (CamelMimePart *mime_part); - void (*set_disposition) (CamelMimePart *mime_part, const gchar *disposition); - const gchar * (*get_disposition) (CamelMimePart *mime_part); - void (*set_filename) (CamelMimePart *mime_part, gchar *filename); - const gchar * (*get_filename) (CamelMimePart *mime_part); - void (*set_content_id) (CamelMimePart *mime_part, gchar *content_id); - const gchar * (*get_content_id) (CamelMimePart *mime_part); - void (*set_content_MD5) (CamelMimePart *mime_part, gchar *content_MD5); - const gchar * (*get_content_MD5) (CamelMimePart *mime_part); - void (*set_encoding) (CamelMimePart *mime_part, CamelMimePartEncodingType type); - const CamelMimePartEncodingType (*get_encoding) (CamelMimePart *mime_part); - void (*set_content_languages) (CamelMimePart *mime_part, GList *content_languages); - const GList * (*get_content_languages) (CamelMimePart *mime_part); - void (*set_header_lines) (CamelMimePart *mime_part, GList *header_lines); - const GList * (*get_header_lines) (CamelMimePart *mime_part); - - void (*set_content_type) (CamelMimePart *mime_part, const gchar *content_type); - GMimeContentField * (*get_content_type) (CamelMimePart *mime_part); - - gboolean (*parse_header_pair) (CamelMimePart *mime_part, gchar *header_name, gchar *header_value); - - } CamelMimePartClass; @@ -116,30 +91,32 @@ GtkType camel_mime_part_get_type (void); /* public methods */ -void camel_mime_part_set_description (CamelMimePart *mime_part, - const gchar *description); +void camel_mime_part_set_description (CamelMimePart *mime_part, const gchar *description); const gchar *camel_mime_part_get_description (CamelMimePart *mime_part); -void camel_mime_part_set_disposition (CamelMimePart *mime_part, - const gchar *disposition); + +void camel_mime_part_set_disposition (CamelMimePart *mime_part, const gchar *disposition); const gchar *camel_mime_part_get_disposition (CamelMimePart *mime_part); -void camel_mime_part_set_filename (CamelMimePart *mime_part, - gchar *filename); + +void camel_mime_part_set_filename (CamelMimePart *mime_part, gchar *filename); const gchar *camel_mime_part_get_filename (CamelMimePart *mime_part); + +void camel_mime_part_set_content_id (CamelMimePart *mime_part, const char *contentid); const gchar *camel_mime_part_get_content_id (CamelMimePart *mime_part); + +void camel_mime_part_set_content_MD5 (CamelMimePart *mime_part, const char *); const gchar *camel_mime_part_get_content_MD5 (CamelMimePart *mime_part); -void camel_mime_part_set_encoding (CamelMimePart *mime_part, - CamelMimePartEncodingType type); + +void camel_mime_part_set_encoding (CamelMimePart *mime_part, CamelMimePartEncodingType type); CamelMimePartEncodingType camel_mime_part_get_encoding (CamelMimePart *mime_part); -void camel_mime_part_set_content_languages (CamelMimePart *mime_part, - GList *content_languages); + +void camel_mime_part_set_content_languages (CamelMimePart *mime_part, GList *content_languages); const GList *camel_mime_part_get_content_languages (CamelMimePart *mime_part); -void camel_mime_part_set_header_lines (CamelMimePart *mime_part, - GList *header_lines); -const GList *camel_mime_part_get_header_lines (CamelMimePart *mime_part); +/* FIXME: what about content-type parameters? what about major/minor parts? */ +void camel_mime_part_set_content_type (CamelMimePart *mime_part, gchar *content_type); GMimeContentField *camel_mime_part_get_content_type (CamelMimePart *mime_part); -const gchar *camel_mime_part_encoding_to_string (CamelMimePartEncodingType encoding); +const gchar * camel_mime_part_encoding_to_string (CamelMimePartEncodingType encoding); CamelMimePartEncodingType camel_mime_part_encoding_from_string (const gchar *string); /* utility functions */ diff --git a/camel/camel-mime-utils.c b/camel/camel-mime-utils.c index 94ede343e6..7b1ad93cd0 100644 --- a/camel/camel-mime-utils.c +++ b/camel/camel-mime-utils.c @@ -542,11 +542,13 @@ quoted_decode_step(unsigned char *in, int len, unsigned char *out, int *savestat this is for the "Q" encoding of international words, which is slightly different than plain quoted-printable */ -int -quoted_decode(unsigned char *in, int len, unsigned char *out) +static int +quoted_decode(const unsigned char *in, int len, unsigned char *out) { - register unsigned char *inptr, *outptr; - unsigned char *inend, c, c1; + register const unsigned char *inptr; + register unsigned char *outptr; + unsigned const char *inend; + unsigned char c, c1; int ret = 0; inend = in+len; @@ -619,22 +621,12 @@ header_decode_lwsp(const char **in) *in = inptr; } -char * -g_strdup_len(const char *start, int len) -{ - char *d = g_malloc(len+1); - memcpy(d, start, len); - d[len] = 0; - return d; -} - - /* decode rfc 2047 encoded string segment */ -char * -rfc2047_decode_word(char *in, int len) +static char * +rfc2047_decode_word(const char *in, int len) { - char *inptr = in+2; - char *inend = in+len-2; + const char *inptr = in+2; + const char *inend = in+len-2; char *encname; int tmplen; int ret; @@ -668,7 +660,7 @@ rfc2047_decode_word(char *in, int len) case 'B': { int state=0; unsigned int save=0; - inlen = base64_decode_step(inptr+2, tmplen, decword, &state, &save); + inlen = base64_decode_step((char *)inptr+2, tmplen, decword, &state, &save); /* if state != 0 then error? */ break; } @@ -704,15 +696,9 @@ rfc2047_decode_word(char *in, int len) return decoded; } -char * -decode_coded_string(char *in) -{ - return rfc2047_decode_word(in, strlen(in)); -} - /* grrr, glib should have this ! */ -GString * -g_string_append_len(GString *st, char *s, int l) +static GString * +g_string_append_len(GString *st, const char *s, int l) { char *tmp; @@ -723,12 +709,12 @@ g_string_append_len(GString *st, char *s, int l) } /* decodes a simple text, rfc822 */ -char * -header_decode_text(char *in, int inlen) +static char * +header_decode_text(const char *in, int inlen) { GString *out; - char *inptr = in; - char *inend = in+inlen; + const char *inptr = in; + const char *inend = in+inlen; char *encstart, *encend; char *decword; @@ -748,9 +734,9 @@ header_decode_text(char *in, int inlen) } g_string_append_len(out, inptr, inend-inptr); - inptr = out->str; + encstart = out->str; g_string_free(out, FALSE); - return inptr; + return encstart; } char * @@ -764,8 +750,8 @@ header_decode_string(const char *in) /* these are all internal parser functions */ -char * -header_decode_token(const char **in) +static char * +decode_token(const char **in) { const char *inptr = *in; const char *start; @@ -776,12 +762,21 @@ header_decode_token(const char **in) inptr++; if (inptr>start) { *in = inptr; - return g_strdup_len(start, inptr-start); + return g_strndup(start, inptr-start); } else { return NULL; } } +char * +header_token_decode(const char *in) +{ + if (in == NULL) + return NULL; + + return decode_token(&in); +} + /* <"> * ( \, cr / \ ) <"> */ @@ -832,7 +827,7 @@ header_decode_atom(const char **in) inptr++; *in = inptr; if (inptr > start) - return g_strdup_len(start, inptr-start); + return g_strndup(start, inptr-start); else return NULL; } @@ -864,7 +859,7 @@ header_decode_value(const char **in) } else if (is_ttoken(*inptr)) { d(printf("decoding token\n")); /* this may not have the right specials for all params? */ - return header_decode_token(in); + return decode_token(in); } return NULL; } @@ -891,7 +886,7 @@ header_decode_param(const char **in, char **paramp, char **valuep) const char *inptr = *in; char *param, *value=NULL; - param = header_decode_token(&inptr); + param = decode_token(&inptr); header_decode_lwsp(&inptr); if (*inptr == '=') { inptr++; @@ -911,7 +906,7 @@ header_decode_param(const char **in, char **paramp, char **valuep) } char * -header_param(struct _header_param *p, char *name) +header_param(struct _header_param *p, const char *name) { while (p && strcasecmp(p->name, name) != 0) p = p->next; @@ -929,12 +924,21 @@ header_set_param(struct _header_param **l, const char *name, const char *value) pn = p->next; if (!strcasecmp(pn->name, name)) { g_free(pn->value); - pn->value = g_strdup(value); - return pn; + if (value) { + pn->value = g_strdup(value); + return pn; + } else { + p->next = pn->next; + g_free(pn); + return NULL; + } } p = pn; } + if (value == NULL) + return NULL; + pn = g_malloc(sizeof(*pn)); pn->next = 0; pn->name = g_strdup(name); @@ -972,6 +976,8 @@ void header_content_type_set_param(struct _header_content_type *t, const char *n int header_content_type_is(struct _header_content_type *ct, const char *type, const char *subtype) { + printf("type = %s / %s\n", type, subtype); + /* no type == text/plain or text/"*" */ if (ct==NULL) { return (!strcasecmp(type, "text") @@ -979,9 +985,11 @@ header_content_type_is(struct _header_content_type *ct, const char *type, const || !strcasecmp(subtype, "*"))); } - return ((!strcasecmp(ct->type, type) - && (!strcasecmp(ct->subtype, subtype) - || !strcasecmp("*", subtype)))); + return (ct->type != NULL + && (!strcasecmp(ct->type, type) + && ((ct->subtype != NULL + && !strcasecmp(ct->subtype, subtype)) + || !strcasecmp("*", subtype)))); } void @@ -1003,8 +1011,8 @@ header_content_type_new(const char *type, const char *subtype) { struct _header_content_type *t = g_malloc(sizeof(*t)); - t->type = type; - t->subtype = subtype; + t->type = g_strdup(type); + t->subtype = g_strdup(subtype); t->params = NULL; t->refcount = 1; return t; @@ -1332,6 +1340,8 @@ header_to_decode(const char *in) d(printf("decoding To: '%s'\n", in)); +#warning header_to_decode needs to return some structure + if (in == NULL) return NULL; @@ -1362,6 +1372,8 @@ header_mime_decode(const char *in) d(printf("decoding MIME-Version: '%s'\n", in)); +#warning header_mime_decode needs to return the version + if (in == NULL) return NULL; @@ -1380,7 +1392,7 @@ header_mime_decode(const char *in) d(printf("major = %d, minor = %d\n", major, minor)); } -struct _header_param * +static struct _header_param * header_param_list_decode(const char **in) { const char *inptr = *in; @@ -1411,6 +1423,23 @@ header_param_list_decode(const char **in) return head; } +static void +header_param_list_format_append(GString *out, struct _header_param *p) +{ + int len = out->len; + while (p) { + int here = out->len; + if (len+strlen(p->name)+strlen(p->value)>60) { + g_string_append(out, "\n\t"); + len = 0; + } + /* FIXME: format the value properly */ + g_string_sprintfa(out, " ; %s=\"%s\"", p->name, p->value); + len += (out->len - here); + p = p->next; + } +} + struct _header_content_type * header_content_type_decode(const char *in) { @@ -1421,12 +1450,12 @@ header_content_type_decode(const char *in) if (in==NULL) return NULL; - type = header_decode_token(&inptr); + type = decode_token(&inptr); header_decode_lwsp(&inptr); if (type) { if (*inptr == '/') { inptr++; - subtype = header_decode_token(&inptr); + subtype = decode_token(&inptr); } if (subtype == NULL && (!strcasecmp(type, "text"))) { g_warning("text type with no subtype, resorting to text/plain: %s", in); @@ -1466,11 +1495,40 @@ header_content_type_dump(struct _header_content_type *ct) printf("\n"); } +char * +header_content_type_format(struct _header_content_type *ct) +{ + GString *out; + char *ret; + + if (ct==NULL) + return NULL; + + out = g_string_new(""); + if (ct->type == NULL) { + g_string_sprintfa(out, "text/plain"); + g_warning("Content-Type with no main type"); + } else if (ct->subtype == NULL) { + g_warning("Content-Type with no sub type: %s", ct->type); + if (!strcasecmp(ct->type, "multipart")) + g_string_sprintfa(out, "%s/mixed", ct->type); + else + g_string_sprintfa(out, "%s", ct->type); + } else { + g_string_sprintfa(out, "%s/%s", ct->type, ct->subtype); + } + header_param_list_format_append(out, ct->params); + + ret = out->str; + g_string_free(out, FALSE); + return ret; +} + char * header_content_encoding_decode(const char *in) { if (in) - return header_decode_token(&in); + return decode_token(&in); return NULL; } @@ -1484,7 +1542,7 @@ CamelMimeDisposition *header_disposition_decode(const char *in) d = g_malloc(sizeof(*d)); d->refcount = 1; - d->disposition = header_decode_token(&inptr); + d->disposition = decode_token(&inptr); if (d->disposition == NULL) g_warning("Empty disposition type"); d->params = header_param_list_decode(&inptr); @@ -1509,6 +1567,26 @@ void header_disposition_unref(CamelMimeDisposition *d) } } +char *header_disposition_format(CamelMimeDisposition *d) +{ + GString *out; + char *ret; + + if (d==NULL) + return NULL; + + out = g_string_new(""); + if (d->disposition) + g_string_append(out, d->disposition); + else + g_string_append(out, "attachment"); + header_param_list_format_append(out, d->params); + + ret = out->str; + g_string_free(out, FALSE); + return ret; +} + /* hrm, is there a library for this shit? */ static struct { char *name; @@ -1583,7 +1661,7 @@ header_decode_date(const char *in, int *saveoffset) header_decode_lwsp(&inptr); if (!isdigit(*inptr)) { - char *day = header_decode_token(&inptr); + char *day = decode_token(&inptr); /* we dont really care about the day, its only for display */ if (day) { d(printf("got day: %s\n", day)); @@ -1596,7 +1674,7 @@ header_decode_date(const char *in, int *saveoffset) } } tm.tm_mday = header_decode_int(&inptr); - monthname = header_decode_token(&inptr); + monthname = decode_token(&inptr); if (monthname) { for (i=0;ivalue != last) + l = l->next; + return header_raw_find(&l, name, offset); +} + static void header_raw_free(struct _header_raw *l) { diff --git a/camel/camel-mime-utils.h b/camel/camel-mime-utils.h index 931e479a99..57d6d3ffb5 100644 --- a/camel/camel-mime-utils.h +++ b/camel/camel-mime-utils.h @@ -52,6 +52,12 @@ typedef struct _CamelMimeDisposition { unsigned int refcount; } CamelMimeDisposition; +/* structured header prameters */ +char *header_param(struct _header_param *p, const char *name); +struct _header_param *header_set_param(struct _header_param **l, const char *name, const char *value); +void header_param_list_free(struct _header_param *p); + +/* Content-Type header */ struct _header_content_type *header_content_type_new(const char *type, const char *subtype); struct _header_content_type *header_content_type_decode(const char *in); void header_content_type_unref(struct _header_content_type *ct); @@ -59,27 +65,31 @@ void header_content_type_ref(struct _header_content_type *ct); const char *header_content_type_param(struct _header_content_type *t, const char *name); void header_content_type_set_param(struct _header_content_type *t, const char *name, const char *value); int header_content_type_is(struct _header_content_type *ct, const char *type, const char *subtype); +char *header_content_type_format(struct _header_content_type *ct); -char *header_param(struct _header_param *p, char *name); -struct _header_param *header_set_param(struct _header_param **l, const char *name, const char *value); +/* DEBUGGING function */ +void header_content_type_dump(struct _header_content_type *ct); +/* Content-Disposition header */ CamelMimeDisposition *header_disposition_decode(const char *in); void header_disposition_ref(CamelMimeDisposition *); void header_disposition_unref(CamelMimeDisposition *); +char *header_disposition_format(CamelMimeDisposition *d); /* decode the contents of a content-encoding header */ char *header_content_encoding_decode(const char *in); -/* working with lists of headers */ +/* raw headers */ void header_raw_append(struct _header_raw **list, const char *name, const char *value, int offset); void header_raw_append_parse(struct _header_raw **list, const char *header, int offset); const char *header_raw_find(struct _header_raw **list, const char *name, int *ofset); +const char *header_raw_find_next(struct _header_raw **list, const char *name, int *ofset, const char *last); void header_raw_replace(struct _header_raw **list, const char *name, const char *value, int offset); void header_raw_remove(struct _header_raw **list, const char *name); void header_raw_clear(struct _header_raw **list); -/* raw header parsing functions */ -char *header_decode_token(const char **in); +/* decode a header which is a simple token */ +char *header_token_decode(const char *in); /* decode a string type, like a subject line */ char *header_decode_string(const char *in); diff --git a/camel/camel-recipient.c b/camel/camel-recipient.c index 66fd94f925..0ed028763b 100644 --- a/camel/camel-recipient.c +++ b/camel/camel-recipient.c @@ -3,8 +3,8 @@ /* * - * Author : - * Bertrand Guiheneuf + * Authors: Bertrand Guiheneuf + * Michael Zucchi * * Copyright 1999, 2000 Helix Code, Inc. (http://www.helixcode.com) * @@ -239,7 +239,29 @@ camel_recipient_table_remove (CamelRecipientTable *recipient_table, } } - +void +camel_recipient_table_remove_type (CamelRecipientTable *recipient_table, + const gchar *recipient_type) +{ + GList *l, *n; + gchar *old_recipient_type; + + /* if the recipient type section does not exist, do nothing */ + if (! g_hash_table_lookup_extended (recipient_table->recipient_hash_table, + recipient_type, + (gpointer)&(old_recipient_type), + (void *)&l)) + return; + + g_hash_table_remove(recipient_table->recipient_hash_table, old_recipient_type); + g_free(old_recipient_type); + n = l; + while (l) { + g_free(l->data); + l = l->next; + } + g_list_free(n); +} /** * camel_recipient_table_get: Get the recipients corresponding to a recipient type. diff --git a/camel/camel-recipient.h b/camel/camel-recipient.h index 25bc49bea7..1136cf36ae 100644 --- a/camel/camel-recipient.h +++ b/camel/camel-recipient.h @@ -70,7 +70,8 @@ void camel_recipient_table_add_list (CamelRecipientTable *recipient_table, void camel_recipient_table_remove (CamelRecipientTable *recipient_table, const gchar *recipient_type, const gchar *recipient); - +void camel_recipient_table_remove_type (CamelRecipientTable *recipient_table, + const gchar *recipient_type); const GList *camel_recipient_table_get (CamelRecipientTable *recipient_table, const gchar *recipient_type); diff --git a/camel/gmime-content-field.c b/camel/gmime-content-field.c index 6d0abce4e8..53d5135c23 100644 --- a/camel/gmime-content-field.c +++ b/camel/gmime-content-field.c @@ -123,22 +123,15 @@ gmime_content_field_set_parameter (GMimeContentField *content_field, const gchar void gmime_content_field_write_to_stream (GMimeContentField *content_field, CamelStream *stream) { - struct _header_param *p; + char *txt; - if (!content_field) return; + if (!content_field) + return; - g_assert (stream); - if (content_field->content_type) { - camel_stream_write_strings (stream, "Content-Type: ", content_field->content_type->type?content_field->content_type->type:"text", - "/", content_field->content_type->subtype?content_field->content_type->subtype:"plain", NULL); - - /* print all parameters */ - p = content_field->content_type->params; - while (p) { - camel_stream_write_strings (stream, ";\n ", p->name, "= \"", p->value, "\"", NULL); - p = p->next; - } - camel_stream_write_string (stream, "\n"); + txt = header_content_type_format(content_field->content_type); + if (txt) { + camel_stream_write_strings (stream, "Content-Type: ", txt, "\n", NULL); + g_free(txt); } } diff --git a/camel/providers/mbox/camel-mbox-folder.c b/camel/providers/mbox/camel-mbox-folder.c index 268ecaf3ab..75eb217e74 100644 --- a/camel/providers/mbox/camel-mbox-folder.c +++ b/camel/providers/mbox/camel-mbox-folder.c @@ -860,6 +860,7 @@ _get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex) /* init other fields? */ message->folder = folder; + gtk_object_ref((GtkObject *)folder); message->message_uid = g_strdup(uid); return message; diff --git a/camel/providers/mbox/camel-mbox-summary.c b/camel/providers/mbox/camel-mbox-summary.c index c2aad8317a..aa6f85610a 100644 --- a/camel/providers/mbox/camel-mbox-summary.c +++ b/camel/providers/mbox/camel-mbox-summary.c @@ -343,7 +343,7 @@ body_part_new(CamelMimeParser *mp, CamelMboxMessageContentInfo *parent, int star static char *strdup_trim(const char *s) { - char *end; + const char *end; if (s == NULL) return NULL; @@ -353,8 +353,7 @@ static char *strdup_trim(const char *s) end = s+strlen(s)-1; while (end>s && isspace(*end)) end--; - end = g_strndup(s, end-s+1); - return end; + return g_strndup(s, end-s+1); } static CamelMboxMessageInfo * @@ -549,7 +548,7 @@ header_evolution_decode(const char *in, unsigned int *uid, unsigned int *flags) { char *header; if (in - && (header = header_decode_token(&in))) { + && (header = header_token_decode(in))) { if (strlen(header) == strlen("00000000-0000") && sscanf(header, "%08x-%04x", uid, flags) == 2) { g_free(header); @@ -583,11 +582,13 @@ safe_write(int fd, char *buffer, size_t towrite) static int header_write(int fd, struct _header_raw *header, unsigned int uid, unsigned int flags) { - struct iovec iv[3]; + struct iovec iv[4]; int outlen = 0; iv[1].iov_base = ":"; iv[1].iov_len = 1; + iv[3].iov_base = "\n"; + iv[3].iov_len = 1; while (header) { if (strcasecmp(header->name, "x-evolution")) { @@ -599,7 +600,7 @@ header_write(int fd, struct _header_raw *header, unsigned int uid, unsigned int iv[2].iov_len = strlen(header->value); do { - len = writev(fd, iv, 3); + len = writev(fd, iv, 4); } while (len == -1 && errno == EINTR); if (len == -1) @@ -1250,8 +1251,8 @@ guint32 camel_mbox_summary_next_uid(CamelMboxSummary *s) guint32 camel_mbox_summary_set_uid(CamelMboxSummary *s, guint32 uid) { - if (s->nextuid < uid) { - s->nextuid = uid; + if (s->nextuid <= uid) { + s->nextuid = uid+1; summary_header_save(s); } return s->nextuid; -- cgit v1.2.3