diff options
author | Vsevolod Stakhov <vsevolod@rambler-co.ru> | 2009-03-24 13:13:57 +0300 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@rambler-co.ru> | 2009-03-24 13:13:57 +0300 |
commit | a0320ce847fb75f83e3c060ece2751f3d6684f05 (patch) | |
tree | 23c5e625f62f193a472fdf7aaa66c09ac339e6ca /src/message.c | |
parent | e894cd18cf4ce43dc63c71fecb69efd7e25e68f9 (diff) | |
download | rspamd-a0320ce847fb75f83e3c060ece2751f3d6684f05.tar.gz rspamd-a0320ce847fb75f83e3c060ece2751f3d6684f05.zip |
* Add smart handling of message headers
Diffstat (limited to 'src/message.c')
-rw-r--r-- | src/message.c | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/src/message.c b/src/message.c index 807463a82..be470bb65 100644 --- a/src/message.c +++ b/src/message.c @@ -552,3 +552,269 @@ get_next_text_part (memory_pool_t *pool, GList *parts, GList **cur) return NULL; } + +struct raw_header { + struct raw_header *next; + char *name; + char *value; +}; + +typedef struct _GMimeHeader { + GHashTable *hash; + GHashTable *writers; + struct raw_header *headers; +} local_GMimeHeader; + + +/* known header field types */ +enum { + HEADER_FROM = 0, + HEADER_REPLY_TO, + HEADER_TO, + HEADER_CC, + HEADER_BCC, + HEADER_SUBJECT, + HEADER_DATE, + HEADER_MESSAGE_ID, + HEADER_UNKNOWN +}; + +static GList * +local_message_get_header(GMimeMessage *message, const char *field) +{ + GList * gret = NULL; +#ifndef GMIME24 + struct raw_header *h; + + if (field == NULL) { + return NULL; + } + h = GMIME_OBJECT(message)->headers->headers; + while (h) { + if (h->value && !g_strncasecmp (field, h->name, strlen (field))) { + gret = g_list_prepend(gret, g_strdup (h->value)); + } + h = h->next; + } + return gret; +#else + GMimeHeaderList *ls; + GMimeHeaderIter *iter; + const char *name; + + ls = GMIME_OBJECT(message)->headers; + + if (g_mime_header_list_get_iter (ls, iter)) { + while (g_mime_header_iter_is_valid (iter)) { + name = g_mime_header_iter_get_name (iter); + if (!g_strncasecmp (field, name, strlen (name))) { + gret = g_list_prepend (gret, g_strdup (g_mime_header_iter_get_value (iter))); + } + if (!g_mime_header_iter_next (iter)) { + break; + } + } + } + + return gret; +#endif +} + +/** +* g_mime_message_set_date_from_string: Set the message sent-date +* @message: MIME Message +* @string: A string of date +* +* Set the sent-date on a MIME Message. +**/ +void +local_mime_message_set_date_from_string (GMimeMessage *message, const gchar *string) +{ + time_t date; + int offset = 0; + + date = g_mime_utils_header_decode_date (string, &offset); + g_mime_message_set_date (message, date, offset); +} + +#ifdef GMIME24 + +#define ADD_RECIPIENT_TEMPLATE(type,def) \ +static void \ +local_message_add_recipients_from_string_##type (GMimeMessage *message, const gchar *string, const gchar *value) \ +{ \ + InternetAddressList *il, *new; \ + \ + il = g_mime_message_get_recipients (message, (def)); \ + new = internet_address_list_parse_string (string); \ + internet_address_list_append (il, new); \ +} \ + +ADD_RECIPIENT_TEMPLATE(to, GMIME_RECIPIENT_TYPE_TO) +ADD_RECIPIENT_TEMPLATE(cc, GMIME_RECIPIENT_TYPE_CC) +ADD_RECIPIENT_TEMPLATE(bcc, GMIME_RECIPIENT_TYPE_BCC) + +#define GET_RECIPIENT_TEMPLATE(type,def) \ +static InternetAddressList* \ +local_message_get_recipients_##type (GMimeMessage *message, const char *unused) \ +{ \ + return g_mime_message_get_recipients (message, (def)); \ +} + +GET_RECIPIENT_TEMPLATE(to, GMIME_RECIPIENT_TYPE_TO) +GET_RECIPIENT_TEMPLATE(cc, GMIME_RECIPIENT_TYPE_CC) +GET_RECIPIENT_TEMPLATE(bcc, GMIME_RECIPIENT_TYPE_BCC) + +#endif + + +/* different declarations for different types of set and get functions */ +typedef const char *(*GetFunc) (GMimeMessage *message); +typedef InternetAddressList *(*GetRcptFunc) (GMimeMessage *message, const char *type ); +typedef GList *(*GetListFunc) (GMimeMessage *message, const char *type ); +typedef void (*SetFunc) (GMimeMessage *message, const char *value); +typedef void (*SetListFunc) (GMimeMessage *message, const char *field, const char *value); + +/** different types of functions +* +* FUNC_CHARPTR +* - function with no arguments +* - get returns char* +* +* FUNC_IA (from Internet Address) +* - function with additional "field" argument from the fieldfunc table, +* - get returns Glist* +* +* FUNC_LIST +* - function with additional "field" argument (given arbitrary header field name) +* - get returns Glist* +**/ +enum { + FUNC_CHARPTR = 0, + FUNC_CHARFREEPTR, + FUNC_IA, + FUNC_LIST +}; + +/** +* fieldfunc struct: structure of MIME fields and corresponding get and set +* functions. +**/ +static struct { + char * name; + GetFunc func; + GetRcptFunc rcptfunc; + GetListFunc getlistfunc; + SetFunc setfunc; + SetListFunc setlfunc; + gint functype; +} fieldfunc[] = { + { "From", g_mime_message_get_sender, NULL, NULL, g_mime_message_set_sender, NULL, FUNC_CHARPTR }, + { "Reply-To", g_mime_message_get_reply_to, NULL, NULL, g_mime_message_set_reply_to, NULL, FUNC_CHARPTR }, +#ifndef GMIME24 + { "To", NULL, (GetRcptFunc)g_mime_message_get_recipients, NULL, NULL, (SetListFunc)g_mime_message_add_recipients_from_string, FUNC_IA }, + { "Cc", NULL, (GetRcptFunc)g_mime_message_get_recipients, NULL, NULL, (SetListFunc)g_mime_message_add_recipients_from_string, FUNC_IA }, + { "Bcc",NULL, (GetRcptFunc)g_mime_message_get_recipients, NULL, NULL, (SetListFunc)g_mime_message_add_recipients_from_string, FUNC_IA }, + { "Date", (GetFunc)g_mime_message_get_date_string, NULL, NULL, local_mime_message_set_date_from_string, NULL, FUNC_CHARFREEPTR }, +#else + { "To", NULL, local_message_get_recipients_to, NULL, NULL, local_message_add_recipients_from_string_to, FUNC_IA }, + { "Cc", NULL, local_message_get_recipients_cc, NULL, NULL, local_message_add_recipients_from_string_cc, FUNC_IA }, + { "Bcc", NULL, local_message_get_recipients_bcc, NULL, NULL, local_message_add_recipients_from_string_bcc, FUNC_IA }, + { "Date", g_mime_message_get_date_as_string, NULL, NULL, local_mime_message_set_date_from_string, NULL, FUNC_CHARFREEPTR }, +#endif + { "Subject", g_mime_message_get_subject, NULL, NULL, g_mime_message_set_subject, NULL, FUNC_CHARPTR }, + { "Message-Id", g_mime_message_get_message_id, NULL, NULL, g_mime_message_set_message_id, NULL, FUNC_CHARPTR }, +#ifndef GMIME24 + { NULL, NULL, NULL, local_message_get_header, NULL, g_mime_message_add_header, FUNC_LIST } +#else + { NULL, NULL, NULL, local_message_get_header, NULL, g_mime_object_append_header, FUNC_LIST } +#endif +}; +/** +* message_set_header: set header of any type excluding special (Content- and MIME-Version:) +**/ +void +message_set_header (GMimeMessage *message, const char *field, const char *value) +{ + gint i; + + if (!g_strcasecmp (field, "MIME-Version:") || !g_strncasecmp (field, "Content-", 8)) { + return; + } + for (i=0; i<=HEADER_UNKNOWN; ++i) { + if (!fieldfunc[i].name || !g_strncasecmp(field, fieldfunc[i].name, strlen(fieldfunc[i].name))) { + switch (fieldfunc[i].functype) { + case FUNC_CHARPTR: + (*(fieldfunc[i].setfunc))(message, value); + break; + case FUNC_IA: + (*(fieldfunc[i].setlfunc))(message, fieldfunc[i].name, value); + break; + case FUNC_LIST: + (*(fieldfunc[i].setlfunc))(message, field, value); + break; + } + break; + } + } +} + + +/** +* message_get_header: returns the list of 'any header' values +* (except of unsupported yet Content- and MIME-Version special headers) +* +* You should free the GList list by yourself. +**/ +GList * +message_get_header (GMimeMessage *message, const char *field) +{ + gint i; + char * ret = NULL, *ia_string; + GList * gret = NULL; + InternetAddressList *ia_list = NULL, *ia; + + for (i = 0; i <= HEADER_UNKNOWN; ++i) { + if (!fieldfunc[i].name || !g_strncasecmp(field, fieldfunc[i].name, strlen(fieldfunc[i].name))) { + switch (fieldfunc[i].functype) { + case FUNC_CHARFREEPTR: + ret = (char *)(*(fieldfunc[i].func))(message); + break; + case FUNC_CHARPTR: + ret = (char *)(*(fieldfunc[i].func))(message); + break; + case FUNC_IA: + ia_list = (*(fieldfunc[i].rcptfunc))(message, field); + gret = g_list_alloc(); + ia = ia_list; +#ifndef GMIME24 + while (ia && ia->address) { + + ia_string = internet_address_to_string ((InternetAddress *)ia->address, FALSE); + gret = g_list_append (gret, ia_string); + ia = ia->next; + } +#else + i = internet_address_list_length (ia); + while (i > 0) { + ia_string = internet_address_to_string (internet_address_list_get_address (ia, i), FALSE); + gret = g_list_append (gret, ia_string); + -- i; + } +#endif + break; + case FUNC_LIST: + gret = (*(fieldfunc[i].getlistfunc))(message, field); + break; + } + break; + } + } + if (gret == NULL && ret != NULL) { + gret = g_list_prepend (gret, g_strdup (ret)); + } + if (fieldfunc[i].functype == FUNC_CHARFREEPTR && ret) { + g_free (ret); + } + return gret; +} |