From 64722b0299f5595184284244e6fed2ce7102bdc3 Mon Sep 17 00:00:00 2001 From: bagyenda <> Date: Tue, 8 May 2007 08:24:19 +0000 Subject: [PATCH] Bug fixes on MIME conversion --- mbuni/ChangeLog | 2 + mbuni/mmlib/mms_msg.c | 87 +++++++++++++++++++++++++-------------- mbuni/mmlib/mms_util.c | 42 +++++++++++++++++++ mbuni/mmlib/mms_util.h | 2 + mbuni/mmsc/mmsfromemail.c | 23 ++++++++++- 5 files changed, 123 insertions(+), 33 deletions(-) diff --git a/mbuni/ChangeLog b/mbuni/ChangeLog index 0419069..8b95d65 100644 --- a/mbuni/ChangeLog +++ b/mbuni/ChangeLog @@ -1,3 +1,5 @@ +2007-05-08 P. A. Bagyenda + * Improved MIME to MMS conversion conversion 2007-05-05 P. A. Bagyenda * Minor improvements to DLR handling in mmsbox. (Thanks to Vincent Chavanis ) 2007-04-13 P. A. Bagyenda diff --git a/mbuni/mmlib/mms_msg.c b/mbuni/mmlib/mms_msg.c index cf9f423..238dc12 100644 --- a/mbuni/mmlib/mms_msg.c +++ b/mbuni/mmlib/mms_msg.c @@ -1333,13 +1333,46 @@ MIMEEntity *mms_tomime(MmsMsg *msg, int base64) return m; } +static void fixup_date(List *headers, Octstr *hname) +{ + Octstr *s; + if ((s = http_header_value(headers, hname)) != NULL) { + struct tm xtm, ytm, *tm; + time_t t = time(NULL), t2; + char buf[64], *p, *q; + + http_header_remove_all(headers, octstr_get_cstr(hname)); + localtime_r(&t, &xtm); /* Initialise it. */ + + strptime(octstr_get_cstr(s), "%a, %d %b %Y %T %z", &xtm); /* Parse date value with time zone. */ + + t2 = gw_mktime(&xtm); /* Convert to unix time... */ + tm = gmtime_r(&t2, &ytm); /* Then convert to GM time. */ + + if (!tm || asctime_r(tm, buf) == NULL) /* Then convert to ascii. If that fails...*/ + ctime_r(&t, buf); /* .. just use current time. */ + + /* Strip leading and trailing blanks. */ + for (p = buf; *p && p < buf + sizeof buf; p++) + if (!isspace(*p)) + break; + q = p + (strlen(p) - 1); + while (isspace(*q) && q > p) + *q-- = 0; + + http_header_add(headers, octstr_get_cstr(hname), p); + octstr_destroy(s); + } +} + MmsMsg *mms_frommime(MIMEEntity *mime) { MmsMsg *m; Octstr *s; MIMEEntity *mx; - int n; - + int i, n; + List *h; + if (!mime) return NULL; @@ -1355,7 +1388,6 @@ MmsMsg *mms_frommime(MIMEEntity *mime) m->headers = mime_entity_headers(mx); if (n > 0) { - int i; m->ismultipart = 1; m->body.l = gwlist_create(); for (i = 0; i < n; i++) @@ -1372,6 +1404,10 @@ MmsMsg *mms_frommime(MIMEEntity *mime) if (s) { octstr_replace(s, octstr_imm("<"), octstr_imm("")); octstr_replace(s, octstr_imm(">"), octstr_imm("")); + if (octstr_get_char(s, 0) == '"') { + octstr_delete(s, 0, 1); + octstr_delete(s, octstr_len(s)-1, 1); + } http_header_remove_all(m->headers, "Message-ID"); http_header_add(m->headers, "Message-ID", octstr_get_cstr(s)); m->msgId = octstr_duplicate(s); @@ -1402,36 +1438,25 @@ MmsMsg *mms_frommime(MIMEEntity *mime) else octstr_destroy(s); - /* Fix-up date string: Put it in GMT format, since it might not be. */ - if ((s = http_header_value(m->headers, octstr_imm("Date"))) != NULL) { - struct tm xtm, ytm, *tm; - time_t t = time(NULL), t2; - char buf[64], *p, *q; - - http_header_remove_all(m->headers, "Date"); - localtime_r(&t, &xtm); /* Initialise it. */ + /* Fix-up date strings: Put it in GMT format, since it might not be. */ + fixup_date(m->headers, octstr_imm("Date")); + fixup_date(m->headers, octstr_imm("X-Mms-Expiry")); + fixup_date(m->headers, octstr_imm("X-Mms-Delivery-Time")); + fixup_date(m->headers, octstr_imm("X-Mms-Previously-Sent-Date")); + fixup_date(m->headers, octstr_imm("X-Mms-Reply-Charging-Deadline")); - strptime(octstr_get_cstr(s), "%a, %d %b %Y %T %z", &xtm); /* Parse date value with time zone. */ - - t2 = gw_mktime(&xtm); /* Convert to unix time... */ - tm = gmtime_r(&t2, &ytm); /* Then convert to GM time. */ - - if (!tm || asctime_r(tm, buf) == NULL) /* Then convert to ascii. If that fails...*/ - ctime_r(&t, buf); /* .. just use current time. */ - - /* Strip leading and trailing blanks. */ - for (p = buf; *p && p < buf + sizeof buf; p++) - if (!isspace(*p)) - break; - q = p + (strlen(p) - 1); - while (isspace(*q) && q > p) - *q-- = 0; - - http_header_add(m->headers, "Date", p); - octstr_destroy(s); - - + /* rebuild headers, skipping bad ones. */ + h = http_create_empty_headers(); + for (i = 0; iheaders); i++) { + Octstr *name = NULL, *value = NULL; + http_header_get(m->headers, i, &name, &value); + if (mms_is_token(name)) /* if header name is bad, kill this header field. */ + http_header_add(h, octstr_get_cstr(name), octstr_get_cstr(value)); + octstr_destroy(name); + octstr_destroy(value); } + http_destroy_headers(m->headers); + m->headers = h; /* XXXX Probably ought to handle some more headers here: * Return-Receipt-To becomes Read request is yes * Disposition-Notification-To: becomes X-Mms-Delivery-Report = Yes diff --git a/mbuni/mmlib/mms_util.c b/mbuni/mmlib/mms_util.c index 63f8017..a9f1978 100644 --- a/mbuni/mmlib/mms_util.c +++ b/mbuni/mmlib/mms_util.c @@ -1495,3 +1495,45 @@ static Octstr *make_url(HTTPURLParse *h) octstr_format_append(url, "#%S", h->fragment); return url; } + +static int is_separator_char(int c) +{ + switch (c) { + case '(': + case ')': + case '<': + case '>': + case '@': + case ',': + case ';': + case ':': + case '\\': + case '"': + case '/': + case '[': + case ']': + case '?': + case '=': + case '{': + case '}': + case 32: /* SP */ + case 9: /* HT */ + return 1; + default: + return 0; + } +} + +/* Is this char part of a 'token' as defined by HTTP? */ +static int is_token_char(int c) +{ + return c >= 32 && c < 127 && !is_separator_char(c); +} + +/* Is this string a 'token' as defined by HTTP? */ +int mms_is_token(Octstr *token) +{ + return octstr_len(token) > 0 && + octstr_check_range(token, 0, octstr_len(token), is_token_char); +} + diff --git a/mbuni/mmlib/mms_util.h b/mbuni/mmlib/mms_util.h index b1297f8..165da91 100644 --- a/mbuni/mmlib/mms_util.h +++ b/mbuni/mmlib/mms_util.h @@ -172,6 +172,8 @@ void strip_boundary_element(List *headers, char *s); int mms_url_fetch_content(int method, Octstr *url, List *request_headers, Octstr *body, List **reply_headers, Octstr **reply_body); +/* check that the token is valid. */ +int mms_is_token(Octstr *token); #define MAXQTRIES 100 #define BACKOFF_FACTOR 5*60 /* In seconds */ #define QUEUERUN_INTERVAL 1*60 /* 1 minutes. */ diff --git a/mbuni/mmsc/mmsfromemail.c b/mbuni/mmsc/mmsfromemail.c index af1e47e..2844571 100644 --- a/mbuni/mmsc/mmsfromemail.c +++ b/mbuni/mmsc/mmsfromemail.c @@ -57,11 +57,11 @@ int main(int argc, char *argv[]) Octstr *email, *me, *rstatus, *fname; Octstr *home_mmsc = NULL; - List *headers; + List *headers, *h2; Octstr *mm4_type = NULL, *transid, *ack, *msgid, *orig_sys; Octstr *newmsgid = NULL; - int mtype = -1, mm1_type = -1, cfidx; + int mtype = -1, mm1_type = -1, cfidx, i; char *err = NULL; mms_lib_init(); @@ -143,6 +143,24 @@ int main(int argc, char *argv[]) http_header_remove_all(headers, "X-MimeOLE"); http_header_remove_all(headers, "X-Mailer"); + /* rebuild headers, removing nasty looking ones. */ + h2 = http_create_empty_headers(); + for (i = 0; i= 0 || + octstr_case_search(name, octstr_imm("mailscanner"), 0) >= 0) + goto loop; + + http_header_add(h2, octstr_get_cstr(name), octstr_get_cstr(value)); + loop: + octstr_destroy(name); + octstr_destroy(value); + } + http_destroy_headers(headers); + headers = h2; /* Look for MM4 headers... */ mm4_type = http_header_value(headers, octstr_imm("X-Mms-Message-Type")); ack = http_header_value(headers, octstr_imm("X-Mms-Ack-Request")); @@ -175,6 +193,7 @@ int main(int argc, char *argv[]) http_header_remove_all(headers, "Message-ID"); http_header_remove_all(headers, "X-Mms-Ack-Request"); http_header_remove_all(headers, "X-Mms-Originator-System"); + http_header_remove_all(headers, "Sender"); /* msgid was there, put it back in proper form. */