2005-03-23 05:55:16 +00:00
|
|
|
/*
|
|
|
|
* Mbuni - Open Source MMS Gateway
|
2005-03-10 08:01:02 +00:00
|
|
|
*
|
2005-03-23 05:55:16 +00:00
|
|
|
* MMS message encoder/decoder and helper functions
|
|
|
|
*
|
2008-07-10 09:46:58 +00:00
|
|
|
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
2005-03-23 05:55:16 +00:00
|
|
|
*
|
|
|
|
* Paul Bagyenda <bagyenda@dsmagic.com>
|
|
|
|
*
|
|
|
|
* This program is free software, distributed under the terms of
|
|
|
|
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
2005-03-10 08:01:02 +00:00
|
|
|
*/
|
2005-03-23 05:55:16 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
#include <time.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include "mms_msg.h"
|
|
|
|
#include "mms_util.h"
|
|
|
|
|
|
|
|
struct MmsMsg {
|
|
|
|
int message_type;
|
|
|
|
Octstr *msgId;
|
|
|
|
List *headers; /* Of type HTTPHeader. */
|
2005-03-21 16:11:51 +00:00
|
|
|
mms_encoding enc;
|
2005-03-10 08:01:02 +00:00
|
|
|
unsigned char ismultipart;
|
|
|
|
union {
|
|
|
|
List *l;
|
|
|
|
Octstr *s;
|
|
|
|
} body; /* list of MIMEEntity (for multipart), text otherwise.*/
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2010-10-26 10:18:13 +00:00
|
|
|
struct MM4_types_map_t mm4_types[] = {
|
|
|
|
{"MM4_forward.REQ", MMS_MSGTYPE_SEND_REQ},
|
|
|
|
{"MM4_forward.RES",MMS_MSGTYPE_SEND_CONF},
|
|
|
|
{"MM4_read_reply_report.REQ", MMS_MSGTYPE_READ_REC_IND},
|
|
|
|
{"MM4_read_reply_report.RES",-1},
|
|
|
|
{"MM4_delivery_report.REQ",MMS_MSGTYPE_DELIVERY_IND},
|
|
|
|
{"MM4_delivery_report.RES",-1},
|
|
|
|
{NULL}
|
|
|
|
};
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
#define SIZHINT 47
|
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
|
2005-03-21 16:11:51 +00:00
|
|
|
static int encode_msgheaders(Octstr *os, List *hdrs);
|
2008-05-05 21:09:44 +00:00
|
|
|
static int decode_msgheaders(ParseContext *context, List *hdr, Octstr *from, int stop_on_ctype,
|
|
|
|
char *unified_prefix, List *strip_prefixes);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
|
2005-03-16 05:04:03 +00:00
|
|
|
static inline void pack_short_integer(Octstr *s, int ch)
|
|
|
|
{
|
2005-03-19 06:46:24 +00:00
|
|
|
unsigned long c = ((unsigned)ch)&0x7f;
|
2005-03-16 05:04:03 +00:00
|
|
|
wsp_pack_short_integer(s, c);
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
2005-03-16 05:04:03 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
#if 0
|
|
|
|
static void encode_uint(Octstr *os, unsigned int l)
|
|
|
|
{
|
|
|
|
char xbuf[5];
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
xbuf[i++] = l&0x7f;
|
|
|
|
l>>=7;
|
|
|
|
} while (i < 5 && l);
|
|
|
|
|
|
|
|
while (--i > 0) {
|
|
|
|
xbuf[i] |= 0x80;
|
|
|
|
octstr_append_data(os, &xbuf[i], 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
octstr_append_data(os, &xbuf[0], 1);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int mms_validate_address(Octstr *s)
|
|
|
|
{
|
|
|
|
|
2008-03-16 16:45:26 +00:00
|
|
|
int i;
|
|
|
|
int l;
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2008-03-16 16:45:26 +00:00
|
|
|
if (s == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
i = octstr_search_char(s, '/', 0);
|
|
|
|
l = octstr_len(s);
|
2005-03-10 08:01:02 +00:00
|
|
|
if (octstr_search_char(s, '@', 0) > 0)
|
|
|
|
return 0;
|
|
|
|
else if (i >= 0)
|
|
|
|
if (octstr_case_search(s, octstr_imm("PLMN"), 0) + 4 == l ||
|
|
|
|
octstr_case_search(s, octstr_imm("IPv4"), 0) + 4 == l ||
|
|
|
|
octstr_case_search(s, octstr_imm("IPv6"), 0) + 4 == l)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int decode_multipart(ParseContext *context, List *body)
|
|
|
|
{
|
|
|
|
int i=0, n;
|
2005-03-21 16:11:51 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
n = parse_get_uintvar(context);
|
|
|
|
|
|
|
|
for (i = 0; i<n && parse_octets_left(context) > 0 ; i++) {
|
|
|
|
int dlen, hlen;
|
2006-10-12 15:21:46 +00:00
|
|
|
MIMEEntity *x = mime_entity_create();
|
|
|
|
List *headers;
|
2005-03-21 16:11:51 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
Octstr *hs;
|
|
|
|
Octstr *content;
|
|
|
|
Octstr *content_type;
|
|
|
|
|
|
|
|
|
|
|
|
hlen = parse_get_uintvar(context);
|
|
|
|
dlen = parse_get_uintvar(context);
|
|
|
|
|
2009-02-09 08:48:56 +00:00
|
|
|
if (hlen < 0 || dlen < 0) {
|
|
|
|
int pleft = parse_octets_left(context);
|
|
|
|
mms_warning(0, NULL, NULL, "Parse error reading mime body [hlen=%d, dlen=%d, left=%d]!",
|
|
|
|
hlen,dlen, pleft);
|
|
|
|
mime_entity_destroy(x);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
parse_limit(context, hlen);
|
|
|
|
|
|
|
|
hs = parse_get_octets(context, parse_octets_left(context));
|
2005-03-21 16:11:51 +00:00
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
headers = wsp_headers_unpack(hs, 1);
|
2005-03-10 08:01:02 +00:00
|
|
|
octstr_destroy(hs);
|
2006-10-12 15:21:46 +00:00
|
|
|
|
|
|
|
strip_boundary_element(headers,NULL);
|
|
|
|
mime_replace_headers(x, headers);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
parse_skip_to_limit(context);
|
|
|
|
parse_pop_limit(context);
|
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
content_type = http_header_value(headers, octstr_imm("Content-Type"));
|
2005-03-10 08:01:02 +00:00
|
|
|
content = parse_get_octets(context, dlen);
|
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
http_destroy_headers(headers);
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
if (!content || !content_type) {
|
|
|
|
int pleft = parse_octets_left(context);
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, NULL, NULL, "Parse error reading mime body [hlen=%d, dlen=%d, left=%d]!",
|
2006-10-12 15:21:46 +00:00
|
|
|
hlen,dlen, pleft);
|
2005-03-10 08:01:02 +00:00
|
|
|
mime_entity_destroy(x);
|
2007-08-27 15:31:23 +00:00
|
|
|
octstr_destroy(content_type);
|
|
|
|
octstr_destroy(content);
|
2005-03-10 08:01:02 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2006-10-12 15:21:46 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
if (octstr_case_compare(content_type,
|
|
|
|
octstr_imm("application/vnd.wap.multipart.related")) == 0 ||
|
|
|
|
octstr_case_compare(content_type,
|
|
|
|
octstr_imm("application/vnd.wap.multipart.alternative")) == 0 ||
|
|
|
|
octstr_case_compare(content_type,
|
|
|
|
octstr_imm("application/vnd.wap.multipart.mixed")) == 0) { /* Body is multipart. */
|
|
|
|
ParseContext *p = parse_context_create(content);
|
2006-10-12 15:21:46 +00:00
|
|
|
List *ml = gwlist_create();
|
|
|
|
int res = decode_multipart(p, ml);
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
parse_context_destroy(p);
|
2006-10-12 15:21:46 +00:00
|
|
|
if (res == 0) {
|
|
|
|
/* Put body parts into mime object. */
|
|
|
|
int j, m = gwlist_len(ml);
|
|
|
|
for (j = 0; j < m; j++)
|
2008-04-29 19:00:50 +00:00
|
|
|
mime_entity_add_part(x, gwlist_get(ml,j));
|
2006-10-12 15:21:46 +00:00
|
|
|
}
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_destroy(ml, (gwlist_item_destructor_t *)mime_entity_destroy);
|
2005-03-10 08:01:02 +00:00
|
|
|
if (res < 0) {
|
2007-08-27 15:31:23 +00:00
|
|
|
octstr_destroy(content_type);
|
|
|
|
octstr_destroy(content);
|
|
|
|
return -1;
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
} else
|
2006-10-12 15:21:46 +00:00
|
|
|
mime_entity_set_body(x,content);
|
|
|
|
octstr_destroy(content);
|
2005-03-10 08:01:02 +00:00
|
|
|
octstr_destroy(content_type);
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_append(body, x);
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int encode_multipart(Octstr *os, List *body)
|
|
|
|
{
|
2006-10-12 15:21:46 +00:00
|
|
|
int i, j, n, m;
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
n = gwlist_len(body);
|
2005-03-10 08:01:02 +00:00
|
|
|
octstr_append_uintvar(os, n);
|
|
|
|
|
2005-03-21 16:11:51 +00:00
|
|
|
i = 0;
|
2005-03-10 08:01:02 +00:00
|
|
|
while (i<n) {
|
|
|
|
Octstr *mhdr, *mbody = octstr_create("");
|
2006-10-12 15:21:46 +00:00
|
|
|
MIMEEntity *x = gwlist_get(body, i);
|
2006-11-25 11:53:40 +00:00
|
|
|
List *headers = mime_entity_headers(x);
|
2006-10-12 15:21:46 +00:00
|
|
|
Octstr *s;
|
|
|
|
|
|
|
|
strip_boundary_element(headers,NULL);
|
|
|
|
mhdr = wsp_headers_pack(headers, 1, WSP_1_3);
|
|
|
|
http_destroy_headers(headers);
|
|
|
|
|
|
|
|
if ((m = mime_entity_num_parts(x)) > 0) { /* This is a multi-part,
|
|
|
|
* go down further.
|
|
|
|
*/
|
|
|
|
List *l = gwlist_create();
|
|
|
|
|
|
|
|
for (j = 0; j < m; j++)
|
|
|
|
gwlist_append(l, mime_entity_get_part(x, j));
|
|
|
|
encode_multipart(mbody, l);
|
|
|
|
gwlist_destroy(l, (gwlist_item_destructor_t *)mime_entity_destroy);
|
|
|
|
} else if ((s = mime_entity_body(x)) != NULL) {
|
|
|
|
octstr_append(mbody, s);
|
|
|
|
octstr_destroy(s);
|
|
|
|
}
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
octstr_append_uintvar(os, octstr_len(mhdr));
|
|
|
|
octstr_append_uintvar(os, octstr_len(mbody));
|
|
|
|
|
|
|
|
octstr_append(os, mhdr);
|
|
|
|
octstr_append(os, mbody);
|
|
|
|
|
|
|
|
octstr_destroy(mhdr);
|
|
|
|
octstr_destroy(mbody);
|
|
|
|
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int decode_msgbody(ParseContext *context, MmsMsg *msg)
|
|
|
|
{
|
|
|
|
int res = 0;
|
|
|
|
if (msg->ismultipart) {
|
2006-10-12 15:21:46 +00:00
|
|
|
msg->body.l = gwlist_create();
|
2005-03-10 08:01:02 +00:00
|
|
|
res = decode_multipart(context, msg->body.l);
|
|
|
|
} else
|
|
|
|
msg->body.s = parse_get_rest(context);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void encode_msgbody(Octstr *os, MmsMsg *msg)
|
|
|
|
{
|
|
|
|
if (msg->ismultipart)
|
|
|
|
encode_multipart(os, msg->body.l);
|
|
|
|
else
|
|
|
|
octstr_append(os, msg->body.s);
|
|
|
|
}
|
|
|
|
|
2005-03-16 05:04:03 +00:00
|
|
|
/* If ret < 0 then we need to get a field value, else we use what's passed. */
|
2005-04-19 09:11:43 +00:00
|
|
|
static Octstr *decode_encoded_string_value(int ret, ParseContext *context, unsigned char *hname)
|
2005-03-16 05:04:03 +00:00
|
|
|
{
|
|
|
|
int val;
|
|
|
|
int ret2;
|
|
|
|
Octstr *res = NULL;
|
|
|
|
|
|
|
|
ret2 = (ret < 0) ? wsp_field_value(context, &val) : ret;
|
|
|
|
|
|
|
|
if (ret2 == WSP_FIELD_VALUE_DATA) { /* expect charset text. */
|
|
|
|
long charset; /* Get it and ignore it. */
|
2010-11-29 12:30:03 +00:00
|
|
|
Octstr *xs;
|
2005-03-16 05:04:03 +00:00
|
|
|
wsp_secondary_field_value(context, &charset);
|
2010-11-29 12:30:03 +00:00
|
|
|
xs = parse_get_nul_string(context);
|
2005-03-16 05:04:03 +00:00
|
|
|
|
|
|
|
if (ret < 0) {
|
|
|
|
parse_skip_to_limit(context);
|
|
|
|
parse_pop_limit(context);
|
|
|
|
}
|
|
|
|
|
2010-11-29 12:30:03 +00:00
|
|
|
res = pack_rfc2047_text(xs, charset);
|
|
|
|
octstr_destroy(xs);
|
2005-03-16 05:04:03 +00:00
|
|
|
} else if (ret2 != WSP_FIELD_VALUE_NUL_STRING) {
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Faulty header value for %s! [ret=%d,ret2=%d]\n", hname,ret,ret2);
|
2005-03-16 05:04:03 +00:00
|
|
|
res = octstr_imm("");
|
|
|
|
} else
|
|
|
|
res = parse_get_nul_string(context);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2005-03-21 16:11:51 +00:00
|
|
|
/* Decodes it, adds to 'unpacked' which is the header list.
|
|
|
|
* returns the first value token got when parsing value --
|
|
|
|
* useful for unpacking msg type
|
|
|
|
*/
|
|
|
|
static int mms_unpack_well_known_field(List *unpacked, int field_type,
|
2008-05-05 21:09:44 +00:00
|
|
|
ParseContext *context,
|
|
|
|
Octstr *xfrom, int msgtype,
|
|
|
|
char *unified_prefix, List *strip_prefixes)
|
2005-03-10 08:01:02 +00:00
|
|
|
{
|
|
|
|
int val, ret;
|
2005-04-19 09:11:43 +00:00
|
|
|
unsigned char *hname = NULL;
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
Octstr *decoded = NULL;
|
2005-04-19 09:11:43 +00:00
|
|
|
unsigned char *ch = NULL;
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
ret = wsp_field_value(context, &val);
|
|
|
|
|
|
|
|
if (parse_error(context)) {
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Faulty header [code = %d], skipping remaining headers.", field_type);
|
2005-03-10 08:01:02 +00:00
|
|
|
parse_skip_to_limit(context);
|
2008-08-08 18:35:12 +00:00
|
|
|
return -2; /* serious error, bail out */
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
hname = mms_header_to_cstr(field_type);
|
|
|
|
|
|
|
|
if (ret == WSP_FIELD_VALUE_NUL_STRING)
|
|
|
|
decoded = parse_get_nul_string(context);
|
|
|
|
|
|
|
|
switch (field_type) {
|
|
|
|
|
|
|
|
case MMS_HEADER_TO:
|
|
|
|
case MMS_HEADER_CC:
|
|
|
|
case MMS_HEADER_BCC:
|
2005-03-16 06:37:25 +00:00
|
|
|
if (ret == WSP_FIELD_VALUE_DATA)
|
|
|
|
decoded = decode_encoded_string_value(ret, context, hname);
|
2008-05-05 21:09:44 +00:00
|
|
|
if (decoded)
|
|
|
|
_mms_fixup_address(&decoded, unified_prefix, strip_prefixes, 1);
|
2008-03-16 16:45:26 +00:00
|
|
|
if (decoded == NULL || mms_validate_address(decoded))
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Faulty address [%s] format in field %s!",
|
2005-03-10 08:01:02 +00:00
|
|
|
octstr_get_cstr(decoded), hname);
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_SUBJECT:
|
|
|
|
case MMS_HEADER_RETRIEVE_TEXT:
|
2005-03-16 05:04:03 +00:00
|
|
|
|
|
|
|
case MMS_HEADER_STORE_STATUS_TEXT:
|
2005-03-16 06:37:25 +00:00
|
|
|
if (ret == WSP_FIELD_VALUE_DATA)
|
|
|
|
decoded = decode_encoded_string_value(ret, context, hname);
|
2005-03-10 08:01:02 +00:00
|
|
|
break;
|
2005-03-21 16:11:51 +00:00
|
|
|
|
|
|
|
case MMS_HEADER_RESPONSE_TEXT:
|
|
|
|
if (msgtype == MMS_MSGTYPE_MBOX_DELETE_REQ &&
|
|
|
|
ret == WSP_FIELD_VALUE_DATA) {
|
|
|
|
int ret2;
|
|
|
|
|
|
|
|
decoded = wsp_unpack_integer_value(context);
|
|
|
|
|
|
|
|
ret2= wsp_field_value(context, &val);
|
2008-07-04 14:51:26 +00:00
|
|
|
if (decoded)
|
|
|
|
octstr_append(decoded, decode_encoded_string_value(ret2, context, hname));
|
|
|
|
else
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Error decoding Header-Response-Text header value");
|
2005-03-21 16:11:51 +00:00
|
|
|
if (ret2 == WSP_FIELD_VALUE_DATA) { /* we need to skip to end of inner value-data. */
|
|
|
|
parse_skip_to_limit(context);
|
|
|
|
parse_pop_limit(context);
|
|
|
|
}
|
|
|
|
} else if (ret == WSP_FIELD_VALUE_DATA)
|
|
|
|
decoded = decode_encoded_string_value(ret, context, hname);
|
|
|
|
|
|
|
|
break;
|
2005-03-10 08:01:02 +00:00
|
|
|
case MMS_HEADER_TRANSACTION_ID:
|
|
|
|
case MMS_HEADER_MESSAGE_ID:
|
|
|
|
case MMS_HEADER_REPLY_CHARGING_ID:
|
|
|
|
if (ret != WSP_FIELD_VALUE_NUL_STRING)
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Unexpected field value type %d for header %s\n",
|
2005-03-10 08:01:02 +00:00
|
|
|
ret, hname);
|
|
|
|
|
|
|
|
break;
|
2005-03-16 05:04:03 +00:00
|
|
|
|
|
|
|
/* MMS v1.2 mandates slightly different format,
|
|
|
|
* when used in m-mbox-delete.conf
|
|
|
|
*/
|
|
|
|
case MMS_HEADER_CONTENT_LOCATION:
|
|
|
|
if (ret == WSP_FIELD_VALUE_DATA) {
|
|
|
|
Octstr *t;
|
|
|
|
decoded = wsp_unpack_integer_value(context);
|
|
|
|
t = parse_get_nul_string(context);
|
2008-07-04 14:51:26 +00:00
|
|
|
if (decoded)
|
|
|
|
octstr_append(decoded, t);
|
|
|
|
else
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "error decoding value for header %s\n",
|
2008-07-04 14:51:26 +00:00
|
|
|
hname);
|
|
|
|
|
2005-03-16 05:04:03 +00:00
|
|
|
octstr_destroy(t);
|
|
|
|
} else if (ret != WSP_FIELD_VALUE_NUL_STRING)
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Unexpected field value type %d for header %s\n",
|
2005-03-16 05:04:03 +00:00
|
|
|
ret, hname);
|
|
|
|
break;
|
2005-03-10 08:01:02 +00:00
|
|
|
case MMS_HEADER_MMS_VERSION:
|
|
|
|
if (ret == WSP_FIELD_VALUE_ENCODED)
|
|
|
|
decoded = wsp_unpack_version_value(val);
|
|
|
|
break;
|
|
|
|
/* integer/octet values */
|
|
|
|
case MMS_HEADER_DELIVERY_REPORT:
|
|
|
|
case MMS_HEADER_REPORT_ALLOWED:
|
|
|
|
case MMS_HEADER_READ_REPORT:
|
2005-03-16 05:04:03 +00:00
|
|
|
|
|
|
|
case MMS_HEADER_DISTRIBUTION_INDICATOR:
|
|
|
|
case MMS_HEADER_QUOTAS:
|
|
|
|
|
|
|
|
case MMS_HEADER_STORE:
|
|
|
|
case MMS_HEADER_STORED:
|
|
|
|
case MMS_HEADER_TOTALS:
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
ch = mms_reports_to_cstr(val);
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_MESSAGE_TYPE:
|
|
|
|
ch = mms_message_type_to_cstr(val);
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_PRIORITY:
|
|
|
|
ch = mms_priority_to_cstr(val);
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_READ_STATUS:
|
|
|
|
ch = mms_read_status_to_cstr(val);
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_REPLY_CHARGING:
|
|
|
|
ch = mms_reply_charging_to_cstr(val);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_HEADER_RESPONSE_STATUS:
|
2005-03-21 16:11:51 +00:00
|
|
|
if (ret == WSP_FIELD_VALUE_DATA) {
|
2005-04-19 09:11:43 +00:00
|
|
|
unsigned char *x;
|
2005-03-21 16:11:51 +00:00
|
|
|
int val;
|
|
|
|
decoded = wsp_unpack_integer_value(context);
|
|
|
|
wsp_field_value(context, &val);
|
|
|
|
x = mms_response_status_to_cstr(val|0x80);
|
|
|
|
|
2008-08-06 05:01:20 +00:00
|
|
|
if (decoded && x)
|
2008-07-04 14:51:26 +00:00
|
|
|
octstr_append_cstr(decoded, (char *)x);
|
|
|
|
else
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "error decoding field_value_data value for header %s: val=%s\n",
|
2008-08-06 05:01:20 +00:00
|
|
|
hname, x ? (char *)x : (char *)"(null)");
|
2005-03-21 16:11:51 +00:00
|
|
|
} else
|
|
|
|
ch = mms_response_status_to_cstr(val|0x80);
|
2005-03-10 08:01:02 +00:00
|
|
|
break;
|
|
|
|
case MMS_HEADER_RETRIEVE_STATUS:
|
2005-03-21 16:11:51 +00:00
|
|
|
ch = mms_retrieve_status_to_cstr(val|0x80);
|
2005-03-10 08:01:02 +00:00
|
|
|
break;
|
|
|
|
case MMS_HEADER_STATUS:
|
|
|
|
ch = mms_status_to_cstr(val);
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_SENDER_VISIBILITY:
|
|
|
|
ch = mms_visibility_to_cstr(val);
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_MESSAGE_CLASS:
|
|
|
|
if (ret != WSP_FIELD_VALUE_NUL_STRING)
|
|
|
|
ch = mms_message_class_to_cstr(val);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_HEADER_DATE: /* Date values. */
|
|
|
|
parse_skip(context, -1);
|
|
|
|
decoded = wsp_unpack_date_value(context);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_HEADER_MESSAGE_SIZE:
|
2005-03-16 05:04:03 +00:00
|
|
|
case MMS_HEADER_REPLY_CHARGING_SIZE:
|
|
|
|
case MMS_HEADER_START:
|
|
|
|
|
|
|
|
case MMS_HEADER_LIMIT:
|
|
|
|
case MMS_HEADER_MESSAGE_COUNT:
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
parse_skip(context, -1);
|
|
|
|
decoded = wsp_unpack_integer_value(context);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_HEADER_CONTENT_TYPE:
|
|
|
|
if (ret == WSP_FIELD_VALUE_ENCODED)
|
|
|
|
ch = wsp_content_type_to_cstr(val);
|
|
|
|
else if (ret == WSP_FIELD_VALUE_DATA)
|
|
|
|
decoded = wsp_unpack_accept_general_form(context);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_HEADER_DELIVERY_TIME:
|
|
|
|
case MMS_HEADER_EXPIRY:
|
2007-08-27 15:31:23 +00:00
|
|
|
case MMS_HEADER_REPLY_CHARGING_DEADLINE:
|
2005-03-10 08:01:02 +00:00
|
|
|
if (ret != WSP_FIELD_VALUE_DATA)
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Error in value format, field %s!",
|
2005-03-10 08:01:02 +00:00
|
|
|
hname);
|
|
|
|
else {
|
|
|
|
int n = parse_get_char(context);
|
|
|
|
|
|
|
|
if (n == 0x80) /* Absolute time */
|
|
|
|
decoded = wsp_unpack_date_value(context);
|
|
|
|
else if (n == 0x81) { /* Relative time. */
|
|
|
|
long l = 0;
|
|
|
|
time_t t = time(NULL);
|
|
|
|
Octstr *s = wsp_unpack_integer_value(context);
|
|
|
|
|
|
|
|
octstr_parse_long(&l, s, 0, 10);
|
|
|
|
octstr_destroy(s);
|
|
|
|
|
|
|
|
t += l;
|
|
|
|
decoded = date_format_http(t);
|
|
|
|
} else
|
|
|
|
decoded = date_format_http(time(NULL)); /* A default. */
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_FROM:
|
|
|
|
if (ret != WSP_FIELD_VALUE_DATA)
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Error in value format, field %s!",hname);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
else {
|
|
|
|
int n = parse_get_char(context);
|
|
|
|
|
2008-05-05 21:09:44 +00:00
|
|
|
if (n == 0x80) /* Address present. */
|
2005-03-16 05:04:03 +00:00
|
|
|
decoded = decode_encoded_string_value(-1,context, hname);
|
2008-05-05 21:09:44 +00:00
|
|
|
else /* Insert address. */
|
2005-03-10 08:01:02 +00:00
|
|
|
decoded = octstr_duplicate(xfrom);
|
2008-05-05 21:09:44 +00:00
|
|
|
|
|
|
|
if (decoded)
|
|
|
|
_mms_fixup_address(&decoded, unified_prefix, strip_prefixes, 1);
|
|
|
|
if (decoded == NULL || mms_validate_address(decoded))
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Faulty address [%s] format in field %s!",
|
2008-05-05 21:09:44 +00:00
|
|
|
octstr_get_cstr(decoded), hname);
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_PREVIOUSLY_SENT_BY:
|
|
|
|
case MMS_HEADER_PREVIOUSLY_SENT_DATE:
|
|
|
|
if (ret != WSP_FIELD_VALUE_DATA)
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Error in value format, field %s!",hname);
|
2005-03-10 08:01:02 +00:00
|
|
|
else {
|
|
|
|
Octstr *t;
|
|
|
|
decoded = wsp_unpack_integer_value(context);
|
|
|
|
|
2005-03-16 05:04:03 +00:00
|
|
|
if (field_type == MMS_HEADER_PREVIOUSLY_SENT_BY)
|
2005-03-16 06:37:25 +00:00
|
|
|
t = decode_encoded_string_value(-1, context, hname);
|
2005-03-16 05:04:03 +00:00
|
|
|
else
|
2005-03-10 08:01:02 +00:00
|
|
|
t = wsp_unpack_date_value(context);
|
2008-07-04 14:51:26 +00:00
|
|
|
if (decoded)
|
|
|
|
octstr_append(decoded, t);
|
|
|
|
else
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "error decoding value for header %s!",
|
2008-07-04 14:51:26 +00:00
|
|
|
hname);
|
2005-03-10 08:01:02 +00:00
|
|
|
octstr_destroy(t);
|
|
|
|
}
|
2005-03-16 05:04:03 +00:00
|
|
|
break;
|
|
|
|
/* From here on, these are MMS v1.2 thingies. a few are above as well... */
|
|
|
|
case MMS_HEADER_ATTRIBUTES:
|
|
|
|
ch = mms_header_to_cstr(val);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_HEADER_ELEMENT_DESCRIPTOR:
|
|
|
|
if (ret != WSP_FIELD_VALUE_DATA)
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Faulty header value for %s!\n", hname);
|
2005-03-16 05:04:03 +00:00
|
|
|
else { /* We expect a content reference and a list of parameters. */
|
|
|
|
Octstr *cr = parse_get_nul_string(context);
|
|
|
|
List *params = http_create_empty_headers();
|
|
|
|
Octstr *ps;
|
|
|
|
while (parse_octets_left(context) > 0) {
|
|
|
|
int val, ret;
|
|
|
|
Octstr *pname = NULL, *pval = NULL;
|
|
|
|
ret = wsp_field_value(context, &val);
|
|
|
|
if (ret == WSP_FIELD_VALUE_ENCODED)
|
2005-03-21 16:11:51 +00:00
|
|
|
pname = mms_descriptor_params_to_string(val|0x80);
|
2005-03-16 05:04:03 +00:00
|
|
|
else if (ret == WSP_FIELD_VALUE_NUL_STRING)
|
|
|
|
pname = parse_get_nul_string(context);
|
|
|
|
|
|
|
|
if (!pname)
|
|
|
|
continue;
|
|
|
|
ret = wsp_field_value(context, &val);
|
|
|
|
if (ret == WSP_FIELD_VALUE_ENCODED)
|
|
|
|
pval = wsp_content_type_to_string(val);
|
|
|
|
else if (ret == WSP_FIELD_VALUE_NUL_STRING)
|
|
|
|
pval = parse_get_nul_string(context);
|
|
|
|
|
|
|
|
if (pval) {
|
|
|
|
http_header_add(params, octstr_get_cstr(pname), octstr_get_cstr(pval));
|
|
|
|
octstr_destroy(pval);
|
|
|
|
}
|
|
|
|
octstr_destroy(pname);
|
|
|
|
}
|
|
|
|
ps = make_value_parameters(params);
|
|
|
|
decoded = octstr_format("%S%s%S", cr,
|
|
|
|
(ps && octstr_len(ps) > 0) ? "; " : "",
|
|
|
|
ps);
|
|
|
|
octstr_destroy(cr);
|
|
|
|
octstr_destroy(ps);
|
|
|
|
http_destroy_headers(params);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_HEADER_MBOX_TOTALS:
|
|
|
|
case MMS_HEADER_MBOX_QUOTAS:
|
|
|
|
if (ret != WSP_FIELD_VALUE_DATA)
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Faulty header value for %s!\n", hname);
|
2005-03-16 05:04:03 +00:00
|
|
|
else {
|
|
|
|
int n = parse_get_char(context);
|
|
|
|
decoded = wsp_unpack_integer_value(context);
|
2008-07-04 14:51:26 +00:00
|
|
|
if (decoded)
|
|
|
|
octstr_format_append(decoded, " %s", (n == 0x80) ? "msgs" : "bytes");
|
|
|
|
else
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "error decoding value for header %s!\n", hname);
|
2005-03-16 05:04:03 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_MM_FLAGS:
|
|
|
|
if (ret != WSP_FIELD_VALUE_DATA)
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Faulty header value for %s!\n", hname);
|
2005-03-16 05:04:03 +00:00
|
|
|
else {
|
|
|
|
int n = parse_get_char(context);
|
|
|
|
char *s;
|
|
|
|
Octstr *p;
|
|
|
|
|
|
|
|
if (n == 0x80) /* Add, subtract or filter. */
|
|
|
|
s = "+";
|
|
|
|
else if (n == 0x81)
|
|
|
|
s = "-";
|
|
|
|
else
|
|
|
|
s = "/";
|
|
|
|
|
|
|
|
p = decode_encoded_string_value(-1,context, hname);
|
|
|
|
decoded = octstr_format("%s%S", s, p);
|
|
|
|
octstr_destroy(p);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_MM_STATE:
|
|
|
|
ch = mms_mm_state_to_cstr(val);
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_STORE_STATUS:
|
2005-03-21 16:11:51 +00:00
|
|
|
ch = mms_store_status_to_cstr(val|0x80);
|
2005-03-16 05:04:03 +00:00
|
|
|
break;
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
default:
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "MMS: Unknown header with code 0x%02x!", field_type);
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ret == WSP_FIELD_VALUE_DATA) {
|
|
|
|
parse_skip_to_limit(context);
|
|
|
|
parse_pop_limit(context);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ch == NULL && decoded != NULL)
|
2005-05-20 05:36:44 +00:00
|
|
|
ch = (unsigned char *)octstr_get_cstr(decoded);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
if (ch == NULL)
|
|
|
|
goto value_error;
|
|
|
|
|
|
|
|
if (!hname) {
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Unknown header number 0x%02x.", field_type);
|
2005-03-10 08:01:02 +00:00
|
|
|
goto value_error;
|
|
|
|
}
|
|
|
|
|
2005-04-19 09:11:43 +00:00
|
|
|
http_header_add(unpacked, (char *)hname, (char *)ch);
|
2007-08-27 15:31:23 +00:00
|
|
|
octstr_destroy(decoded);
|
2008-08-08 18:35:12 +00:00
|
|
|
return val; /* success (we hope) */
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
value_error:
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Skipping faulty header [code=%d, val=%d]!", field_type, val);
|
2005-03-10 08:01:02 +00:00
|
|
|
octstr_destroy(decoded);
|
2008-08-08 18:35:12 +00:00
|
|
|
return -2;
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
|
2008-05-05 21:09:44 +00:00
|
|
|
static int decode_msgheaders(ParseContext *context, List *hdrs, Octstr *from,
|
|
|
|
int stop_on_ctype, char *unified_prefixes, List *strip_prefixes)
|
2005-03-10 08:01:02 +00:00
|
|
|
{
|
|
|
|
int fcont = 1;
|
2005-03-21 16:11:51 +00:00
|
|
|
int msgtype = 0;
|
|
|
|
|
|
|
|
gw_assert(hdrs != NULL);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
while (fcont && parse_octets_left(context) &&
|
|
|
|
!parse_error(context)) {
|
|
|
|
int byte = parse_get_char(context);
|
2005-03-21 16:11:51 +00:00
|
|
|
int val = 0;
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2005-03-16 06:37:25 +00:00
|
|
|
if (byte >= 0x80)
|
2008-05-30 13:56:14 +00:00
|
|
|
val = mms_unpack_well_known_field(hdrs, byte&0x7f, context, from, msgtype,
|
|
|
|
unified_prefixes, strip_prefixes);
|
2008-08-08 18:35:12 +00:00
|
|
|
else if (byte >= 0) {
|
2005-03-10 08:01:02 +00:00
|
|
|
parse_skip(context, -1); /* Go back a bit. */
|
2005-03-21 16:11:51 +00:00
|
|
|
wsp_unpack_app_header(hdrs, context);
|
2008-08-08 18:35:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (val < -1) /* serious parser error occured above. */
|
|
|
|
break;
|
|
|
|
|
2005-03-21 16:11:51 +00:00
|
|
|
if ((byte&0x7f) == MMS_HEADER_CONTENT_TYPE &&
|
|
|
|
stop_on_ctype)
|
2005-03-10 08:01:02 +00:00
|
|
|
fcont = 0;
|
2005-03-21 16:11:51 +00:00
|
|
|
if ((byte&0x7f) == MMS_HEADER_MESSAGE_TYPE)
|
|
|
|
msgtype = val;
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void mms_pack_well_known_field(Octstr *os, int field_type, Octstr *value)
|
|
|
|
{
|
|
|
|
Octstr *encoded = octstr_create("");
|
|
|
|
int ch = 0;
|
|
|
|
unsigned char c;
|
|
|
|
|
|
|
|
switch (field_type) {
|
|
|
|
|
|
|
|
case MMS_HEADER_TO:
|
|
|
|
case MMS_HEADER_CC:
|
|
|
|
case MMS_HEADER_BCC:
|
|
|
|
case MMS_HEADER_SUBJECT:
|
|
|
|
case MMS_HEADER_TRANSACTION_ID:
|
|
|
|
case MMS_HEADER_MESSAGE_ID:
|
|
|
|
case MMS_HEADER_REPLY_CHARGING_ID:
|
|
|
|
case MMS_HEADER_RETRIEVE_TEXT:
|
2005-03-16 05:04:03 +00:00
|
|
|
|
|
|
|
case MMS_HEADER_STORE_STATUS_TEXT:
|
2010-11-29 12:30:03 +00:00
|
|
|
{
|
|
|
|
int charset;
|
|
|
|
Octstr *xvalue = parse_rfc2047_text(value, &charset);
|
|
|
|
|
|
|
|
if (charset == US_ASCII_MIB_VAL)
|
|
|
|
wsp_pack_text(os, xvalue);
|
|
|
|
else { /* Need to use the other encoding */
|
|
|
|
wsp_pack_integer_value(encoded, charset);
|
|
|
|
wsp_pack_text(encoded,xvalue);
|
|
|
|
wsp_pack_value(os, encoded);
|
|
|
|
}
|
|
|
|
octstr_destroy(xvalue);
|
|
|
|
}
|
2005-03-10 08:01:02 +00:00
|
|
|
break;
|
2005-03-16 05:04:03 +00:00
|
|
|
|
2005-03-21 16:11:51 +00:00
|
|
|
case MMS_HEADER_RESPONSE_TEXT: /* make sure response status does not begin with digit!! Has special meaning*/
|
2005-03-16 05:04:03 +00:00
|
|
|
case MMS_HEADER_CONTENT_LOCATION:
|
|
|
|
if (isdigit(octstr_get_char(value, 0))) { /* begins with number. */
|
|
|
|
long i, l;
|
|
|
|
Octstr *s;
|
|
|
|
i = octstr_parse_long(&l, value, 0, 10);
|
|
|
|
if (i < 0) {
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Bad counter for field %s!",
|
2005-03-16 05:04:03 +00:00
|
|
|
mms_header_to_cstr(field_type));
|
|
|
|
i = 0;
|
|
|
|
}
|
|
|
|
wsp_pack_integer_value(encoded, l);
|
|
|
|
s = octstr_copy(value, i, octstr_len(value));
|
2005-03-21 16:11:51 +00:00
|
|
|
octstr_strip_blanks(s);
|
|
|
|
|
2005-03-16 05:04:03 +00:00
|
|
|
wsp_pack_text(encoded,s);
|
|
|
|
wsp_pack_value(os, encoded);
|
|
|
|
|
|
|
|
octstr_destroy(s);
|
|
|
|
} else
|
|
|
|
wsp_pack_text(os, value);
|
|
|
|
break;
|
2005-03-10 08:01:02 +00:00
|
|
|
case MMS_HEADER_MMS_VERSION:
|
|
|
|
wsp_pack_version_value(os, value);
|
|
|
|
break;
|
|
|
|
/* integer/octet values: Need to stream line this with better error-checking */
|
|
|
|
case MMS_HEADER_DELIVERY_REPORT:
|
|
|
|
case MMS_HEADER_REPORT_ALLOWED:
|
|
|
|
case MMS_HEADER_READ_REPORT:
|
2005-03-16 05:04:03 +00:00
|
|
|
|
|
|
|
case MMS_HEADER_DISTRIBUTION_INDICATOR:
|
|
|
|
case MMS_HEADER_QUOTAS:
|
|
|
|
|
|
|
|
case MMS_HEADER_STORE:
|
|
|
|
case MMS_HEADER_STORED:
|
|
|
|
case MMS_HEADER_TOTALS:
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
pack_short_integer(os, mms_string_to_reports(value));
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_MESSAGE_TYPE:
|
|
|
|
pack_short_integer(os, mms_string_to_message_type(value));
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_PRIORITY:
|
|
|
|
pack_short_integer(os, mms_string_to_priority(value));
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_READ_STATUS:
|
|
|
|
pack_short_integer(os, mms_string_to_read_status(value));
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_REPLY_CHARGING:
|
|
|
|
pack_short_integer(os, mms_string_to_reply_charging(value));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_HEADER_RESPONSE_STATUS:
|
2005-03-21 16:11:51 +00:00
|
|
|
if (isdigit(octstr_get_char(value, 0))) { /* begins with number. */
|
|
|
|
long i, l;
|
|
|
|
Octstr *s;
|
|
|
|
i = octstr_parse_long(&l, value, 0, 10);
|
|
|
|
if (i < 0) {
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Bad counter for field %s!",
|
2005-03-21 16:11:51 +00:00
|
|
|
mms_header_to_cstr(field_type));
|
|
|
|
i = 0;
|
|
|
|
}
|
|
|
|
wsp_pack_integer_value(encoded, l);
|
|
|
|
s = octstr_copy(value, i, octstr_len(value));
|
|
|
|
octstr_strip_blanks(s);
|
|
|
|
|
|
|
|
pack_short_integer(encoded, mms_string_to_response_status(s));
|
|
|
|
wsp_pack_value(os, encoded);
|
|
|
|
|
|
|
|
octstr_destroy(s);
|
|
|
|
} else
|
|
|
|
pack_short_integer(os, mms_string_to_response_status(value));
|
2005-03-10 08:01:02 +00:00
|
|
|
break;
|
|
|
|
case MMS_HEADER_RETRIEVE_STATUS:
|
|
|
|
pack_short_integer(os, mms_string_to_retrieve_status(value));
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_STATUS:
|
|
|
|
pack_short_integer(os, mms_string_to_status(value));
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_SENDER_VISIBILITY:
|
|
|
|
pack_short_integer(os, mms_string_to_visibility(value));
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_MESSAGE_CLASS:
|
|
|
|
ch = mms_string_to_message_class(value);
|
|
|
|
if (ch < 0)
|
|
|
|
wsp_pack_text(os, value);
|
|
|
|
else
|
|
|
|
pack_short_integer(os, ch);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_HEADER_DATE: /* Date values. */
|
|
|
|
wsp_pack_date(os, value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_HEADER_MESSAGE_SIZE:
|
2005-03-16 05:04:03 +00:00
|
|
|
|
|
|
|
case MMS_HEADER_REPLY_CHARGING_SIZE:
|
|
|
|
case MMS_HEADER_START:
|
|
|
|
|
|
|
|
case MMS_HEADER_LIMIT:
|
|
|
|
case MMS_HEADER_MESSAGE_COUNT:
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
wsp_pack_integer_string(os, value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_HEADER_CONTENT_TYPE:
|
|
|
|
wsp_pack_content_type(os, value);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_HEADER_DELIVERY_TIME:
|
|
|
|
case MMS_HEADER_EXPIRY:
|
|
|
|
case MMS_HEADER_REPLY_CHARGING_DEADLINE:
|
|
|
|
|
|
|
|
if (octstr_isnum(value) == 1) { /* A delta value. */
|
|
|
|
|
|
|
|
long l;
|
|
|
|
|
|
|
|
sscanf(octstr_get_cstr(value), "%ld", &l);
|
|
|
|
c = 129;
|
|
|
|
octstr_append_char(encoded, c);
|
|
|
|
wsp_pack_long_integer(encoded, l);
|
|
|
|
} else { /* Must be a date value .*/
|
|
|
|
c = 128;
|
|
|
|
octstr_append_char(encoded, c);
|
|
|
|
wsp_pack_date(encoded, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
wsp_pack_value(os, encoded);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_FROM:
|
|
|
|
|
|
|
|
if (octstr_compare(octstr_imm("#insert"), value) == 0) {
|
|
|
|
c = 129;
|
2005-04-19 09:11:43 +00:00
|
|
|
octstr_append_data(encoded, (char *)&c, 1);
|
2005-03-10 08:01:02 +00:00
|
|
|
} else {
|
|
|
|
c = 128;
|
2005-04-19 09:11:43 +00:00
|
|
|
octstr_append_data(encoded, (char *)&c, 1);
|
2005-03-10 08:01:02 +00:00
|
|
|
wsp_pack_text(encoded, value);
|
|
|
|
}
|
|
|
|
wsp_pack_value(os, encoded);
|
|
|
|
|
2005-03-21 16:11:51 +00:00
|
|
|
break;
|
2005-03-10 08:01:02 +00:00
|
|
|
case MMS_HEADER_PREVIOUSLY_SENT_BY:
|
|
|
|
case MMS_HEADER_PREVIOUSLY_SENT_DATE:
|
|
|
|
{
|
|
|
|
long i, l;
|
|
|
|
Octstr *s;
|
|
|
|
|
|
|
|
i = octstr_parse_long(&l, value, 0, 10);
|
|
|
|
if (i <0) {
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Bad counter indicator for field!");
|
2005-03-10 08:01:02 +00:00
|
|
|
i = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
wsp_pack_integer_value(encoded, l);
|
|
|
|
s = octstr_copy(value, i, octstr_len(value));
|
|
|
|
|
2005-03-21 16:11:51 +00:00
|
|
|
octstr_strip_blanks(s);
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
if (field_type == MMS_HEADER_PREVIOUSLY_SENT_BY)
|
|
|
|
wsp_pack_text(encoded, s);
|
|
|
|
else
|
|
|
|
wsp_pack_date(encoded, s);
|
|
|
|
|
|
|
|
octstr_destroy(s);
|
|
|
|
wsp_pack_value(os, encoded);
|
|
|
|
}
|
|
|
|
break;
|
2005-03-16 05:04:03 +00:00
|
|
|
|
|
|
|
case MMS_HEADER_MM_STATE:
|
|
|
|
pack_short_integer(os, mms_string_to_mm_state(value));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_HEADER_STORE_STATUS:
|
|
|
|
pack_short_integer(os, mms_string_to_store_status(value));
|
|
|
|
break;
|
|
|
|
case MMS_HEADER_MM_FLAGS:
|
|
|
|
{
|
|
|
|
Octstr *s;
|
|
|
|
int i = 1;
|
|
|
|
ch = octstr_get_char(value, 0);
|
|
|
|
|
2005-03-19 06:46:24 +00:00
|
|
|
if (ch == '+')
|
|
|
|
pack_short_integer(encoded, 0x80);
|
|
|
|
else if (ch == '-')
|
|
|
|
pack_short_integer(encoded, 0x81);
|
2005-03-16 05:04:03 +00:00
|
|
|
else if (ch == '/')
|
2005-03-19 06:46:24 +00:00
|
|
|
pack_short_integer(encoded, 0x82);
|
2005-03-16 05:04:03 +00:00
|
|
|
else {
|
|
|
|
i = 0;
|
2005-03-19 06:46:24 +00:00
|
|
|
pack_short_integer(encoded, 0x82); /* default is filter. */
|
2005-03-16 05:04:03 +00:00
|
|
|
}
|
|
|
|
s = octstr_copy(value, i, octstr_len(value));
|
|
|
|
wsp_pack_text(encoded, s);
|
|
|
|
wsp_pack_value(os, encoded);
|
|
|
|
|
|
|
|
octstr_destroy(s);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_HEADER_ATTRIBUTES:
|
|
|
|
ch = mms_string_to_header(value);
|
|
|
|
pack_short_integer(os, ch);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_HEADER_MBOX_TOTALS:
|
|
|
|
case MMS_HEADER_MBOX_QUOTAS:
|
|
|
|
{
|
|
|
|
long i, l;
|
|
|
|
|
|
|
|
i = octstr_parse_long(&l, value, 0, 10);
|
|
|
|
if (i <0) {
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "Bad quota value for field %s!", mms_header_to_cstr(field_type));
|
2005-03-16 05:04:03 +00:00
|
|
|
i = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (octstr_case_search(value, octstr_imm("bytes"), i) < 0)
|
|
|
|
ch = 0x80;
|
|
|
|
else
|
|
|
|
ch = 0x81;
|
|
|
|
pack_short_integer(encoded, ch);
|
|
|
|
wsp_pack_integer_value(encoded, l);
|
|
|
|
|
|
|
|
wsp_pack_value(os, encoded);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MMS_HEADER_ELEMENT_DESCRIPTOR:
|
|
|
|
{
|
|
|
|
Octstr *cv, *cpar;
|
|
|
|
List *params;
|
|
|
|
int i, n;
|
|
|
|
|
|
|
|
split_header_value(value, &cv, &cpar);
|
|
|
|
params = get_value_parameters(cpar);
|
|
|
|
|
|
|
|
wsp_pack_text(encoded, cv);
|
2006-10-12 15:21:46 +00:00
|
|
|
n = gwlist_len(params);
|
2005-03-16 05:04:03 +00:00
|
|
|
|
|
|
|
for (i = 0; i<n; i++) {
|
|
|
|
Octstr *h, *v;
|
|
|
|
int ch;
|
|
|
|
http_header_get(params, i, &h, &v);
|
|
|
|
ch = mms_string_to_descriptor_params(h);
|
|
|
|
if (ch < 0)
|
|
|
|
wsp_pack_text(encoded, h);
|
|
|
|
else
|
|
|
|
pack_short_integer(encoded, ch);
|
|
|
|
|
|
|
|
ch = wsp_string_to_content_type(v);
|
|
|
|
if (ch < 0)
|
|
|
|
wsp_pack_text(encoded, v);
|
|
|
|
else
|
|
|
|
pack_short_integer(encoded, ch);
|
|
|
|
|
|
|
|
octstr_destroy(h);
|
|
|
|
octstr_destroy(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
octstr_destroy(cv);
|
|
|
|
octstr_destroy(cpar);
|
|
|
|
http_destroy_headers(params);
|
|
|
|
|
|
|
|
wsp_pack_value(os, encoded);
|
|
|
|
}
|
|
|
|
break;
|
2005-03-10 08:01:02 +00:00
|
|
|
default:
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "MMS: Unknown header with code 0x%02x!", field_type);
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
|
2007-08-27 15:31:23 +00:00
|
|
|
octstr_destroy(encoded);
|
2005-03-10 08:01:02 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-03-21 16:11:51 +00:00
|
|
|
static int encode_msgheaders(Octstr *os, List *hdrs)
|
2005-03-10 08:01:02 +00:00
|
|
|
{
|
|
|
|
int fcont = 1;
|
2006-10-12 15:21:46 +00:00
|
|
|
int i, l = gwlist_len(hdrs), mtype;
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
Octstr *msgtype = NULL, *transid = NULL, *version = NULL, *ctype;
|
2006-10-12 15:21:46 +00:00
|
|
|
|
|
|
|
strip_boundary_element(hdrs,NULL);
|
2005-03-10 08:01:02 +00:00
|
|
|
/* First ensure that top headers are in place. */
|
|
|
|
|
|
|
|
version = http_header_value(hdrs,
|
|
|
|
octstr_imm("X-Mms-MMS-Version"));
|
2005-04-14 11:27:23 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
transid = http_header_value(hdrs,
|
|
|
|
octstr_imm("X-Mms-Transaction-Id"));
|
|
|
|
msgtype = http_header_value(hdrs,
|
|
|
|
octstr_imm("X-Mms-Message-Type"));
|
|
|
|
|
|
|
|
ctype = http_header_value(hdrs,
|
|
|
|
octstr_imm("Content-Type"));
|
|
|
|
|
|
|
|
mtype = mms_string_to_message_type(msgtype);
|
|
|
|
|
|
|
|
pack_short_integer(os, MMS_HEADER_MESSAGE_TYPE);
|
|
|
|
pack_short_integer(os, mtype);
|
|
|
|
octstr_destroy(msgtype);
|
|
|
|
|
|
|
|
if (transid) {
|
|
|
|
pack_short_integer(os, MMS_HEADER_TRANSACTION_ID);
|
|
|
|
wsp_pack_text(os, transid);
|
|
|
|
octstr_destroy(transid);
|
|
|
|
}
|
|
|
|
pack_short_integer(os, MMS_HEADER_MMS_VERSION);
|
|
|
|
wsp_pack_version_value(os, version);
|
|
|
|
octstr_destroy(version);
|
|
|
|
|
|
|
|
/* Now pack the rest. */
|
|
|
|
for (i = 0; fcont && i < l; i++) {
|
|
|
|
Octstr *field = NULL, *value = NULL;
|
|
|
|
int htype;
|
|
|
|
|
|
|
|
http_header_get(hdrs, i, &field, &value);
|
|
|
|
|
|
|
|
htype = mms_string_to_header(field);
|
|
|
|
|
|
|
|
if (htype == MMS_HEADER_MMS_VERSION ||
|
|
|
|
htype == MMS_HEADER_MESSAGE_TYPE ||
|
|
|
|
htype == MMS_HEADER_TRANSACTION_ID ||
|
|
|
|
htype == MMS_HEADER_CONTENT_TYPE)
|
|
|
|
goto loop1;
|
|
|
|
|
|
|
|
if (htype < 0)
|
|
|
|
wsp_pack_application_header(os, field, value);
|
|
|
|
else {
|
|
|
|
pack_short_integer(os, htype);
|
|
|
|
mms_pack_well_known_field(os, htype, value);
|
|
|
|
}
|
|
|
|
loop1:
|
|
|
|
if (field) octstr_destroy(field);
|
|
|
|
if (value) octstr_destroy(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ctype) {
|
|
|
|
pack_short_integer(os, MMS_HEADER_CONTENT_TYPE);
|
|
|
|
wsp_pack_content_type(os, ctype);
|
|
|
|
octstr_destroy(ctype);
|
|
|
|
} else if (mtype == MMS_MSGTYPE_SEND_REQ ||
|
|
|
|
mtype == MMS_MSGTYPE_RETRIEVE_CONF)
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_warning(0, "mms_msg", NULL, "MMS: Content type missing in encode_headers!");
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Does basic fixups on a message. */
|
|
|
|
static int fixup_msg(MmsMsg *m, Octstr *from)
|
|
|
|
{
|
2008-04-18 12:32:31 +00:00
|
|
|
Octstr *ver = NULL;
|
2007-03-20 16:43:44 +00:00
|
|
|
Octstr *s = NULL;
|
2005-03-10 08:01:02 +00:00
|
|
|
if (!m)
|
|
|
|
return -1;
|
|
|
|
|
2005-03-21 16:11:51 +00:00
|
|
|
ver = http_header_value(m->headers, octstr_imm("X-Mms-MMS-Version"));
|
2005-04-14 11:27:23 +00:00
|
|
|
if (!ver || octstr_str_compare(ver, "1.1") <= 0) {
|
2005-03-21 16:11:51 +00:00
|
|
|
m->enc = MS_1_1;
|
2005-04-14 11:27:23 +00:00
|
|
|
if (!ver)
|
|
|
|
http_header_add(m->headers, "X-Mms-MMS-Version", MMS_DEFAULT_VERSION);
|
|
|
|
} else if (octstr_str_compare(ver, "1.2") <= 0)
|
2005-03-21 16:11:51 +00:00
|
|
|
m->enc = MS_1_2;
|
2006-10-12 15:21:46 +00:00
|
|
|
http_header_remove_all(m->headers, "MIME-Version");
|
2007-03-20 16:43:44 +00:00
|
|
|
switch (m->message_type) {
|
|
|
|
case MMS_MSGTYPE_SEND_REQ:
|
|
|
|
case MMS_MSGTYPE_RETRIEVE_CONF:
|
|
|
|
case MMS_MSGTYPE_FORWARD_REQ:
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
/* Check for from. */
|
|
|
|
if (from && (s = http_header_value(m->headers, octstr_imm("From"))) == NULL)
|
|
|
|
http_header_add(m->headers, "From", octstr_get_cstr(from));
|
2008-04-18 12:32:31 +00:00
|
|
|
else
|
2005-03-10 08:01:02 +00:00
|
|
|
octstr_destroy(s);
|
|
|
|
|
|
|
|
/* Check for date. */
|
|
|
|
|
|
|
|
if ((s = http_header_value(m->headers, octstr_imm("Date"))) == NULL) {
|
|
|
|
Octstr *t = date_format_http(time(NULL));
|
|
|
|
http_header_add(m->headers, "Date", octstr_get_cstr(t));
|
|
|
|
octstr_destroy(t);
|
|
|
|
} else
|
|
|
|
octstr_destroy(s);
|
2007-03-20 16:43:44 +00:00
|
|
|
|
2007-09-19 13:06:26 +00:00
|
|
|
/* check for transaction ID. */
|
|
|
|
if ((s = http_header_value(m->headers, octstr_imm("X-Mms-Transaction-ID"))) == NULL) {
|
|
|
|
if (m->message_type != MMS_MSGTYPE_RETRIEVE_CONF)
|
|
|
|
http_header_add(m->headers, "X-Mms-Transaction-ID", "00001");
|
2008-04-18 12:32:31 +00:00
|
|
|
} else
|
2007-09-19 13:06:26 +00:00
|
|
|
octstr_destroy(s);
|
2005-10-21 12:37:15 +00:00
|
|
|
#if 0 /* This will be done elsewhere. */
|
2005-04-08 10:29:08 +00:00
|
|
|
/* Check for msgid, put in if missing. */
|
2005-10-21 08:04:42 +00:00
|
|
|
if ((s = http_header_value(m->headers, octstr_imm("Message-ID"))) == NULL)
|
|
|
|
http_header_add(m->headers, "Message-ID", "00000");
|
2005-04-08 10:29:08 +00:00
|
|
|
else
|
|
|
|
octstr_destroy(s);
|
2005-10-21 12:37:15 +00:00
|
|
|
#endif
|
2005-07-01 06:13:59 +00:00
|
|
|
/* check for content-type. */
|
|
|
|
if ((s = http_header_value(m->headers, octstr_imm("Content-Type"))) == NULL) {
|
|
|
|
char *ctype;
|
|
|
|
if (m->body.s == NULL ||
|
|
|
|
(!m->ismultipart &&
|
|
|
|
octstr_check_range(m->body.s, 0,
|
|
|
|
octstr_len(m->body.s), _mms_gw_isprint) == 0))
|
|
|
|
ctype = "application/octet-stream";
|
|
|
|
else if (m->ismultipart)
|
|
|
|
ctype = "application/vnd.wap.multipart.mixed";
|
|
|
|
else
|
|
|
|
ctype = "text/plain";
|
|
|
|
http_header_add(m->headers, "Content-Type", ctype);
|
|
|
|
} else
|
|
|
|
octstr_destroy(s);
|
2007-03-20 16:43:44 +00:00
|
|
|
strip_boundary_element(m->headers, NULL); /* remove top-level boundary element if any. */
|
|
|
|
break;
|
|
|
|
case MMS_MSGTYPE_SEND_CONF:
|
|
|
|
case MMS_MSGTYPE_NOTIFICATION_IND:
|
|
|
|
case MMS_MSGTYPE_DELIVERY_IND:
|
|
|
|
case MMS_MSGTYPE_READ_REC_IND:
|
|
|
|
case MMS_MSGTYPE_READ_ORIG_IND:
|
|
|
|
http_header_remove_all(m->headers, "Content-Type"); /* Just in case, particularly from mime! */
|
|
|
|
break;
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
2008-04-18 12:32:31 +00:00
|
|
|
octstr_destroy(ver);
|
2005-03-10 08:01:02 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2005-03-21 16:11:51 +00:00
|
|
|
|
|
|
|
mms_encoding mms_message_enc(MmsMsg *msg)
|
|
|
|
{
|
2006-02-24 05:15:26 +00:00
|
|
|
gw_assert(msg);
|
2005-03-21 16:11:51 +00:00
|
|
|
return msg->enc;
|
|
|
|
}
|
|
|
|
|
2008-05-05 21:09:44 +00:00
|
|
|
MmsMsg *mms_frombinary_ex(Octstr *msg, Octstr *from, char *unified_prefix, List *strip_prefixes)
|
2005-03-10 08:01:02 +00:00
|
|
|
{
|
|
|
|
int res = 0;
|
|
|
|
MmsMsg _m = {0}, *m = NULL;
|
2006-02-24 05:15:26 +00:00
|
|
|
ParseContext *p;
|
2005-03-10 08:01:02 +00:00
|
|
|
Octstr *s;
|
|
|
|
|
2006-02-24 05:15:26 +00:00
|
|
|
if (!msg)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
p = parse_context_create(msg);
|
2005-03-21 16:11:51 +00:00
|
|
|
mms_strings_init(); /* Just in case. */
|
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
_m.headers = gwlist_create();
|
2008-05-05 21:09:44 +00:00
|
|
|
decode_msgheaders(p, _m.headers, from, 1, unified_prefix, strip_prefixes);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
if (_m.headers == NULL ||
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_len(_m.headers) == 0)
|
2005-05-24 07:16:32 +00:00
|
|
|
goto done;
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
/* Get the message type and also set flag for whether multipart.*/
|
|
|
|
|
|
|
|
s = http_header_value(_m.headers, octstr_imm("Content-Type"));
|
|
|
|
if (s &&
|
|
|
|
octstr_search(s, octstr_imm("application/vnd.wap.multipart"), 0) == 0)
|
|
|
|
_m.ismultipart = 1;
|
2007-08-27 15:31:23 +00:00
|
|
|
|
|
|
|
octstr_destroy(s);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
s = http_header_value(_m.headers, octstr_imm("X-Mms-Message-Type"));
|
|
|
|
if (s) {
|
|
|
|
_m.message_type = mms_string_to_message_type(s);
|
|
|
|
octstr_destroy(s);
|
2005-05-24 07:16:32 +00:00
|
|
|
} else
|
2005-03-10 08:01:02 +00:00
|
|
|
goto done;
|
2005-05-24 07:16:32 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
s = http_header_value(_m.headers, octstr_imm("Message-ID"));
|
|
|
|
_m.msgId = s;
|
|
|
|
|
2005-05-24 07:16:32 +00:00
|
|
|
if ((res = decode_msgbody(p, &_m)) < 0) /* A body decode error occured. */
|
|
|
|
goto done;
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2005-05-24 07:16:32 +00:00
|
|
|
m = gw_malloc(sizeof m[0]); /* all ok, copy. */
|
2005-03-10 08:01:02 +00:00
|
|
|
*m = _m;
|
|
|
|
|
|
|
|
fixup_msg(m, from);
|
|
|
|
|
|
|
|
done:
|
|
|
|
parse_context_destroy(p);
|
2005-05-24 07:16:32 +00:00
|
|
|
if (!m) { /* This means an error occurred. Delete the interim stuff. */
|
|
|
|
MmsMsg *msg = &_m;
|
|
|
|
|
2007-08-27 15:31:23 +00:00
|
|
|
if (msg->ismultipart)
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_destroy(msg->body.l, (gwlist_item_destructor_t *)mime_entity_destroy);
|
2007-08-27 15:31:23 +00:00
|
|
|
else
|
2005-05-24 07:16:32 +00:00
|
|
|
octstr_destroy(msg->body.s);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2007-08-27 15:31:23 +00:00
|
|
|
http_destroy_headers(msg->headers);
|
|
|
|
octstr_destroy(msg->msgId);
|
2005-05-24 07:16:32 +00:00
|
|
|
}
|
2005-03-10 08:01:02 +00:00
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void _x_mime_entity_dump(MIMEEntity *x, int level, int headers_only)
|
|
|
|
{
|
2006-10-12 15:21:46 +00:00
|
|
|
int i,m, ism;
|
|
|
|
List *h;
|
|
|
|
Octstr *body;
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
ism = ((m = mime_entity_num_parts(x)) > 0);
|
|
|
|
debug("part.dump", 0, "%sMultipart -> ", ism ? "" : "Not ");
|
|
|
|
|
2006-11-25 11:53:40 +00:00
|
|
|
h = mime_entity_headers(x);
|
2006-10-12 15:21:46 +00:00
|
|
|
strip_boundary_element(h,NULL);
|
|
|
|
http_header_dump(h);
|
|
|
|
http_destroy_headers(h);
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
if (ism)
|
2006-10-12 15:21:46 +00:00
|
|
|
for (i = 0; i<m; i++) {
|
|
|
|
MIMEEntity *xm = mime_entity_get_part(x, i);
|
|
|
|
_x_mime_entity_dump(xm, level+1, headers_only);
|
|
|
|
mime_entity_destroy(xm);
|
|
|
|
}
|
|
|
|
else if ((body = mime_entity_body(x)) != NULL) {
|
|
|
|
if (!headers_only)
|
|
|
|
octstr_dump(body, level);
|
|
|
|
octstr_destroy(body);
|
|
|
|
}
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void mms_msgdump(MmsMsg *m, int headers_only)
|
|
|
|
{
|
|
|
|
int i, n;
|
|
|
|
|
2009-08-13 04:03:36 +00:00
|
|
|
if (!m)
|
|
|
|
return;
|
2006-02-24 05:15:26 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
http_header_dump(m->headers);
|
|
|
|
|
|
|
|
debug("mms.dump", 0, "Dumping MMS message body (%s) [%ld parts] --> ",
|
|
|
|
m->ismultipart ? "mulitpart" : "not multipart",
|
2006-10-12 15:21:46 +00:00
|
|
|
m->ismultipart ? gwlist_len(m->body.l) : 0);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
if (m->ismultipart)
|
2006-10-12 15:21:46 +00:00
|
|
|
for (i = 0, n = gwlist_len(m->body.l); i< n; i++) {
|
|
|
|
MIMEEntity *x = gwlist_get(m->body.l, i);
|
|
|
|
debug("mms.dump", 0, "--->Message part: %d --->", i);
|
|
|
|
|
|
|
|
_x_mime_entity_dump(x,0,headers_only);
|
|
|
|
}
|
2005-03-10 08:01:02 +00:00
|
|
|
else if (!headers_only)
|
2006-10-12 15:21:46 +00:00
|
|
|
octstr_dump(m->body.s, 0);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Octstr *mms_tobinary(MmsMsg *msg)
|
|
|
|
{
|
2006-02-24 05:15:26 +00:00
|
|
|
Octstr *s;
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2006-02-24 05:15:26 +00:00
|
|
|
if (!msg)
|
|
|
|
return NULL;
|
|
|
|
s = octstr_create("");
|
2005-03-21 16:11:51 +00:00
|
|
|
encode_msgheaders(s, msg->headers);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
if (msg->body.s)
|
|
|
|
encode_msgbody(s, msg);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
int mms_messagetype(MmsMsg *msg)
|
|
|
|
{
|
2006-02-24 05:15:26 +00:00
|
|
|
gw_assert(msg);
|
|
|
|
return msg->message_type;
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-04-18 12:32:31 +00:00
|
|
|
static int convert_mime_msg(MIMEEntity *m)
|
2005-03-10 08:01:02 +00:00
|
|
|
{
|
2008-04-18 12:32:31 +00:00
|
|
|
int i, n, res = 0;
|
|
|
|
Octstr *content_type = NULL, *params = NULL;
|
2005-03-10 08:01:02 +00:00
|
|
|
char *s = NULL;
|
2006-11-25 11:53:40 +00:00
|
|
|
List *h = mime_entity_headers(m);
|
2006-10-12 15:21:46 +00:00
|
|
|
|
2007-03-20 16:43:44 +00:00
|
|
|
n = get_content_type(h, &content_type, ¶ms);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2007-03-20 16:43:44 +00:00
|
|
|
if (n == 0 && content_type) {
|
2005-03-10 08:01:02 +00:00
|
|
|
if (octstr_str_compare(content_type,
|
|
|
|
"application/vnd.wap.multipart.related") == 0)
|
|
|
|
s = "multipart/related";
|
|
|
|
else if (octstr_str_compare(content_type,
|
|
|
|
"application/vnd.wap.multipart.alternative") == 0)
|
|
|
|
s = "multipart/alternative";
|
|
|
|
else if (octstr_str_compare(content_type,
|
|
|
|
"application/vnd.wap.multipart.mixed") == 0)
|
|
|
|
s = "multipart/mixed";
|
|
|
|
}
|
2008-04-18 12:32:31 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
if (s) {
|
2006-11-18 06:20:05 +00:00
|
|
|
Octstr *value;
|
|
|
|
|
|
|
|
if (params && octstr_len(params) > 0) {
|
|
|
|
List *ph = get_value_parameters(params); /* unpack then re-pack them with proper quoting for mime.*/
|
|
|
|
Octstr *ps = make_value_parameters(ph);
|
|
|
|
value = octstr_format("%s; %S", s, params);
|
|
|
|
octstr_destroy(ps);
|
|
|
|
http_destroy_headers(ph);
|
|
|
|
} else
|
|
|
|
value = octstr_create(s);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
http_header_remove_all(h, "Content-Type");
|
|
|
|
http_header_add(h, "Content-Type", octstr_get_cstr(value));
|
|
|
|
mime_replace_headers(m,h);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
octstr_destroy(value);
|
2008-04-18 12:32:31 +00:00
|
|
|
res = 1;
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
2007-08-27 15:31:23 +00:00
|
|
|
|
|
|
|
http_destroy_headers(h);
|
2006-10-12 15:21:46 +00:00
|
|
|
if ((n = mime_entity_num_parts(m)) > 0)
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
MIMEEntity *x = mime_entity_get_part(m, i);
|
2008-04-18 12:32:31 +00:00
|
|
|
int xres = convert_mime_msg(x);
|
|
|
|
if (xres) {
|
|
|
|
mime_entity_replace_part(m, i, x);
|
|
|
|
res = 1;
|
|
|
|
}
|
|
|
|
mime_entity_destroy(x);
|
2006-10-12 15:21:46 +00:00
|
|
|
}
|
2008-04-18 12:32:31 +00:00
|
|
|
octstr_destroy(params);
|
|
|
|
octstr_destroy(content_type);
|
|
|
|
|
|
|
|
return res;
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
|
2008-04-18 12:32:31 +00:00
|
|
|
static int unconvert_mime_msg(MIMEEntity *m)
|
2005-03-10 08:01:02 +00:00
|
|
|
{
|
2008-04-18 12:32:31 +00:00
|
|
|
int i, n, res = 0;
|
2005-03-10 08:01:02 +00:00
|
|
|
Octstr *content_type, *params;
|
|
|
|
char *s = NULL;
|
2006-11-25 11:53:40 +00:00
|
|
|
List *h = mime_entity_headers(m);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2007-03-20 16:43:44 +00:00
|
|
|
n = get_content_type(h, &content_type, ¶ms);
|
|
|
|
if (n == 0 && content_type) {
|
2005-03-10 08:01:02 +00:00
|
|
|
if (octstr_case_compare(content_type,
|
|
|
|
octstr_imm("multipart/related")) == 0)
|
|
|
|
s = "application/vnd.wap.multipart.related";
|
|
|
|
else if (octstr_case_compare(content_type,
|
|
|
|
octstr_imm("multipart/alternative")) == 0)
|
|
|
|
s = "application/vnd.wap.multipart.alternative";
|
|
|
|
else if (octstr_case_compare(content_type,
|
|
|
|
octstr_imm("multipart/mixed")) == 0)
|
|
|
|
s = "application/vnd.wap.multipart.mixed";
|
2007-07-17 12:43:30 +00:00
|
|
|
else if (DRM_CONTENT_TYPE(content_type) &&
|
2007-07-17 08:26:38 +00:00
|
|
|
mime_entity_num_parts(m) > 0) { /* fixup drm that might have been screwed up. */
|
|
|
|
Octstr *x = mime_entity_body(m);
|
|
|
|
while (mime_entity_num_parts(m) > 0) /* remove them all. this message must not be parsed as mime. */
|
|
|
|
mime_entity_remove_part(m, 0);
|
|
|
|
mime_entity_set_body(m, x);
|
|
|
|
octstr_destroy(x);
|
|
|
|
}
|
2008-04-18 12:32:31 +00:00
|
|
|
res = 1;
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
if (s)
|
|
|
|
strip_boundary_element(h,s);
|
|
|
|
mime_replace_headers(m, h);
|
|
|
|
http_destroy_headers(h);
|
2007-08-27 15:31:23 +00:00
|
|
|
octstr_destroy(params);
|
2008-04-18 12:32:31 +00:00
|
|
|
octstr_destroy(content_type);
|
2006-10-12 15:21:46 +00:00
|
|
|
if ((n = mime_entity_num_parts(m)) > 0)
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
MIMEEntity *x = mime_entity_get_part(m, i);
|
2008-04-18 12:32:31 +00:00
|
|
|
int xres = unconvert_mime_msg(x);
|
|
|
|
if (xres) {
|
|
|
|
mime_entity_replace_part(m, i, x);
|
|
|
|
res = 1;
|
|
|
|
}
|
|
|
|
mime_entity_destroy(x);
|
2006-10-12 15:21:46 +00:00
|
|
|
}
|
2008-04-18 12:32:31 +00:00
|
|
|
return res;
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-01 05:54:35 +00:00
|
|
|
MIMEEntity *mms_tomime(MmsMsg *msg, int base64)
|
2005-03-10 08:01:02 +00:00
|
|
|
{
|
2006-02-24 05:15:26 +00:00
|
|
|
MIMEEntity *m;
|
2005-03-10 08:01:02 +00:00
|
|
|
int i, n;
|
|
|
|
|
2006-02-24 05:15:26 +00:00
|
|
|
if (!msg)
|
|
|
|
return NULL;
|
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
m = mime_entity_create();
|
|
|
|
mime_replace_headers(m, msg->headers);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
if (!msg->ismultipart)
|
2006-10-12 15:21:46 +00:00
|
|
|
mime_entity_set_body(m, msg->body.s);
|
2005-03-10 08:01:02 +00:00
|
|
|
else {
|
2006-10-12 15:21:46 +00:00
|
|
|
for (i = 0, n = gwlist_len(msg->body.l); i < n; i++) {
|
|
|
|
MIMEEntity *mx = gwlist_get(msg->body.l, i);
|
|
|
|
mime_entity_add_part(m, mx);
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
convert_mime_msg(m);
|
2005-07-01 05:54:35 +00:00
|
|
|
if (base64)
|
2007-07-17 08:26:38 +00:00
|
|
|
base64_mimeparts(m,0);
|
2005-03-10 08:01:02 +00:00
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2007-05-08 08:24:19 +00:00
|
|
|
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)
|
2007-08-27 15:31:23 +00:00
|
|
|
*q-- = 0;
|
2007-05-08 08:24:19 +00:00
|
|
|
|
|
|
|
http_header_add(headers, octstr_get_cstr(hname), p);
|
|
|
|
octstr_destroy(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
MmsMsg *mms_frommime(MIMEEntity *mime)
|
|
|
|
{
|
2006-02-24 05:15:26 +00:00
|
|
|
MmsMsg *m;
|
2005-03-10 08:01:02 +00:00
|
|
|
Octstr *s;
|
|
|
|
MIMEEntity *mx;
|
2007-05-08 08:24:19 +00:00
|
|
|
int i, n;
|
|
|
|
List *h;
|
|
|
|
|
2006-02-24 05:15:26 +00:00
|
|
|
if (!mime)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
m = gw_malloc(sizeof *m);
|
2005-03-10 08:01:02 +00:00
|
|
|
memset(m, 0, sizeof *m);
|
|
|
|
|
|
|
|
mx = mime_entity_duplicate(mime);
|
2006-10-12 15:21:46 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
unconvert_mime_msg(mx); /* Fix-up content type issues. */
|
|
|
|
unpack_mimeheaders(mx);
|
|
|
|
unbase64_mimeparts(mx);
|
|
|
|
|
2006-11-25 11:53:40 +00:00
|
|
|
m->headers = mime_entity_headers(mx);
|
2007-07-19 18:15:17 +00:00
|
|
|
if ((n = mime_entity_num_parts(mx)) > 0) {
|
2005-03-10 08:01:02 +00:00
|
|
|
m->ismultipart = 1;
|
2006-10-12 15:21:46 +00:00
|
|
|
m->body.l = gwlist_create();
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
gwlist_append(m->body.l, mime_entity_get_part(mx, i));
|
2005-03-10 08:01:02 +00:00
|
|
|
} else {
|
|
|
|
m->ismultipart = 0;
|
2006-10-12 15:21:46 +00:00
|
|
|
m->body.s = mime_entity_body(mx);
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
2006-10-12 15:21:46 +00:00
|
|
|
mime_entity_destroy(mx); /* Because all its bits are used above. XXX not very clean! */
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
|
2007-03-28 12:13:44 +00:00
|
|
|
/* Now check for important headers. If missing, put them in - MsgId fixup - Vince */
|
|
|
|
s = http_header_value(m->headers, octstr_imm("Message-ID"));
|
|
|
|
if (s) {
|
|
|
|
octstr_replace(s, octstr_imm("<"), octstr_imm(""));
|
|
|
|
octstr_replace(s, octstr_imm(">"), octstr_imm(""));
|
2007-05-08 08:24:19 +00:00
|
|
|
if (octstr_get_char(s, 0) == '"') {
|
|
|
|
octstr_delete(s, 0, 1);
|
|
|
|
octstr_delete(s, octstr_len(s)-1, 1);
|
|
|
|
}
|
2007-03-28 12:13:44 +00:00
|
|
|
http_header_remove_all(m->headers, "Message-ID");
|
|
|
|
http_header_add(m->headers, "Message-ID", octstr_get_cstr(s));
|
|
|
|
m->msgId = octstr_duplicate(s);
|
|
|
|
octstr_destroy(s);
|
|
|
|
}
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
/* Default type is send */
|
2007-01-30 17:06:29 +00:00
|
|
|
if ((s = http_header_value(m->headers, octstr_imm("X-Mms-Message-Type"))) == NULL ||
|
|
|
|
octstr_compare(s, octstr_imm("MM4_forward.REQ")) == 0) {
|
|
|
|
http_header_remove_all(m->headers, "X-Mms-Message-Type");
|
2005-03-10 08:01:02 +00:00
|
|
|
http_header_add(m->headers, "X-Mms-Message-Type",
|
2005-04-19 09:11:43 +00:00
|
|
|
(char *)mms_message_type_to_cstr(MMS_MSGTYPE_SEND_REQ));
|
2005-03-10 08:01:02 +00:00
|
|
|
m->message_type = MMS_MSGTYPE_SEND_REQ;
|
2007-01-30 17:06:29 +00:00
|
|
|
if (s)
|
|
|
|
octstr_destroy(s);
|
2005-03-10 08:01:02 +00:00
|
|
|
} else {
|
|
|
|
m->message_type = mms_string_to_message_type(s);
|
|
|
|
if (m->message_type < 0) {
|
2008-09-04 17:20:42 +00:00
|
|
|
mms_error(0, NULL, NULL, "Unknown message type: %s while parsing mime entity.", octstr_get_cstr(s));
|
2005-03-10 08:01:02 +00:00
|
|
|
octstr_destroy(s);
|
|
|
|
goto failed;
|
|
|
|
}
|
|
|
|
octstr_destroy(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((s = http_header_value(m->headers, octstr_imm("X-Mms-MMS-Version"))) == NULL)
|
2005-03-16 05:04:03 +00:00
|
|
|
http_header_add(m->headers, "X-Mms-MMS-Version", MMS_DEFAULT_VERSION);
|
2005-03-10 08:01:02 +00:00
|
|
|
else
|
|
|
|
octstr_destroy(s);
|
|
|
|
|
2007-05-08 08:24:19 +00:00
|
|
|
/* 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"));
|
|
|
|
|
|
|
|
/* rebuild headers, skipping bad ones. */
|
|
|
|
h = http_create_empty_headers();
|
|
|
|
for (i = 0; i<gwlist_len(m->headers); 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);
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
2007-05-08 08:24:19 +00:00
|
|
|
http_destroy_headers(m->headers);
|
|
|
|
m->headers = h;
|
2005-03-10 08:01:02 +00:00
|
|
|
/* 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
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* XXXX Also need to validate this message a bit better. */
|
|
|
|
fixup_msg(m, octstr_imm("anon@unknown"));
|
|
|
|
|
|
|
|
return m;
|
|
|
|
|
|
|
|
failed:
|
|
|
|
mms_destroy(m);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void mms_destroy(MmsMsg *msg)
|
|
|
|
{
|
|
|
|
|
2006-02-24 05:15:26 +00:00
|
|
|
if (!msg)
|
|
|
|
return;
|
2005-03-10 08:01:02 +00:00
|
|
|
if (msg->ismultipart)
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_destroy(msg->body.l, (gwlist_item_destructor_t *)mime_entity_destroy);
|
2005-03-10 08:01:02 +00:00
|
|
|
else if (msg->body.s)
|
|
|
|
octstr_destroy(msg->body.s);
|
|
|
|
http_destroy_headers(msg->headers);
|
2005-03-21 16:11:51 +00:00
|
|
|
if (msg->msgId)
|
|
|
|
octstr_destroy(msg->msgId);
|
2005-03-10 08:01:02 +00:00
|
|
|
gw_free(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
List *mms_message_headers(MmsMsg *msg)
|
|
|
|
{
|
|
|
|
|
2006-02-24 05:15:26 +00:00
|
|
|
gw_assert(msg);
|
2005-03-10 08:01:02 +00:00
|
|
|
return http_header_duplicate(msg->headers);
|
|
|
|
}
|
|
|
|
|
2005-04-14 11:27:23 +00:00
|
|
|
MmsMsg *mms_readreport(Octstr *msgid, Octstr *from, Octstr *to, time_t date, Octstr *status)
|
|
|
|
{
|
|
|
|
|
2006-02-24 05:15:26 +00:00
|
|
|
MmsMsg *m;
|
2005-04-14 11:27:23 +00:00
|
|
|
Octstr *s;
|
|
|
|
|
2006-02-24 05:15:26 +00:00
|
|
|
|
|
|
|
m = gw_malloc(sizeof *m);
|
2005-04-14 11:27:23 +00:00
|
|
|
m->ismultipart = 0;
|
|
|
|
m->headers = http_create_empty_headers();
|
|
|
|
|
|
|
|
m->message_type = MMS_MSGTYPE_READ_ORIG_IND;
|
|
|
|
m->body.s = NULL;
|
|
|
|
m->msgId = octstr_duplicate(msgid ? msgid : octstr_imm("none"));
|
|
|
|
|
|
|
|
/* Now append headers. */
|
|
|
|
|
|
|
|
http_header_add(m->headers, "X-Mms-Message-Type", "m-read-orig-ind");
|
|
|
|
http_header_add(m->headers, "X-Mms-MMS-Version", MMS_DEFAULT_VERSION);
|
|
|
|
|
|
|
|
http_header_add(m->headers, "Message-ID", msgid ? octstr_get_cstr(msgid) : "none");
|
|
|
|
http_header_add(m->headers, "To", octstr_get_cstr(to));
|
|
|
|
|
|
|
|
http_header_add(m->headers, "From", octstr_get_cstr(from));
|
|
|
|
|
|
|
|
s = date_format_http(date);
|
|
|
|
http_header_add(m->headers, "Date", octstr_get_cstr(s));
|
|
|
|
|
|
|
|
http_header_add(m->headers, "X-Mms-Status", octstr_get_cstr(status));
|
|
|
|
|
|
|
|
octstr_destroy(s);
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2008-08-06 17:45:08 +00:00
|
|
|
MmsMsg *mms_deliveryreport(Octstr *msgid, Octstr *from, Octstr *to, time_t date, Octstr *status)
|
2005-03-10 08:01:02 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
MmsMsg *m = gw_malloc(sizeof *m);
|
|
|
|
Octstr *s;
|
|
|
|
|
|
|
|
|
|
|
|
m->ismultipart = 0;
|
|
|
|
m->headers = http_create_empty_headers();
|
|
|
|
|
|
|
|
m->message_type = MMS_MSGTYPE_DELIVERY_IND;
|
|
|
|
m->body.s = NULL;
|
2005-04-14 11:27:23 +00:00
|
|
|
m->msgId = octstr_duplicate(msgid ? msgid : octstr_imm("none"));
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
/* Now append headers. */
|
|
|
|
|
|
|
|
http_header_add(m->headers, "X-Mms-Message-Type", "m-delivery-ind");
|
2005-03-16 05:04:03 +00:00
|
|
|
http_header_add(m->headers, "X-Mms-MMS-Version", MMS_DEFAULT_VERSION);
|
2005-03-21 16:11:51 +00:00
|
|
|
|
|
|
|
http_header_add(m->headers, "Message-ID", msgid ? octstr_get_cstr(msgid) : "none");
|
2008-08-06 17:45:08 +00:00
|
|
|
if (to)
|
|
|
|
http_header_add(m->headers, "To", octstr_get_cstr(to));
|
|
|
|
if (from)
|
|
|
|
http_header_add(m->headers, "From", octstr_get_cstr(from));
|
2005-03-10 08:01:02 +00:00
|
|
|
s = date_format_http(date);
|
|
|
|
http_header_add(m->headers, "Date", octstr_get_cstr(s));
|
|
|
|
|
|
|
|
http_header_add(m->headers, "X-Mms-Status", octstr_get_cstr(status));
|
|
|
|
|
|
|
|
octstr_destroy(s);
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2008-12-24 19:00:30 +00:00
|
|
|
MmsMsg *mms_notification(Octstr *from, Octstr *subject,
|
|
|
|
Octstr *mclass,
|
|
|
|
unsigned int msize, Octstr *url,
|
2005-03-16 05:16:09 +00:00
|
|
|
Octstr *transactionid, time_t expiryt, int optimizesize)
|
2005-03-10 08:01:02 +00:00
|
|
|
{
|
|
|
|
MmsMsg *m = gw_malloc(sizeof *m);
|
|
|
|
char buf[10];
|
|
|
|
|
|
|
|
time_t tnow = time(NULL);
|
|
|
|
|
|
|
|
m->ismultipart = 0;
|
|
|
|
m->msgId = NULL;
|
|
|
|
m->body.s = NULL;
|
|
|
|
m->headers = http_create_empty_headers();
|
|
|
|
m->message_type = MMS_MSGTYPE_NOTIFICATION_IND;
|
|
|
|
|
|
|
|
http_header_add(m->headers, "X-Mms-Message-Type", "m-notification-ind");
|
|
|
|
http_header_add(m->headers, "X-Mms-Transaction-ID",
|
|
|
|
octstr_get_cstr(transactionid));
|
2005-03-16 05:04:03 +00:00
|
|
|
http_header_add(m->headers, "X-Mms-MMS-Version", MMS_DEFAULT_VERSION);
|
2008-12-24 19:00:30 +00:00
|
|
|
|
|
|
|
if (from)
|
|
|
|
http_header_add(m->headers, "From", octstr_get_cstr(from));
|
2005-03-10 08:01:02 +00:00
|
|
|
|
2009-05-06 05:12:32 +00:00
|
|
|
if (subject && !optimizesize)
|
2008-12-24 19:00:30 +00:00
|
|
|
http_header_add(m->headers, "Subject", octstr_get_cstr(subject));
|
|
|
|
|
|
|
|
http_header_add(m->headers, "X-Mms-Message-Class",
|
|
|
|
mclass ? octstr_get_cstr(mclass) : "Personal");
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
sprintf(buf, "%d", msize);
|
|
|
|
http_header_add(m->headers, "X-Mms-Message-Size", buf);
|
|
|
|
|
|
|
|
#define LARGET 365*24*3600
|
|
|
|
|
|
|
|
sprintf(buf, "%ld", expiryt ? expiryt - tnow : LARGET);
|
|
|
|
http_header_add(m->headers, "X-Mms-Expiry", buf);
|
|
|
|
|
|
|
|
|
|
|
|
/* No reply charge stuff for now. */
|
|
|
|
|
|
|
|
http_header_add(m->headers, "X-Mms-Content-Location", octstr_get_cstr(url));
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
MmsMsg *mms_retrieveconf(MmsMsg *msg, Octstr *transactionid,
|
2005-03-21 16:11:51 +00:00
|
|
|
char *err, char *errtxt, Octstr *opt_from,
|
|
|
|
int menc)
|
2005-03-10 08:01:02 +00:00
|
|
|
{
|
|
|
|
MmsMsg *m;
|
|
|
|
|
|
|
|
m = gw_malloc(sizeof *m);
|
2005-11-15 05:23:47 +00:00
|
|
|
m->msgId = msg ? octstr_duplicate(msg->msgId) : octstr_imm("00000");
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
m->headers = http_create_empty_headers();
|
|
|
|
m->message_type = MMS_MSGTYPE_RETRIEVE_CONF;
|
|
|
|
|
|
|
|
http_header_add(m->headers, "X-Mms-Message-Type", "m-retrieve-conf");
|
|
|
|
if (transactionid)
|
|
|
|
http_header_add(m->headers, "X-Mms-Transaction-ID",
|
|
|
|
octstr_get_cstr(transactionid));
|
2005-03-21 16:11:51 +00:00
|
|
|
|
|
|
|
if (menc >= MS_1_2)
|
|
|
|
http_header_add(m->headers, "X-Mms-MMS-Version", "1.2");
|
|
|
|
else
|
|
|
|
http_header_add(m->headers, "X-Mms-MMS-Version", MMS_DEFAULT_VERSION);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
if (!msg) {
|
|
|
|
Octstr *x = date_format_http(time(NULL));
|
|
|
|
|
|
|
|
m->ismultipart = 0;
|
|
|
|
|
|
|
|
http_header_add(m->headers, "Date", octstr_get_cstr(x));
|
|
|
|
http_header_add(m->headers, "X-Mms-Retrieve-Status",err);
|
|
|
|
if (err)
|
|
|
|
http_header_add(m->headers, "X-Mms-Retrieve-Text",err);
|
|
|
|
if (opt_from)
|
|
|
|
http_header_add(m->headers, "From", octstr_get_cstr(opt_from));
|
|
|
|
http_header_add(m->headers, "Content-Type", "text/plain");
|
|
|
|
|
|
|
|
if (errtxt)
|
|
|
|
m->body.s = octstr_create(errtxt);
|
|
|
|
else
|
|
|
|
m->body.s = octstr_create(" ");
|
|
|
|
|
|
|
|
octstr_destroy(x);
|
|
|
|
} else { /* Otherwise copy from message. */
|
|
|
|
List *h = mms_message_headers(msg);
|
|
|
|
int i, n;
|
|
|
|
|
|
|
|
#if 0 /* Some phones do not like this header! */
|
|
|
|
http_header_add(m->headers, "X-Mms-Retrieve-Status", "Ok");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
http_header_combine(h, m->headers);
|
|
|
|
http_destroy_headers(m->headers);
|
|
|
|
m->headers = h;
|
|
|
|
|
|
|
|
m->ismultipart = msg->ismultipart;
|
|
|
|
|
|
|
|
if (!m->ismultipart)
|
|
|
|
m->body.s = octstr_duplicate(msg->body.s);
|
|
|
|
else
|
|
|
|
/* Body is a list of MIMEEntities, so recreate it. */
|
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
for (m->body.l = gwlist_create(), i = 0,
|
|
|
|
n = gwlist_len(msg->body.l);
|
2005-03-10 08:01:02 +00:00
|
|
|
i<n; i++)
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_append(m->body.l,
|
|
|
|
mime_entity_duplicate(gwlist_get(msg->body.l, i)));
|
2006-09-06 11:49:23 +00:00
|
|
|
/* Remove some headers that may not be permitted. */
|
|
|
|
mms_remove_headers(m, "X-Mms-Expiry");
|
|
|
|
mms_remove_headers(m, "X-Mms-Delivery-Time");
|
|
|
|
mms_remove_headers(m, "X-Mms-Sender-Visibility");
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
int mms_remove_headers(MmsMsg *m, char *name)
|
|
|
|
{
|
2006-02-24 05:15:26 +00:00
|
|
|
gw_assert(m);
|
2005-03-10 08:01:02 +00:00
|
|
|
http_header_remove_all(m->headers, name);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-03-21 16:11:51 +00:00
|
|
|
MmsMsg *mms_sendconf(char *errstr, char *msgid, char *transid, int isforward, int menc)
|
2005-03-10 08:01:02 +00:00
|
|
|
{
|
|
|
|
MmsMsg *m = gw_malloc(sizeof *m);
|
|
|
|
|
|
|
|
|
|
|
|
m->ismultipart = 0;
|
|
|
|
m->msgId = msgid ? octstr_create(msgid) : NULL;
|
|
|
|
m->body.s = NULL;
|
|
|
|
|
|
|
|
m->headers = http_create_empty_headers();
|
|
|
|
|
|
|
|
if (!isforward) {
|
|
|
|
m->message_type = MMS_MSGTYPE_SEND_CONF;
|
|
|
|
http_header_add(m->headers, "X-Mms-Message-Type", "m-send-conf");
|
|
|
|
} else {
|
|
|
|
m->message_type = MMS_MSGTYPE_FORWARD_CONF;
|
|
|
|
http_header_add(m->headers, "X-Mms-Message-Type", "m-forward-conf");
|
|
|
|
}
|
|
|
|
http_header_add(m->headers, "X-Mms-Transaction-ID", transid);
|
2005-03-21 16:11:51 +00:00
|
|
|
|
|
|
|
if (menc >= MS_1_2)
|
|
|
|
http_header_add(m->headers, "X-Mms-MMS-Version", "1.2");
|
|
|
|
else
|
|
|
|
http_header_add(m->headers, "X-Mms-MMS-Version", MMS_DEFAULT_VERSION);
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
http_header_add(m->headers, "X-Mms-Response-Status", errstr);
|
|
|
|
|
|
|
|
if (msgid)
|
|
|
|
http_header_add(m->headers, "Message-ID", msgid);
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2007-09-25 06:03:48 +00:00
|
|
|
MmsMsg *mms_notifyresp_ind(char *transid, int menc, char *status, int report_allowed)
|
|
|
|
{
|
|
|
|
MmsMsg *m = gw_malloc(sizeof *m);
|
|
|
|
|
|
|
|
|
|
|
|
m->ismultipart = 0;
|
|
|
|
m->msgId = NULL;
|
|
|
|
m->body.s = NULL;
|
|
|
|
|
|
|
|
m->headers = http_create_empty_headers();
|
|
|
|
|
|
|
|
m->message_type = MMS_MSGTYPE_NOTIFYRESP;
|
|
|
|
http_header_add(m->headers, "X-Mms-Message-Type", "m-notifyresp-ind");
|
|
|
|
http_header_add(m->headers, "X-Mms-Transaction-ID", transid);
|
|
|
|
|
|
|
|
if (menc >= MS_1_2)
|
|
|
|
http_header_add(m->headers, "X-Mms-MMS-Version", "1.2");
|
|
|
|
else
|
|
|
|
http_header_add(m->headers, "X-Mms-MMS-Version", MMS_DEFAULT_VERSION);
|
|
|
|
|
|
|
|
|
|
|
|
http_header_add(m->headers, "X-Mms-Status", status);
|
|
|
|
http_header_add(m->headers, "X-Mms-Report-Allowed", report_allowed ? "Yes" : "No");
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2006-07-17 06:52:10 +00:00
|
|
|
int mms_make_sendreq(MmsMsg *retrieveconf)
|
|
|
|
{
|
|
|
|
|
|
|
|
gw_assert(retrieveconf);
|
|
|
|
|
|
|
|
if (retrieveconf->message_type == MMS_MSGTYPE_SEND_REQ)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
gw_assert(retrieveconf->message_type == MMS_MSGTYPE_RETRIEVE_CONF);
|
|
|
|
|
|
|
|
retrieveconf->message_type = MMS_MSGTYPE_SEND_REQ;
|
|
|
|
mms_replace_header_value(retrieveconf, "X-Mms-Message-Type",
|
|
|
|
(char *)mms_message_type_to_cstr(MMS_MSGTYPE_SEND_REQ));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2005-03-10 08:01:02 +00:00
|
|
|
|
|
|
|
int mms_replace_header_value(MmsMsg *msg, char *hname, char *value)
|
|
|
|
{
|
2006-02-24 05:15:26 +00:00
|
|
|
gw_assert(msg);
|
2005-03-10 08:01:02 +00:00
|
|
|
http_header_remove_all(msg->headers, hname);
|
|
|
|
http_header_add(msg->headers, hname, value);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-04-14 11:27:23 +00:00
|
|
|
int mms_add_missing_headers(MmsMsg *msg, List *headers)
|
|
|
|
{
|
2006-02-24 05:15:26 +00:00
|
|
|
List *h;
|
|
|
|
|
|
|
|
gw_assert(msg);
|
|
|
|
h = http_header_duplicate(headers);
|
2005-04-14 11:27:23 +00:00
|
|
|
http_header_combine(h, msg->headers);
|
|
|
|
|
|
|
|
http_destroy_headers(msg->headers);
|
|
|
|
msg->headers = h;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-03-19 06:46:24 +00:00
|
|
|
int mms_replace_header_values(MmsMsg *msg, char *hname, List *value)
|
|
|
|
{
|
|
|
|
int i;
|
2006-02-24 05:15:26 +00:00
|
|
|
|
|
|
|
gw_assert(msg);
|
2005-03-19 06:46:24 +00:00
|
|
|
http_header_remove_all(msg->headers, hname);
|
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
for (i = 0; i < gwlist_len(value); i++) {
|
|
|
|
Octstr *x = gwlist_get(value, i);
|
2005-03-19 06:46:24 +00:00
|
|
|
http_header_add(msg->headers, hname, octstr_get_cstr(x));
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
Octstr *mms_get_header_value(MmsMsg *msg, Octstr *header)
|
|
|
|
{
|
2006-02-24 05:15:26 +00:00
|
|
|
gw_assert(msg);
|
2007-08-27 15:31:23 +00:00
|
|
|
return http_header_value(msg->headers, header);
|
2005-03-10 08:01:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-03-19 06:46:24 +00:00
|
|
|
List *mms_get_header_values(MmsMsg *msg, Octstr *header)
|
|
|
|
{
|
2006-02-24 05:15:26 +00:00
|
|
|
List *h;
|
|
|
|
List *l;
|
|
|
|
int i;
|
2005-03-19 06:46:24 +00:00
|
|
|
|
2006-02-24 05:15:26 +00:00
|
|
|
gw_assert(msg);
|
2006-10-12 15:21:46 +00:00
|
|
|
l = gwlist_create();
|
2006-02-24 05:15:26 +00:00
|
|
|
h = http_header_find_all(msg->headers, octstr_get_cstr(header));
|
2006-10-12 15:21:46 +00:00
|
|
|
for (i = 0; i < gwlist_len(h); i++) {
|
2005-03-19 06:46:24 +00:00
|
|
|
Octstr *hname, *value;
|
|
|
|
|
|
|
|
http_header_get(h, i, &hname, &value);
|
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_append(l, value);
|
2005-03-19 06:46:24 +00:00
|
|
|
octstr_destroy(hname);
|
|
|
|
}
|
|
|
|
http_destroy_headers(h);
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
int mms_convert_readrec2readorig(MmsMsg *msg)
|
|
|
|
{
|
2005-04-14 11:27:23 +00:00
|
|
|
Octstr *s;
|
|
|
|
|
2006-02-24 05:15:26 +00:00
|
|
|
gw_assert(msg);
|
2005-03-10 08:01:02 +00:00
|
|
|
if (msg->message_type != MMS_MSGTYPE_READ_REC_IND)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
mms_replace_header_value(msg, "X-Mms-Message-Type", "m-read-orig-ind");
|
|
|
|
msg->message_type = MMS_MSGTYPE_READ_ORIG_IND;
|
2005-04-14 11:27:23 +00:00
|
|
|
|
|
|
|
if ((s = mms_get_header_value(msg, octstr_imm("Date"))) == NULL) {
|
|
|
|
time_t t = time(NULL);
|
|
|
|
s = date_format_http(t);
|
|
|
|
mms_replace_header_value(msg, "Date", octstr_get_cstr(s));
|
2007-08-27 15:31:23 +00:00
|
|
|
}
|
|
|
|
octstr_destroy(s);
|
2005-04-14 11:27:23 +00:00
|
|
|
|
2005-03-10 08:01:02 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2005-03-21 16:11:51 +00:00
|
|
|
|
|
|
|
MmsMsg *mms_storeconf(char *errstr, char *transid, Octstr *msgloc, int isupload, int menc)
|
|
|
|
{
|
|
|
|
MmsMsg *m = gw_malloc(sizeof *m);
|
|
|
|
|
|
|
|
|
|
|
|
m->ismultipart = 0;
|
|
|
|
m->msgId = NULL;
|
|
|
|
m->body.s = NULL;
|
|
|
|
|
|
|
|
m->headers = http_create_empty_headers();
|
|
|
|
|
|
|
|
if (!isupload) {
|
|
|
|
m->message_type = MMS_MSGTYPE_MBOX_STORE_CONF;
|
|
|
|
http_header_add(m->headers, "X-Mms-Message-Type", "m-mbox-store-conf");
|
|
|
|
} else {
|
|
|
|
m->message_type = MMS_MSGTYPE_MBOX_UPLOAD_CONF;
|
|
|
|
http_header_add(m->headers, "X-Mms-Message-Type", "m-mbox-upload-conf");
|
|
|
|
}
|
2007-08-27 15:31:23 +00:00
|
|
|
http_header_add(m->headers, "X-Mms-Transaction-ID", transid);
|
|
|
|
http_header_add(m->headers, "X-Mms-MMS-Version", "1.2"); /* ignore menc for now. */
|
2005-03-21 16:11:51 +00:00
|
|
|
http_header_add(m->headers, "X-Mms-Store-Status", errstr);
|
|
|
|
|
|
|
|
if (msgloc)
|
|
|
|
http_header_add(m->headers, "X-Mms-Content-Location", octstr_get_cstr(msgloc));
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
MmsMsg *mms_deleteconf(int menc, char *transid)
|
|
|
|
{
|
|
|
|
MmsMsg *m = gw_malloc(sizeof *m);
|
|
|
|
|
|
|
|
|
|
|
|
m->ismultipart = 0;
|
|
|
|
m->msgId = NULL;
|
|
|
|
m->body.s = NULL;
|
|
|
|
|
|
|
|
m->headers = http_create_empty_headers();
|
|
|
|
m->message_type = MMS_MSGTYPE_MBOX_DELETE_CONF;
|
|
|
|
http_header_add(m->headers, "X-Mms-Message-Type", "m-mbox-delete-conf");
|
|
|
|
|
|
|
|
http_header_add(m->headers, "X-Mms-Transaction-ID", transid);
|
|
|
|
http_header_add(m->headers, "X-Mms-MMS-Version", "1.2"); /* ignore menc for now. */
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2010-10-21 17:51:16 +00:00
|
|
|
int mms_msgsize(MmsMsg *m)
|
2005-03-21 16:11:51 +00:00
|
|
|
{
|
2006-02-24 05:15:26 +00:00
|
|
|
Octstr *s;
|
|
|
|
int n;
|
2005-03-21 16:11:51 +00:00
|
|
|
|
2010-10-26 10:18:13 +00:00
|
|
|
if (m == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2006-02-24 05:15:26 +00:00
|
|
|
s = mms_tobinary(m); /* Dirty, but works... */
|
|
|
|
n = octstr_len(s);
|
2005-03-21 16:11:51 +00:00
|
|
|
octstr_destroy(s);
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mms_convert_to_mboxdescr(MmsMsg *mm, Octstr *cloc, List *reqhdrs,
|
|
|
|
unsigned long msize)
|
|
|
|
{
|
|
|
|
int i, n;
|
|
|
|
List *mh, *xh;
|
|
|
|
Octstr *xstate;
|
2005-04-08 10:29:08 +00:00
|
|
|
int addcontent = 0, hasmsgid = 0;
|
2005-03-21 16:11:51 +00:00
|
|
|
|
|
|
|
if (!mm)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
mh = http_create_empty_headers();
|
|
|
|
|
|
|
|
mm->message_type = MMS_MSGTYPE_MBOX_DESCR;
|
|
|
|
|
|
|
|
http_header_add(mh, "X-Mms-Message-Type", "m-mbox-descr");
|
|
|
|
http_header_add(mh, "X-Mms-MMS-Version", "1.2");
|
2005-04-08 10:29:08 +00:00
|
|
|
http_header_add(mh, "X-Mms-Content-Location", octstr_get_cstr(cloc));
|
2005-03-21 16:11:51 +00:00
|
|
|
|
|
|
|
/* Add only those headers requested. */
|
2006-10-12 15:21:46 +00:00
|
|
|
for (i = 0, n = gwlist_len(reqhdrs); i < n; i++) {
|
|
|
|
Octstr *header = gwlist_get(reqhdrs,i);
|
2005-03-21 16:11:51 +00:00
|
|
|
List *h = http_header_find_all(mm->headers, octstr_get_cstr(header));
|
|
|
|
int j;
|
|
|
|
|
|
|
|
if (octstr_case_compare(header, octstr_imm("Content")) == 0) {
|
|
|
|
addcontent = 1;
|
|
|
|
goto loop;
|
|
|
|
} else if (octstr_case_compare(header, octstr_imm("X-Mms-Message-Size")) == 0) {
|
|
|
|
char yy[64];
|
|
|
|
|
|
|
|
sprintf(yy, "%lu", msize);
|
|
|
|
http_header_add(mh, "X-Mms-Message-Size", yy);
|
|
|
|
goto loop;
|
2005-04-08 10:29:08 +00:00
|
|
|
} else if (octstr_case_compare(header, octstr_imm("Message-ID")) == 0)
|
|
|
|
hasmsgid = 1;
|
2005-03-21 16:11:51 +00:00
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
for (j = 0; j < gwlist_len(h); j++) {
|
2005-03-21 16:11:51 +00:00
|
|
|
Octstr *hname, *value;
|
|
|
|
http_header_get(h, j, &hname, &value);
|
|
|
|
octstr_destroy(hname);
|
|
|
|
|
|
|
|
http_header_add(mh, octstr_get_cstr(header), octstr_get_cstr(value));
|
|
|
|
|
|
|
|
octstr_destroy(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
loop:
|
|
|
|
http_destroy_headers(h);
|
|
|
|
/* We ignore the extra attributes request. */
|
|
|
|
}
|
|
|
|
|
2005-04-08 10:29:08 +00:00
|
|
|
if (!hasmsgid) {
|
|
|
|
Octstr *v = http_header_value(mm->headers, octstr_imm("Message-ID"));
|
|
|
|
if (v) {
|
|
|
|
http_header_add(mh, "Message-ID",
|
|
|
|
octstr_get_cstr(v));
|
|
|
|
octstr_destroy(v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-03-21 16:11:51 +00:00
|
|
|
/* Copy over the MM-State and MM-flags headers. */
|
|
|
|
xh = http_header_find_all(mm->headers, "X-Mms-MM-Flags");
|
|
|
|
if (xh) {
|
|
|
|
http_header_combine(mh,xh);
|
|
|
|
http_destroy_headers(xh);
|
|
|
|
}
|
|
|
|
xstate = http_header_value(mm->headers, octstr_imm("X-Mms-MM-State"));
|
|
|
|
if (xstate) {
|
|
|
|
http_header_remove_all(mh, "X-Mms-MM-State");
|
|
|
|
http_header_add(mh, "X-Mms-MM-State", octstr_get_cstr(xstate));
|
|
|
|
octstr_destroy(xstate);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!addcontent) {
|
|
|
|
if (mm->ismultipart)
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_destroy(mm->body.l, (gwlist_item_destructor_t *)mime_entity_destroy);
|
2005-03-21 16:11:51 +00:00
|
|
|
else if (mm->body.s)
|
|
|
|
octstr_destroy(mm->body.s);
|
|
|
|
mm->body.s = NULL;
|
2005-04-19 09:43:10 +00:00
|
|
|
} else {
|
|
|
|
/* copy over content type. */
|
|
|
|
Octstr *ctype = http_header_value(mm->headers, octstr_imm("Content-Type"));
|
|
|
|
if (ctype) {
|
|
|
|
http_header_add(mh, "Content-Type", octstr_get_cstr(ctype));
|
|
|
|
octstr_destroy(ctype);
|
|
|
|
}
|
2005-03-21 16:11:51 +00:00
|
|
|
}
|
2005-04-19 09:43:10 +00:00
|
|
|
|
|
|
|
http_destroy_headers(mm->headers);
|
|
|
|
mm->headers = mh;
|
2005-03-21 16:11:51 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
MmsMsg *mms_viewconf(char *transid,
|
|
|
|
List *msgrefs,
|
|
|
|
List *msglocs,
|
|
|
|
char *err,
|
|
|
|
List *required_headers,
|
|
|
|
MmsMsgGetFunc_t *getmsg,
|
|
|
|
void *p1, void *p2,
|
|
|
|
int maxsize, int menc,
|
|
|
|
List *otherhdrs)
|
|
|
|
{
|
|
|
|
MmsMsg *m = gw_malloc(sizeof *m);
|
|
|
|
int msize, i, n;
|
|
|
|
int msgcount;
|
|
|
|
|
|
|
|
err = err ? err : "Ok";
|
|
|
|
|
|
|
|
m->ismultipart = 0;
|
|
|
|
m->msgId = NULL;
|
|
|
|
m->body.s = NULL;
|
|
|
|
|
|
|
|
m->headers = http_create_empty_headers();
|
|
|
|
m->message_type = MMS_MSGTYPE_MBOX_VIEW_CONF;
|
|
|
|
http_header_add(m->headers, "X-Mms-Message-Type", "m-mbox-view-conf");
|
|
|
|
|
|
|
|
http_header_add(m->headers, "X-Mms-Transaction-ID", transid);
|
|
|
|
http_header_add(m->headers, "X-Mms-MMS-Version", "1.2"); /* ignore menc for now. */
|
|
|
|
|
|
|
|
/* Put in some dummy headers so count works fine ... */
|
|
|
|
|
|
|
|
http_header_add(m->headers, "X-Mms-Message-Count", "0");
|
|
|
|
http_header_add(m->headers, "Content-Type", "*/*"); /* we'll change this later. */
|
|
|
|
|
|
|
|
http_header_combine(m->headers, otherhdrs); /* add any other hdrs passed. */
|
|
|
|
|
|
|
|
if (msgrefs == NULL ||
|
|
|
|
strcasecmp(err, "ok") != 0) { /* We got an error. */
|
|
|
|
http_header_add(m->headers, "X-Mms-Response-Status",
|
|
|
|
err ? err : "Error-unspecified");
|
|
|
|
return m;
|
|
|
|
} else
|
|
|
|
http_header_add(m->headers, "X-Mms-Response-Status", "Ok");
|
|
|
|
|
|
|
|
msize = mms_msgsize(m);
|
2006-10-12 15:21:46 +00:00
|
|
|
n = gwlist_len(msgrefs);
|
2005-03-21 16:11:51 +00:00
|
|
|
msgcount = 0;
|
|
|
|
|
|
|
|
m->ismultipart = 1;
|
2006-10-12 15:21:46 +00:00
|
|
|
m->body.l = gwlist_create();
|
2005-03-21 16:11:51 +00:00
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
unsigned long tmsize;
|
2006-10-12 15:21:46 +00:00
|
|
|
Octstr *msgref = gwlist_get(msgrefs,i);
|
|
|
|
Octstr *msgloc = gwlist_get(msglocs, i);
|
2005-03-21 16:11:51 +00:00
|
|
|
MmsMsg *mm = getmsg(p1, p2, msgref, &tmsize);
|
|
|
|
Octstr *ms;
|
|
|
|
|
|
|
|
if (mms_convert_to_mboxdescr(mm,
|
|
|
|
msgloc,
|
|
|
|
required_headers, tmsize) != 0)
|
|
|
|
goto loop;
|
|
|
|
|
|
|
|
ms = mms_tobinary(mm);
|
|
|
|
if (octstr_len(ms) + msize <= maxsize) {
|
|
|
|
MIMEEntity *mtmp = mime_entity_create();
|
2006-11-25 11:53:40 +00:00
|
|
|
List *h = mime_entity_headers(mtmp);
|
2005-03-21 16:11:51 +00:00
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
http_header_add(h, "Content-Type",
|
2005-04-19 09:43:10 +00:00
|
|
|
"application/vnd.wap.mms-message");
|
2006-10-12 15:21:46 +00:00
|
|
|
mime_replace_headers(mtmp, h);
|
|
|
|
mime_entity_set_body(mtmp, ms);
|
|
|
|
|
|
|
|
http_destroy_headers(h);
|
2005-03-21 16:11:51 +00:00
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_append(m->body.l, mtmp);
|
2005-03-21 16:11:51 +00:00
|
|
|
msgcount++;
|
|
|
|
msize += octstr_len(ms);
|
|
|
|
} else {
|
|
|
|
i = n; /* force end. */
|
|
|
|
octstr_destroy(ms);
|
|
|
|
}
|
|
|
|
|
|
|
|
mms_destroy(mm);
|
|
|
|
|
|
|
|
loop:(void)0;
|
|
|
|
}
|
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
if (gwlist_len(m->body.l) > 0) {
|
2005-03-21 16:11:51 +00:00
|
|
|
char x[32];
|
2006-10-12 15:21:46 +00:00
|
|
|
sprintf(x, "%d", (int)gwlist_len(m->body.l));
|
2005-03-21 16:11:51 +00:00
|
|
|
mms_replace_header_value(m, "X-Mms-Message-Count", x);
|
|
|
|
mms_replace_header_value(m, "Content-Type", "application/vnd.wap.multipart.mixed");
|
|
|
|
} else {
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_destroy(m->body.l,NULL);
|
2005-03-21 16:11:51 +00:00
|
|
|
m->body.s = NULL;
|
|
|
|
m->ismultipart = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *mms_msgbody(MmsMsg *msg)
|
|
|
|
{
|
|
|
|
if (!msg)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (msg->ismultipart) {
|
2006-10-12 15:21:46 +00:00
|
|
|
List *l = gwlist_create();
|
2005-03-21 16:11:51 +00:00
|
|
|
int i;
|
|
|
|
|
2006-10-12 15:21:46 +00:00
|
|
|
for (i = 0; i < gwlist_len(msg->body.l); i++)
|
|
|
|
gwlist_append(l, mime_entity_duplicate(gwlist_get(msg->body.l,i)));
|
2005-03-21 16:11:51 +00:00
|
|
|
return l;
|
|
|
|
} else
|
|
|
|
return octstr_duplicate(msg->body.s);
|
|
|
|
}
|
|
|
|
|
|
|
|
int mms_clearbody(MmsMsg *msg)
|
|
|
|
{
|
|
|
|
if (!msg)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (msg->ismultipart)
|
2006-10-12 15:21:46 +00:00
|
|
|
gwlist_destroy(msg->body.l, (gwlist_item_destructor_t *)mime_entity_destroy);
|
2005-03-21 16:11:51 +00:00
|
|
|
else if (msg->body.s)
|
|
|
|
octstr_destroy(msg->body.s);
|
|
|
|
msg->body.s = NULL;
|
|
|
|
msg->ismultipart = 0;
|
|
|
|
http_header_remove_all(msg->headers, "Content-Type");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int mms_putbody(MmsMsg *msg, void *body, int ismultipart)
|
|
|
|
{
|
2006-02-24 05:15:26 +00:00
|
|
|
gw_assert(msg);
|
2005-03-21 16:11:51 +00:00
|
|
|
mms_clearbody(msg);
|
|
|
|
|
|
|
|
msg->ismultipart = ismultipart;
|
|
|
|
msg->body.s = body;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|