From e30df1e560ff2351c011bf75dd87f4174df6fe48 Mon Sep 17 00:00:00 2001 From: bagyenda <> Date: Mon, 21 Mar 2005 16:11:51 +0000 Subject: [PATCH] MMbox code, now (mostly) up to speed. --- mbuni/mmlib/mms_mmbox.c | 146 +++++-- mbuni/mmlib/mms_mmbox.h | 13 +- mbuni/mmlib/mms_msg.c | 442 ++++++++++++++++++-- mbuni/mmlib/mms_msg.h | 40 +- mbuni/mmlib/mms_strings.def | 4 +- mbuni/mmlib/mms_uaprof.c | 5 + mbuni/mmlib/mms_uaprof.h | 1 + mbuni/mmlib/mms_util.c | 46 ++- mbuni/mmlib/mms_util.h | 14 +- mbuni/mmsc/mmsfromemail.c | 4 +- mbuni/mmsc/mmsglobalsender.c | 4 +- mbuni/mmsc/mmsmobilesender.c | 6 +- mbuni/mmsc/mmsproxy.c | 762 ++++++++++++++++++++++++++++++----- mbuni/mmsc/mmssend.c | 45 +-- 14 files changed, 1287 insertions(+), 245 deletions(-) diff --git a/mbuni/mmlib/mms_mmbox.c b/mbuni/mmlib/mms_mmbox.c index a5a9214..f1912a8 100644 --- a/mbuni/mmlib/mms_mmbox.c +++ b/mbuni/mmlib/mms_mmbox.c @@ -254,7 +254,7 @@ static char *skip_space(char *s) * df state flag1 flag2 flag3 ... */ static int update_mmbox_index(int fd, char *mmbox_dir, int cmd, - Octstr *df, Octstr *state, List *flags) + Octstr *df, Octstr *state, List *flags, long msgsize) { char fbuf[256], linbuf[1024]; int tempfd; @@ -297,22 +297,25 @@ static int update_mmbox_index(int fd, char *mmbox_dir, int cmd, char idx[128], xstate[32]; Octstr *outs = NULL; int i; - - sscanf(linbuf, "%s %s%n", idx, xstate, &i); + int size; + + sscanf(linbuf, "%s %s %d%n", idx, xstate, &size, &i); if (df && octstr_str_compare(df, idx) == 0) if (cmd == ITEM_DEL || cmd == ITEM_ADD) goto loop; /* Skip it. */ else { /* MOD. */ Octstr *p = linearise_string_list(flags, " "); - outs = octstr_format("%S %S %S\n", df, state, p); + outs = octstr_format("%S %S %d %S\n", df, state, msgsize, p); octstr_destroy(p); } else { /* Copy out as-is */ - outs = octstr_format("%s %s %s%s", + char *p = skip_space(linbuf + i); + outs = octstr_format("%s %s %d %s%s", idx, xstate, - skip_space(linbuf + i), - (strchr(linbuf+i, '\n') >= 0 ? "" : "\n")); + size, + p, + (strchr(p, '\n') != NULL ? "" : "\n")); } loop: if (outs) { @@ -324,7 +327,7 @@ static int update_mmbox_index(int fd, char *mmbox_dir, int cmd, if (cmd == ITEM_ADD) { /* Finally, for ADD, just add it. */ Octstr *s, *p = linearise_string_list(flags, " "); - s = octstr_format("%S %S %S\n", df, state, p); + s = octstr_format("%S %S %d %S\n", df, state, msgsize, p); octstr_destroy(p); octstr_write_to_socket(tempfd, s); octstr_destroy(s); @@ -384,14 +387,15 @@ static List *make_mm_flags(List *oflags, List *flag_cmds) return l; } -Octstr *mms_mmbox_addmsg(char *mmbox_root, char *user, MmsMsg *msg, Octstr *dfltstate) +Octstr *mms_mmbox_addmsg(char *mmbox_root, char *user, MmsMsg *msg, List *flag_cmds, Octstr *dfltstate) { int ifd = -1, nifd, dfd = -1; char df[128]; Octstr *home = user_mmbox_dir(mmbox_root,user); Octstr *s = octstr_create(""), *sdf = NULL; - List *flag_cmds = NULL, *flags = NULL; + List *flags = NULL; Octstr *state = NULL; + int msize; if (!home) goto done; @@ -407,20 +411,21 @@ Octstr *mms_mmbox_addmsg(char *mmbox_root, char *user, MmsMsg *msg, Octstr *dflt } state = mms_get_header_value(msg, octstr_imm("X-Mms-MM-State")); - flag_cmds = mms_get_header_values(msg, octstr_imm("X-Mms-MM-Flags")); + flags = make_mm_flags(mms_get_header_values(msg, octstr_imm("X-Mms-MM-Flags")), flag_cmds); if (state == NULL) state = dfltstate ? octstr_duplicate(dfltstate) : octstr_create("Sent"); - flags = make_mm_flags(NULL, flag_cmds); mms_replace_header_values(msg, "X-Mms-MM-Flags", flags); mms_replace_header_value(msg, "X-Mms-MM-State", octstr_get_cstr(state)); - s = mms_tobinary(msg); + s = mms_tobinary(msg); + msize = octstr_len(s); + octstr_write_to_socket(dfd, s); sdf = octstr_create(df); - if ((nifd = update_mmbox_index(ifd, octstr_get_cstr(home), ITEM_ADD, sdf, state, flags)) < 0 ) { + if ((nifd = update_mmbox_index(ifd, octstr_get_cstr(home), ITEM_ADD, sdf, state, flags, msize)) < 0 ) { char fbuf[256]; sprintf(fbuf, "%s/%s", octstr_get_cstr(home), df); unlink(fbuf); @@ -445,8 +450,6 @@ Octstr *mms_mmbox_addmsg(char *mmbox_root, char *user, MmsMsg *msg, Octstr *dflt octstr_destroy(state); if (flags) list_destroy(flags, (list_item_destructor_t *)octstr_destroy); - if (flag_cmds) - list_destroy(flag_cmds, (list_item_destructor_t *)octstr_destroy); return sdf; } @@ -464,6 +467,7 @@ int mms_mmbox_modmsg(char *mmbox_root, char *user, Octstr *msgref, int ifd = -1, nifd, tmpfd = -1; MmsMsg *m = NULL; int res = -1; + int msize; octstr_replace(sdf, octstr_imm("-"), octstr_imm("/")); @@ -511,13 +515,14 @@ int mms_mmbox_modmsg(char *mmbox_root, char *user, Octstr *msgref, goto done; s = mms_tobinary(m); + msize = octstr_len(s); octstr_write_to_socket(tmpfd, s); rename(octstr_get_cstr(ftmp), octstr_get_cstr(fname)); close(tmpfd); - if ((nifd = update_mmbox_index(ifd, octstr_get_cstr(home), ITEM_MOD, sdf, nstate, flags)) < 0) { + if ((nifd = update_mmbox_index(ifd, octstr_get_cstr(home), ITEM_MOD, sdf, nstate, flags, msize)) < 0) { /* Not good, we wrote but could not update the index file. scream. */ error(0, "mmbox.mod: failed to update index file, home is %s!", octstr_get_cstr(home)); @@ -575,7 +580,7 @@ int mms_mmbox_delmsg(char *mmbox_root, char *user, Octstr *msgref) fname = octstr_format("%S/%S", home, sdf); - if ((nifd = update_mmbox_index(ifd, octstr_get_cstr(home), ITEM_DEL, sdf, NULL, NULL)) < 0) { + if ((nifd = update_mmbox_index(ifd, octstr_get_cstr(home), ITEM_DEL, sdf, NULL, NULL,0)) < 0) { error(0, "mmbox.del: failed to update index file, home is %s!", octstr_get_cstr(home)); @@ -621,8 +626,19 @@ static int _x_octstr_str_compare(Octstr *s, char *p) { return (octstr_str_compare(s,p) == 0); } + +static void replace_slash(char s[]) +{ + while (*s) + if (*s == '/') + *s++ = '-'; + else + s++; +} + List *mms_mmbox_search(char *mmbox_root, char *user, - List *state, List *flag_cmds, int start, int limit) + List *state, List *flag_cmds, int start, int limit, + List *msgrefs) { int tmpfd = -1; FILE *fp = NULL; @@ -655,21 +671,35 @@ List *mms_mmbox_search(char *mmbox_root, char *user, while (fgets(linbuf, sizeof linbuf, fp) != NULL) { char idx[128], xstate[32]; List *xflags = NULL; - int i; + int i, size; + + int match = (!state && (!msgrefs || list_len(msgrefs) == 0) && (!xflags || list_len(xflags) == 0)); - sscanf(linbuf, "%s %s%n", idx, xstate, &i); + sscanf(linbuf, "%s %s %d%n", idx, xstate, &size, &i); - /* search. */ - if ((!state || list_search(state, xstate, - (list_item_matches_t *)_x_octstr_str_compare) != NULL) && - (!flag_cmds || list_len(flag_cmds) == 0 || + /* search: by id list if given, by states if given, by flags if given */ + if (!match && state && list_search(state, xstate, + (list_item_matches_t *)_x_octstr_str_compare) != NULL) + match = 1; + + /* For the rest we only match if nothing else matched. Save time */ + replace_slash(idx); + if (!match && msgrefs && + list_search(msgrefs, idx, + (list_item_matches_t *)_x_octstr_str_compare) != NULL) + match = 1; + + if (!match && + flag_cmds && ((xflags = parse_string_list(linbuf + i)) != NULL && - list_search(xflags, flags, (list_item_matches_t *)string_in_list) != NULL))) - if (ct >= start && ct <= limit) { + list_search(xflags, flags, (list_item_matches_t *)string_in_list) != NULL)) + match = 1; + + if (match && ct >= start && list_len(dflist) <= limit) { Octstr *x = octstr_create(idx); - octstr_replace(x, octstr_imm("/"), octstr_imm("-")); + /* octstr_replace(x, octstr_imm("/"), octstr_imm("-")); */ list_append(dflist, x); - } + } ct++; if (xflags) list_destroy(xflags, (list_item_destructor_t *)octstr_destroy); @@ -693,7 +723,7 @@ List *mms_mmbox_search(char *mmbox_root, char *user, return dflist; } -MmsMsg *mms_mmbox_get(char *mmbox_root, char *user, Octstr *msgref) +MmsMsg *mms_mmbox_get(char *mmbox_root, char *user, Octstr *msgref, unsigned long *msize) { Octstr *sdf = octstr_duplicate(msgref); Octstr *fname = NULL, *home = user_mmbox_dir(mmbox_root,user); @@ -701,7 +731,6 @@ MmsMsg *mms_mmbox_get(char *mmbox_root, char *user, Octstr *msgref) int ifd = -1; MmsMsg *m = NULL; - octstr_replace(sdf, octstr_imm("-"), octstr_imm("/")); if (!home) @@ -715,9 +744,12 @@ MmsMsg *mms_mmbox_get(char *mmbox_root, char *user, Octstr *msgref) fname = octstr_format("%S/%S", home, sdf); s = octstr_read_file(octstr_get_cstr(fname)); - if (s) + if (s) { + if (msize) + *msize = octstr_len(s); m = mms_frombinary(s, octstr_imm("anon@anon")); - + } else if (msize) + *msize = 0; done: if (ifd > 0) close(ifd); @@ -733,3 +765,51 @@ MmsMsg *mms_mmbox_get(char *mmbox_root, char *user, Octstr *msgref) return m; } + +int mms_mmbox_count(char *mmbox_root, char *user, unsigned long *msgcount, unsigned long *byte_count) +{ + + int tmpfd = -1; + FILE *fp = NULL; + char linbuf[1024]; + int ret = -1; + Octstr *home = user_mmbox_dir(mmbox_root,user); + int ifd = -1; + + + ifd = open_mmbox_index(octstr_get_cstr(home),1); + + if (ifd < 0) + goto done; + + if ((tmpfd = dup(ifd)) < 0 || + (fp = fdopen(tmpfd, "r")) == NULL) { + error(0, "mmbox.count: %s Failed to dup descriptor for index " + "file, fp = %d: error = %s\n", octstr_get_cstr(home), + (int)fp, strerror(errno)); + goto done; + } + + *msgcount = 0; + *byte_count = 0; + + while (fgets(linbuf, sizeof linbuf, fp) != NULL) { + int size = 0; + + sscanf(linbuf, "%*s %*s %d", &size); + ++*msgcount; + *byte_count = *byte_count + size; + } + ret = 0; + + done: + if (fp) + fclose(fp); + else if (tmpfd) + close(tmpfd); + + if (ifd > 0) + close(ifd); + + return ret; +} diff --git a/mbuni/mmlib/mms_mmbox.h b/mbuni/mmlib/mms_mmbox.h index ac0c665..881578e 100644 --- a/mbuni/mmlib/mms_mmbox.h +++ b/mbuni/mmlib/mms_mmbox.h @@ -3,12 +3,19 @@ #include "mms_msg.h" /* Initialise the root of the mmbox. Should be called once from load settings. */ int mmbox_root_init(char *mmbox_root); -Octstr *mms_mmbox_addmsg(char *mmbox_root, char *user, MmsMsg *msg, Octstr *dfltstate); +Octstr *mms_mmbox_addmsg(char *mmbox_root, char *user, MmsMsg *msg, List *flag_cmds, Octstr *dfltstate); int mms_mmbox_modmsg(char *mmbox_root, char *user, Octstr *msgref, Octstr *state, List *flag_cmds); int mms_mmbox_delmsg(char *mmbox_root, char *user, Octstr *msgref); List *mms_mmbox_search(char *mmbox_root, char *user, - List *state, List *flag_cmds, int start, int limit); + List *state, List *flag_cmds, int start, int limit, + List *msgrefs); + +MmsMsg *mms_mmbox_get(char *mmbox_root, char *user, Octstr *msgref, unsigned long *msize); +int mms_mmbox_count(char *mmbox_root, char *user, unsigned long *msgcount, + unsigned long *byte_count); + +#define USER_MMBOX_MSG_QUOTA 200000 /* Means nothing at the moment. */ +#define USER_MMBOX_DATA_QUOTA 2000000 /* ditto. */ -MmsMsg *mms_mmbox_get(char *mmbox_root, char *user, Octstr *msgref); #endif diff --git a/mbuni/mmlib/mms_msg.c b/mbuni/mmlib/mms_msg.c index a3c9c37..fd90c26 100644 --- a/mbuni/mmlib/mms_msg.c +++ b/mbuni/mmlib/mms_msg.c @@ -10,7 +10,7 @@ struct MmsMsg { int message_type; Octstr *msgId; List *headers; /* Of type HTTPHeader. */ - + mms_encoding enc; unsigned char ismultipart; union { List *l; @@ -22,6 +22,8 @@ struct MmsMsg { #define SIZHINT 47 static void mm_destroy(MIMEEntity *mx); +static int encode_msgheaders(Octstr *os, List *hdrs); +static int decode_msgheaders(ParseContext *context, List *hdr, Octstr *from, int stop_on_ctype); static inline void pack_short_integer(Octstr *s, int ch) { @@ -73,13 +75,13 @@ int mms_validate_address(Octstr *s) static int decode_multipart(ParseContext *context, List *body) { int i=0, n; - + n = parse_get_uintvar(context); for (i = 0; i 0 ; i++) { int dlen, hlen; MIMEEntity *x = gw_malloc(sizeof *x); - + Octstr *hs; Octstr *content; Octstr *content_type; @@ -91,9 +93,8 @@ static int decode_multipart(ParseContext *context, List *body) parse_limit(context, hlen); - - hs = parse_get_octets(context, parse_octets_left(context)); + x->headers = wsp_headers_unpack(hs, 1); octstr_destroy(hs); @@ -141,18 +142,18 @@ static int decode_multipart(ParseContext *context, List *body) static int encode_multipart(Octstr *os, List *body) { - int i=0, n; + int i, n; n = list_len(body); octstr_append_uintvar(os, n); + i = 0; while (iheaders, 1, WSP_1_3); - + if (x->multiparts && list_len(x->multiparts) > 0) /* This is a multi-part, go down further. */ encode_multipart(mbody, x->multiparts); @@ -221,9 +222,13 @@ static Octstr *decode_encoded_string_value(int ret, ParseContext *context, char return res; } -/* Decodes it, adds to 'unpacked' which is the header list. */ -static void mms_unpack_well_known_field(List *unpacked, int field_type, - ParseContext *context, Octstr *xfrom) +/* 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, + ParseContext *context, + Octstr *xfrom, int msgtype) { int val, ret; char *hname = NULL; @@ -236,7 +241,7 @@ static void mms_unpack_well_known_field(List *unpacked, int field_type, if (parse_error(context)) { warning(0, "Faulty header [code = %d], skipping remaining headers.", field_type); parse_skip_to_limit(context); - return; + return -1; } hname = mms_header_to_cstr(field_type); @@ -257,13 +262,31 @@ static void mms_unpack_well_known_field(List *unpacked, int field_type, octstr_get_cstr(decoded), hname); break; case MMS_HEADER_SUBJECT: - case MMS_HEADER_RESPONSE_TEXT: case MMS_HEADER_RETRIEVE_TEXT: case MMS_HEADER_STORE_STATUS_TEXT: if (ret == WSP_FIELD_VALUE_DATA) decoded = decode_encoded_string_value(ret, context, hname); break; + + 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); + octstr_append(decoded, decode_encoded_string_value(ret2, context, hname)); + + 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; case MMS_HEADER_TRANSACTION_ID: case MMS_HEADER_MESSAGE_ID: case MMS_HEADER_REPLY_CHARGING_ID: @@ -319,10 +342,20 @@ static void mms_unpack_well_known_field(List *unpacked, int field_type, break; case MMS_HEADER_RESPONSE_STATUS: - ch = mms_response_status_to_cstr(val); + if (ret == WSP_FIELD_VALUE_DATA) { + char *x; + int val; + decoded = wsp_unpack_integer_value(context); + wsp_field_value(context, &val); + x = mms_response_status_to_cstr(val|0x80); + + octstr_append_cstr(decoded, x); + + } else + ch = mms_response_status_to_cstr(val|0x80); break; case MMS_HEADER_RETRIEVE_STATUS: - ch = mms_retrieve_status_to_cstr(val); + ch = mms_retrieve_status_to_cstr(val|0x80); break; case MMS_HEADER_STATUS: ch = mms_status_to_cstr(val); @@ -436,7 +469,7 @@ static void mms_unpack_well_known_field(List *unpacked, int field_type, Octstr *pname = NULL, *pval = NULL; ret = wsp_field_value(context, &val); if (ret == WSP_FIELD_VALUE_ENCODED) - pname = mms_descriptor_params_to_string(val); + pname = mms_descriptor_params_to_string(val|0x80); else if (ret == WSP_FIELD_VALUE_NUL_STRING) pname = parse_get_nul_string(context); @@ -498,7 +531,7 @@ static void mms_unpack_well_known_field(List *unpacked, int field_type, ch = mms_mm_state_to_cstr(val); break; case MMS_HEADER_STORE_STATUS: - ch = mms_store_status_to_cstr(val); + ch = mms_store_status_to_cstr(val|0x80); break; default: @@ -523,35 +556,37 @@ static void mms_unpack_well_known_field(List *unpacked, int field_type, http_header_add(unpacked, hname, ch); if (decoded) octstr_destroy(decoded); - return; + return val; value_error: warning(0, "Skipping faulty header [code = %d, val=%d]!", field_type, val); octstr_destroy(decoded); + return -1; } -static int decode_msgheaders(ParseContext *context, MmsMsg *msg, Octstr *from) +static int decode_msgheaders(ParseContext *context, List *hdrs, Octstr *from, int stop_on_ctype) { int fcont = 1; - - gw_assert(msg->headers == NULL); - msg->headers = list_create(); - - mms_strings_init(); /* Just in case. */ + int msgtype = 0; + + gw_assert(hdrs != NULL); while (fcont && parse_octets_left(context) && !parse_error(context)) { int byte = parse_get_char(context); - + int val = 0; if (byte >= 0x80) - mms_unpack_well_known_field(msg->headers, byte&0x7f, context, from); + val = mms_unpack_well_known_field(hdrs, byte&0x7f, context, from, msgtype); else { parse_skip(context, -1); /* Go back a bit. */ - wsp_unpack_app_header(msg->headers, context); + wsp_unpack_app_header(hdrs, context); } - if ((byte&0x7f) == MMS_HEADER_CONTENT_TYPE) + if ((byte&0x7f) == MMS_HEADER_CONTENT_TYPE && + stop_on_ctype) fcont = 0; + if ((byte&0x7f) == MMS_HEADER_MESSAGE_TYPE) + msgtype = val; } return 0; @@ -573,7 +608,6 @@ static void mms_pack_well_known_field(Octstr *os, int field_type, Octstr *value) case MMS_HEADER_TRANSACTION_ID: case MMS_HEADER_MESSAGE_ID: case MMS_HEADER_REPLY_CHARGING_ID: - case MMS_HEADER_RESPONSE_TEXT: case MMS_HEADER_RETRIEVE_TEXT: case MMS_HEADER_STORE_STATUS_TEXT: @@ -581,6 +615,7 @@ static void mms_pack_well_known_field(Octstr *os, int field_type, Octstr *value) wsp_pack_text(os, value); /* XXX need to deal with charset issues. */ break; + case MMS_HEADER_RESPONSE_TEXT: /* make sure response status does not begin with digit!! Has special meaning*/ case MMS_HEADER_CONTENT_LOCATION: if (isdigit(octstr_get_char(value, 0))) { /* begins with number. */ long i, l; @@ -593,6 +628,8 @@ static void mms_pack_well_known_field(Octstr *os, int field_type, Octstr *value) } wsp_pack_integer_value(encoded, l); s = octstr_copy(value, i, octstr_len(value)); + octstr_strip_blanks(s); + wsp_pack_text(encoded,s); wsp_pack_value(os, encoded); @@ -631,7 +668,25 @@ static void mms_pack_well_known_field(Octstr *os, int field_type, Octstr *value) break; case MMS_HEADER_RESPONSE_STATUS: - pack_short_integer(os, mms_string_to_response_status(value)); + 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) { + warning(0, "Bad counter for field %s!", + 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)); break; case MMS_HEADER_RETRIEVE_STATUS: pack_short_integer(os, mms_string_to_retrieve_status(value)); @@ -702,7 +757,7 @@ static void mms_pack_well_known_field(Octstr *os, int field_type, Octstr *value) } wsp_pack_value(os, encoded); - break; + break; case MMS_HEADER_PREVIOUSLY_SENT_BY: case MMS_HEADER_PREVIOUSLY_SENT_DATE: { @@ -718,6 +773,8 @@ static void mms_pack_well_known_field(Octstr *os, int field_type, Octstr *value) wsp_pack_integer_value(encoded, l); s = octstr_copy(value, i, octstr_len(value)); + octstr_strip_blanks(s); + if (field_type == MMS_HEADER_PREVIOUSLY_SENT_BY) wsp_pack_text(encoded, s); else @@ -833,10 +890,9 @@ static void mms_pack_well_known_field(Octstr *os, int field_type, Octstr *value) return; } -static int encode_msgheaders(Octstr *os, MmsMsg *msg) +static int encode_msgheaders(Octstr *os, List *hdrs) { int fcont = 1; - List *hdrs = msg->headers; int i, l = list_len(hdrs), mtype; Octstr *msgtype = NULL, *transid = NULL, *version = NULL, *ctype; @@ -909,9 +965,16 @@ static int encode_msgheaders(Octstr *os, MmsMsg *msg) /* Does basic fixups on a message. */ static int fixup_msg(MmsMsg *m, Octstr *from) { + Octstr *ver; if (!m) return -1; + ver = http_header_value(m->headers, octstr_imm("X-Mms-MMS-Version")); + if (!ver || octstr_str_compare(ver, "1.1") <= 0) + m->enc = MS_1_1; + else if (octstr_str_compare(ver, "1.2") <= 0) + m->enc = MS_1_2; + if (m->message_type == MMS_MSGTYPE_SEND_REQ) { Octstr *s = NULL; @@ -934,6 +997,12 @@ static int fixup_msg(MmsMsg *m, Octstr *from) return 0; } + +mms_encoding mms_message_enc(MmsMsg *msg) +{ + return msg->enc; +} + MmsMsg *mms_frombinary(Octstr *msg, Octstr *from) { int res = 0; @@ -942,7 +1011,11 @@ MmsMsg *mms_frombinary(Octstr *msg, Octstr *from) Octstr *s; - decode_msgheaders(p, &_m, from); + + mms_strings_init(); /* Just in case. */ + + _m.headers = list_create(); + decode_msgheaders(p, _m.headers, from, 1); if (_m.headers == NULL || list_len(_m.headers) == 0) @@ -1029,7 +1102,7 @@ Octstr *mms_tobinary(MmsMsg *msg) { Octstr *s = octstr_create(""); - encode_msgheaders(s, msg); + encode_msgheaders(s, msg->headers); if (msg->body.s) encode_msgbody(s, msg); @@ -1291,7 +1364,8 @@ void mms_destroy(MmsMsg *msg) else if (msg->body.s) octstr_destroy(msg->body.s); http_destroy_headers(msg->headers); - octstr_destroy(msg->msgId); + if (msg->msgId) + octstr_destroy(msg->msgId); gw_free(msg); } @@ -1319,7 +1393,8 @@ MmsMsg *mms_deliveryreport(Octstr *msgid, Octstr *to, time_t date, Octstr *statu http_header_add(m->headers, "X-Mms-Message-Type", "m-delivery-ind"); http_header_add(m->headers, "X-Mms-MMS-Version", MMS_DEFAULT_VERSION); - http_header_add(m->headers, "Message-ID", octstr_get_cstr(msgid)); + + http_header_add(m->headers, "Message-ID", msgid ? octstr_get_cstr(msgid) : "none"); http_header_add(m->headers, "To", octstr_get_cstr(to)); s = date_format_http(date); @@ -1384,7 +1459,8 @@ MmsMsg *mms_notification(MmsMsg *msg, unsigned int msize, Octstr *url, } MmsMsg *mms_retrieveconf(MmsMsg *msg, Octstr *transactionid, - char *err, char *errtxt, Octstr *opt_from) + char *err, char *errtxt, Octstr *opt_from, + int menc) { MmsMsg *m; @@ -1392,9 +1468,11 @@ MmsMsg *mms_retrieveconf(MmsMsg *msg, Octstr *transactionid, if (msg) { if (msg->message_type == MMS_MSGTYPE_RETRIEVE_CONF) return msg; /* Unchanged. XXX should we copy it instead?!! */ - +#if 0 + /* we don't need this for mmbox ?? */ if (msg->message_type != MMS_MSGTYPE_SEND_REQ) return NULL; +#endif } m = gw_malloc(sizeof *m); @@ -1407,7 +1485,11 @@ MmsMsg *mms_retrieveconf(MmsMsg *msg, Octstr *transactionid, if (transactionid) http_header_add(m->headers, "X-Mms-Transaction-ID", octstr_get_cstr(transactionid)); - http_header_add(m->headers, "X-Mms-MMS-Version", MMS_DEFAULT_VERSION); + + 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); if (!msg) { Octstr *x = date_format_http(time(NULL)); @@ -1463,7 +1545,7 @@ int mms_remove_headers(MmsMsg *m, char *name) return 0; } -MmsMsg *mms_sendconf(char *errstr, char *msgid, char *transid, int isforward) +MmsMsg *mms_sendconf(char *errstr, char *msgid, char *transid, int isforward, int menc) { MmsMsg *m = gw_malloc(sizeof *m); @@ -1482,7 +1564,11 @@ MmsMsg *mms_sendconf(char *errstr, char *msgid, char *transid, int isforward) http_header_add(m->headers, "X-Mms-Message-Type", "m-forward-conf"); } http_header_add(m->headers, "X-Mms-Transaction-ID", transid); - http_header_add(m->headers, "X-Mms-MMS-Version", MMS_DEFAULT_VERSION); + + 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-Response-Status", errstr); @@ -1550,3 +1636,275 @@ int mms_convert_readrec2readorig(MmsMsg *msg) msg->message_type = MMS_MSGTYPE_READ_ORIG_IND; return 0; } + +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"); + } + 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. */ + + 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; +} + +static int mms_msgsize(MmsMsg *m) +{ + Octstr *s = mms_tobinary(m); /* Dirty, but works... */ + int n = octstr_len(s); + + 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; + int addcontent = 0; + + 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"); + + /* Add only those headers requested. */ + for (i = 0, n = list_len(reqhdrs); i < n; i++) { + Octstr *header = list_get(reqhdrs,i); + 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; + } + + for (j = 0; j < list_len(h); j++) { + 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. */ + } + + /* 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); + } + http_destroy_headers(mm->headers); + mm->headers = mh; + + if (!addcontent) { + if (mm->ismultipart) + list_destroy(mm->body.l, (list_item_destructor_t *)mm_destroy); + else if (mm->body.s) + octstr_destroy(mm->body.s); + mm->body.s = NULL; + } + 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); + + n = list_len(msgrefs); + msgcount = 0; + + m->ismultipart = 1; + m->body.l = list_create(); + for (i = 0; i < n; i++) { + unsigned long tmsize; + Octstr *msgref = list_get(msgrefs,i); + Octstr *msgloc = list_get(msglocs, i); + 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(); + + http_header_add(mtmp->headers, "Content-Type", "application/vnd.wap.mms-message"); + mtmp->body = ms; + + list_append(m->body.l, mtmp); + msgcount++; + msize += octstr_len(ms); + } else { + i = n; /* force end. */ + octstr_destroy(ms); + } + + mms_destroy(mm); + + loop:(void)0; + } + + if (list_len(m->body.l) > 0) { + char x[32]; + sprintf(x, "%d", (int)list_len(m->body.l)); + mms_replace_header_value(m, "X-Mms-Message-Count", x); + mms_replace_header_value(m, "Content-Type", "application/vnd.wap.multipart.mixed"); + } else { + list_destroy(m->body.l,NULL); + m->body.s = NULL; + m->ismultipart = 0; + } + + return m; +} + +void *mms_msgbody(MmsMsg *msg) +{ + if (!msg) + return NULL; + + if (msg->ismultipart) { + List *l = list_create(); + int i; + + for (i = 0; i < list_len(msg->body.l); i++) + list_append(l, mime_entity_duplicate(list_get(msg->body.l,i))); + return l; + } else + return octstr_duplicate(msg->body.s); +} + +int mms_clearbody(MmsMsg *msg) +{ + if (!msg) + return -1; + + if (msg->ismultipart) + list_destroy(msg->body.l, (list_item_destructor_t *)mm_destroy); + 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) +{ + mms_clearbody(msg); + + msg->ismultipart = ismultipart; + msg->body.s = body; + + return 0; +} diff --git a/mbuni/mmlib/mms_msg.h b/mbuni/mmlib/mms_msg.h index 484887f..9dc9096 100644 --- a/mbuni/mmlib/mms_msg.h +++ b/mbuni/mmlib/mms_msg.h @@ -9,6 +9,8 @@ typedef struct MmsMsg MmsMsg; /* Opaque type. */ +typedef MmsMsg *MmsMsgGetFunc_t(void *p1, void *p2, Octstr *msgref, unsigned long *msize); + extern int mms_validate_address(Octstr *s); /* @@ -23,6 +25,8 @@ extern MmsMsg *mms_frombinary(Octstr *msg, Octstr *from); */ extern Octstr *mms_tobinary(MmsMsg *msg); +extern mms_encoding mms_message_enc(MmsMsg *msg); + extern int mms_messagetype(MmsMsg *msg); /* @@ -46,9 +50,9 @@ extern MmsMsg *mms_notification(MmsMsg *msg, unsigned int msize, Octstr *url, Octstr *transactionid, time_t expiryt, int optimizesize); -MmsMsg *mms_retrieveconf(MmsMsg *msg, Octstr *transactionid, char *err, char *errtxt, Octstr *opt_from); +MmsMsg *mms_retrieveconf(MmsMsg *msg, Octstr *transactionid, char *err, char *errtxt, Octstr *opt_from, int menc); int mms_remove_headers(MmsMsg *m, char *name); -MmsMsg *mms_sendconf(char *errstr, char *msgid, char *transid, int isforward); +MmsMsg *mms_sendconf(char *errstr, char *msgid, char *transid, int isforward, int menc); Octstr *mms_get_header_value(MmsMsg *msg, Octstr *header); @@ -60,4 +64,36 @@ int mms_replace_header_values(MmsMsg *msg, char *hname, List *values); int mms_convert_readrec2readorig(MmsMsg *msg); + +MmsMsg *mms_storeconf(char *errstr, char *transid, Octstr *msgloc, int isupload, int menc); +MmsMsg *mms_deleteconf(int menc, char *transid); + +/* Makes a view-conf message. Insane number of arguments I know, + * but it seems a fair price to keep the interfaces clean + * + */ +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); + +/* Returns a copy of the message body. Either as list of MIME Entities or as string -- + * caller must consult content_type to determine which is returned. + */ +void *mms_msgbody(MmsMsg *msg); + +/* Remove message body. */ +int mms_clearbody(MmsMsg *msg); + +/* Put a new message body. Old one removed if it is there. + * second param is a list of MIME entities or a string depending on content type + * ismultipart tells us which. No copy is made of body. + * Use function with extreme caution! It should be for testing only really!!!! + */ +int mms_putbody(MmsMsg *msg, void *body, int ismultipart); #endif diff --git a/mbuni/mmlib/mms_strings.def b/mbuni/mmlib/mms_strings.def index 20b38c6..8bfd065 100644 --- a/mbuni/mmlib/mms_strings.def +++ b/mbuni/mmlib/mms_strings.def @@ -100,8 +100,8 @@ VNSTRING(MS_1_2,"X-Mms-Limit", MMS_HEADER_LIMIT) ) LINEAR(reports, -STRING("yes") -STRING("no") +STRING("Yes") +STRING("No") ) NAMED(message_type, diff --git a/mbuni/mmlib/mms_uaprof.c b/mbuni/mmlib/mms_uaprof.c index bad779f..bb1d5f4 100644 --- a/mbuni/mmlib/mms_uaprof.c +++ b/mbuni/mmlib/mms_uaprof.c @@ -1311,3 +1311,8 @@ int mms_format_special(MmsMsg *inmsg, return 0; } + +extern unsigned long mms_ua_maxmsgsize(MmsUaProfile *prof) +{ + return prof ? prof->maxmsgsize : 0; +} diff --git a/mbuni/mmlib/mms_uaprof.h b/mbuni/mmlib/mms_uaprof.h index 24208ea..69c7234 100644 --- a/mbuni/mmlib/mms_uaprof.h +++ b/mbuni/mmlib/mms_uaprof.h @@ -37,5 +37,6 @@ extern int mms_format_special(MmsMsg *inmsg, char *txtmsg, char *htmlmsg, MIMEEntity **outmsg); +extern unsigned long mms_ua_maxmsgsize(MmsUaProfile *prof); #define DEFAULT_CHARSET "UTF-8" #endif diff --git a/mbuni/mmlib/mms_util.c b/mbuni/mmlib/mms_util.c index f6061cf..3bf917c 100644 --- a/mbuni/mmlib/mms_util.c +++ b/mbuni/mmlib/mms_util.c @@ -241,7 +241,7 @@ List *mms_proxy_relays(Cfg *cfg) } -Octstr *mms_makefetchurl(char *qf, Octstr *token, +Octstr *mms_makefetchurl(char *qf, Octstr *token, int loc, MmsBoxSettings *settings) { Octstr *url = octstr_create(""); @@ -254,9 +254,9 @@ Octstr *mms_makefetchurl(char *qf, Octstr *token, hstr = octstr_format("%S:%d", settings->hostname, settings->port); - octstr_format_append(url, "http://%S/%s/%S", + octstr_format_append(url, "http://%S/%s@%d/%S", hstr, - qf, + qf, loc, token ? token : octstr_imm("x")); octstr_destroy(hstr); return url; @@ -320,7 +320,7 @@ Octstr *mms_find_sender_ip(List *request_hdrs, Octstr *ip_header, Octstr *ip, in } int mms_decodefetchurl(Octstr *fetch_url, - Octstr **qf, Octstr **token) + Octstr **qf, Octstr **token, int *loc) { Octstr *xfurl = octstr_duplicate(fetch_url); int i, j, n; @@ -364,12 +364,37 @@ int mms_decodefetchurl(Octstr *fetch_url, else *token = octstr_create(""); octstr_destroy(xfurl); + + /* Now get loc out of qf. */ + *loc = MMS_LOC_MQUEUE; + i = octstr_search_char(*qf, '@', 0); + if (i >= 0) { + long l; + int j = octstr_parse_long(&l, *qf, i+1, 10); + if (j > 0) + *loc = l; + octstr_delete(*qf, i, octstr_len(*qf)); + } + return 0; } Octstr *mms_maketransid(char *qf, Octstr *mmscname) { - Octstr *res = octstr_format("%s@%S", qf, mmscname); + Octstr *res; + Octstr *x; + static int ct; + + if (!qf) + x = octstr_format("msg.%ld.x%d.%d.%d", + time(NULL), ++ct, getpid(), random()%10000); + else + x = octstr_create(qf); + + res = octstr_format("%S@%S", x, mmscname); + + octstr_destroy(x); + return res; } @@ -906,7 +931,7 @@ void mms_log2(char *logmsg, Octstr *from, Octstr *to, int msize, Octstr *msgid, Octstr *acct, Octstr *viaproxy, - char *interface, Octstr *ua) + char *interface, Octstr *ua, Octstr *mmboxloc) { List *l; if (to) { @@ -915,7 +940,7 @@ void mms_log2(char *logmsg, Octstr *from, Octstr *to, } else l = NULL; - mms_log(logmsg, from,l,msize,msgid,acct,viaproxy,interface,ua); + mms_log(logmsg, from,l,msize,msgid,acct,viaproxy,interface,ua,mmboxloc); if (l) list_destroy(l, NULL); @@ -925,7 +950,7 @@ void mms_log(char *logmsg, Octstr *from, List *to, int msize, Octstr *msgid, Octstr *acct, Octstr *viaproxy, - char *interface, Octstr *ua) + char *interface, Octstr *ua, Octstr *mmboxloc) { Octstr *xto = octstr_create(""); int i, n = to ? list_len(to) : 0; @@ -936,7 +961,7 @@ void mms_log(char *logmsg, Octstr *from, List *to, (i == 0) ? "" : ", ", list_get(to,i)); - alog("%s MMS [INT:%s] [ACT:%s] [MMSC:%s] [from:%s] [to:%s] [msgid:%s] [size=%d] [UA:%s]", + alog("%s MMS [INT:%s] [ACT:%s] [MMSC:%s] [from:%s] [to:%s] [msgid:%s] [size=%d] [UA:%s] [MMBox:%s]", logmsg, interface, acct ? octstr_get_cstr(acct) : "", viaproxy ? octstr_get_cstr(viaproxy) : "", @@ -944,7 +969,8 @@ void mms_log(char *logmsg, Octstr *from, List *to, octstr_get_cstr(xto), msgid ? octstr_get_cstr(msgid) : "", msize, - ua ? octstr_get_cstr(ua) : ""); + ua ? octstr_get_cstr(ua) : "", + mmboxloc ? octstr_get_cstr(mmboxloc) : ""); octstr_destroy(xto); } diff --git a/mbuni/mmlib/mms_util.h b/mbuni/mmlib/mms_util.h index 155f306..7021372 100644 --- a/mbuni/mmlib/mms_util.h +++ b/mbuni/mmlib/mms_util.h @@ -96,10 +96,8 @@ extern char *mms_hostname; /* Our hostname. */ #define MMSC_VERSION VERSION #define MMS_NAME PACKAGE -#if 0 -#define EMAILPROFILE "http://localhost/email.xml" /* For now we hard code it. */ -#define MMBOXPROFILE "http://localhost/mmbox.xml" -#endif +/* Message location flags: Used to distinguish fetch-urls */ +enum mms_loc_t {MMS_LOC_MMBOX = 1, MMS_LOC_MQUEUE=2}; /* Returns mmsbox settings. */ MmsBoxSettings *mms_load_mmsbox_settings(Cfg *cfg); @@ -108,7 +106,7 @@ MmsBoxSettings *mms_load_mmsbox_settings(Cfg *cfg); /* Returns list of MmsProxyRelay */ extern List *mms_proxy_relays(Cfg *cfg); -extern Octstr *mms_makefetchurl(char *qf, Octstr *token, +extern Octstr *mms_makefetchurl(char *qf, Octstr *token, int loc, MmsBoxSettings *settings); extern Octstr *mms_maketransid(char *qf, Octstr *mmscname); @@ -116,7 +114,7 @@ extern Octstr *mms_maketransid(char *qf, Octstr *mmscname); extern Octstr *mms_getqf_fromtransid(Octstr *transid); extern int mms_decodefetchurl(Octstr *fetch_url, - Octstr **qf, Octstr **token); + Octstr **qf, Octstr **token, int *loc); Octstr *mms_find_sender_msisdn(Octstr **send_url, List *request_hdrs, Octstr *msisdn_header, MmsDetokenizerFuncStruct *detokenizerfuncs); Octstr *mms_find_sender_ip(List *request_hdrs, Octstr *ip_header, Octstr *ip, int *isv6); @@ -163,14 +161,14 @@ void mms_log(char *logmsg, Octstr *from, List *to, Octstr *acct, Octstr *viaproxy, char *interface, - Octstr *ua); + Octstr *ua, Octstr *mmboxloc); void mms_log2(char *logmsg, Octstr *from, Octstr *to, int msize, Octstr *msgid, Octstr *acct, Octstr *viaproxy, char *interface, - Octstr *ua); + Octstr *ua, Octstr *mmboxloc); /* * lockfile: tries to lock a file, returns 0 if success, errno (which could be +ve) otherwise. diff --git a/mbuni/mmsc/mmsfromemail.c b/mbuni/mmsc/mmsfromemail.c index c3e9d26..da2822a 100644 --- a/mbuni/mmsc/mmsfromemail.c +++ b/mbuni/mmsc/mmsfromemail.c @@ -170,7 +170,7 @@ int main(int argc, char *argv[]) List *xlto; mresp = mms_sendconf(err, octstr_get_cstr(msgid), transid ? octstr_get_cstr(transid) : "001", - 0); + 0,MS_1_1); rto = octstr_format("system-user@%S", xproxy); xlto = list_create(); @@ -188,7 +188,7 @@ int main(int argc, char *argv[]) } mms_log("Received", xfrom, lto, - -1, msgid, NULL, xproxy, xproxy ? "MM4" : "MM3", NULL); + -1, msgid, NULL, xproxy, xproxy ? "MM4" : "MM3", NULL,NULL); list_destroy(lto,NULL); octstr_destroy(transid); diff --git a/mbuni/mmsc/mmsglobalsender.c b/mbuni/mmsc/mmsglobalsender.c index 41c559e..6684ce9 100644 --- a/mbuni/mmsc/mmsglobalsender.c +++ b/mbuni/mmsc/mmsglobalsender.c @@ -145,7 +145,7 @@ static int sendMsg(MmsEnvelope *e) settings->hostname, 1, 1, octstr_get_cstr(settings->mms_email_txt), octstr_get_cstr(settings->mms_email_html), 1); mms_log2("Sent", e->from, to->rcpt, - -1, e->msgId, NULL, NULL, "MM3", NULL); + -1, e->msgId, NULL, NULL, "MM3", NULL,NULL); } else if (e->viaproxy && octstr_len(e->viaproxy) > 0) /* If proxy to send through is already set, use it. */ res = mms_sendtoproxy(e->from, @@ -480,7 +480,7 @@ static int mms_sendtoproxy(Octstr *from, Octstr *to, settings->hostname, 0, 0,NULL,NULL,0); mms_log2("Sent", from, to, - -1, msgid, NULL, proxy, "MM4", NULL); + -1, msgid, NULL, proxy, "MM4", NULL,NULL); octstr_destroy(pto); diff --git a/mbuni/mmsc/mmsmobilesender.c b/mbuni/mmsc/mmsmobilesender.c index 5ded50e..a2abb5f 100644 --- a/mbuni/mmsc/mmsmobilesender.c +++ b/mbuni/mmsc/mmsmobilesender.c @@ -118,7 +118,7 @@ static void start_push(Octstr *rcpt_to, int isphonenum, MmsEnvelope *e, MmsMsg * close(sock); /* ?? */ mms_log2("Notify", octstr_imm("system"), to, -1, e ? e->msgId : NULL, - NULL, NULL, "MM1", NULL); + NULL, NULL, "MM1", NULL,NULL); e = update_env_success(e, xto); } else { e = update_env_failed(e); @@ -189,7 +189,7 @@ static int receive_push_reply(HTTPCaller *caller) http_header_dump(reply_headers); mms_log2("Notify", octstr_imm("system"), to, - -1, env ? env->msgId : NULL, NULL, NULL, "MM1", NULL); + -1, env ? env->msgId : NULL, NULL, NULL, "MM1", NULL,NULL); if (update_env_success(env, xto) != NULL) goto push_free_env; @@ -389,7 +389,7 @@ static int sendNotify(MmsEnvelope *e) } /* To get here means we can send Ind. */ - url = mms_makefetchurl(e->qf.name, e->token, + url = mms_makefetchurl(e->qf.name, e->token, MMS_LOC_MQUEUE, settings); transid = mms_maketransid(e->qf.name, settings->host_alias); diff --git a/mbuni/mmsc/mmsproxy.c b/mbuni/mmsc/mmsproxy.c index f0d7252..48cc962 100644 --- a/mbuni/mmsc/mmsproxy.c +++ b/mbuni/mmsc/mmsproxy.c @@ -201,53 +201,70 @@ void fetchmms_proxy(MmsHTTPClientInfo *h) MmsEnvelope *e = NULL; MmsMsg *m = NULL, *mr = NULL; List *rh; - + int loc, menc = MS_1_1; + debug("proxy.fetchinterface", 0, " ---> Entered fetch interface <---"); rh = http_create_empty_headers(); http_header_add(rh, "Pragma", "no-cache"); http_header_add(rh, "Cache-Control", "no-cache"); - if (mms_decodefetchurl(h->url, &qf, &token) != 0) { + if (mms_decodefetchurl(h->url, &qf, &token,&loc) != 0) { error(0, "MMS Fetch interface: failed to decode request url (%s) from %s!", octstr_get_cstr(h->url), octstr_get_cstr(h->ip)); goto failed; } - e = mms_queue_readenvelope(octstr_get_cstr(qf), - octstr_get_cstr(settings->mm1_queuedir), 1); - - if (!e || - (m = mms_queue_getdata(e)) == NULL) { - error(0, "MMS Fetch interface: failed to find envelope/data %s for request url (%s) from %s (e=%s)!", - octstr_get_cstr(qf), octstr_get_cstr(h->url), octstr_get_cstr(h->ip), - (e)? "found" : "not found"); - - mr = mms_retrieveconf(NULL, NULL, "Error-permanent-message-not-found", "Message not found", - settings->system_user); - s = mms_tobinary(mr); - goto failed; + + if (loc == MMS_LOC_MQUEUE) { /* where is the message? */ + e = mms_queue_readenvelope(octstr_get_cstr(qf), + octstr_get_cstr(settings->mm1_queuedir), 1); + + if (!e || + (m = mms_queue_getdata(e)) == NULL) { + error(0, "MMS Fetch interface: failed to find envelope/data %s for request url (%s) from %s (e=%s)!", + octstr_get_cstr(qf), octstr_get_cstr(h->url), octstr_get_cstr(h->ip), + (e)? "found" : "not found"); + + mr = mms_retrieveconf(NULL, NULL, "Error-permanent-message-not-found", "Message not found", + settings->system_user, MS_1_1); + s = mms_tobinary(mr); + goto failed; + } + } else { /* it is in mmbox, so get it from there. */ + unsigned long msize; + if ((m = mms_mmbox_get(octstr_get_cstr(settings->mmbox_rootdir), + octstr_get_cstr(h->client_addr), qf, &msize)) == NULL) { + error(0, "MMS Fetch interface: failed to find data in MMBOX %s, url=%s, from=%s (e=%s)!", + octstr_get_cstr(qf), octstr_get_cstr(h->url), octstr_get_cstr(h->ip), + (e)? "found" : "not found"); + mr = mms_retrieveconf(NULL, NULL, "Error-permanent-message-not-found", "Message not found", + settings->system_user, MS_1_1); + s = mms_tobinary(mr); + goto failed; + } + menc = MS_1_2; } - /* Adapt content. */ - transid = mms_maketransid(e->qf.name, settings->host_alias); + transid = mms_maketransid(octstr_get_cstr(qf), settings->host_alias); if (h->prof) { MmsMsg *outmsg = NULL; int x = mms_transform_msg(m, h->prof, &outmsg); if (x == -1) { /* Temporary failure, we need to fetch profile. */ mr = mms_retrieveconf(NULL, transid, "Error-transient-failure", "Mobile MMS Settings not found", - settings->system_user); + settings->system_user,MS_1_1); s = mms_tobinary(mr); goto failed; } else if (x < 0) { /* Doesn't support MMS */ - mr = mms_retrieveconf(NULL, transid, "Error-permanent-content-unsupported", "No MMS Support", - settings->system_user); + mr = mms_retrieveconf(NULL, transid, + "Error-permanent-content-unsupported", "No MMS Support", + settings->system_user,MS_1_1); s = mms_tobinary(mr); goto failed; } else if (x == 0) { if (outmsg == NULL) { /* Too large so truncated. */ - Octstr *xx = octstr_format(octstr_get_cstr(settings->mms_toolarge), e->from); + Octstr *xx = octstr_format(octstr_get_cstr(settings->mms_toolarge), (e) ? e->from : h->client_addr); mr = mms_retrieveconf(NULL, transid, #if 0 @@ -256,7 +273,7 @@ void fetchmms_proxy(MmsHTTPClientInfo *h) "Ok", #endif octstr_get_cstr(xx), - settings->system_user); + settings->system_user,MS_1_1); octstr_destroy(xx); s = mms_tobinary(mr); @@ -268,22 +285,24 @@ void fetchmms_proxy(MmsHTTPClientInfo *h) } } - mr = mms_retrieveconf(m, transid, "Error-permanent-message-not-found", NULL, e->from); + mr = mms_retrieveconf(m, transid, "Error-permanent-message-not-found", NULL, + (e) ? e->from : h->client_addr, menc); s = mms_tobinary(mr); - if ((token == NULL && e->token != NULL) || - (e->token == NULL && token != NULL) || - (octstr_compare(e->token, token) != 0)) { - error(0, "MMS Fetch interface: token mismatch, did client mod the fetch url?? " - " env=%s for request url (%s) from %s!", - octstr_get_cstr(qf), octstr_get_cstr(h->url), octstr_get_cstr(h->ip)); - goto failed; - } + if (loc == MMS_LOC_MQUEUE) + if ((token == NULL && e->token != NULL) || + (e->token == NULL && token != NULL) || + (octstr_compare(e->token, token) != 0)) { + error(0, "MMS Fetch interface: token mismatch, did client mod the fetch url?? " + " env=%s for request url (%s) from %s!", + octstr_get_cstr(qf), octstr_get_cstr(h->url), octstr_get_cstr(h->ip)); + goto failed; + } if (!m) { - error(0, "MMS Fetch interface: Failed to get message for request url (%s) from %s!", - octstr_get_cstr(h->url), octstr_get_cstr(h->ip)); + error(0, "MMS Fetch interface: Failed to get message, url=%s, loc=%d from %s!", + octstr_get_cstr(h->url), loc, octstr_get_cstr(h->ip)); goto failed; } @@ -295,11 +314,11 @@ void fetchmms_proxy(MmsHTTPClientInfo *h) } - - e->lastaccess = time(NULL); /* No more notifications requests. */ - e->sendt = e->expiryt + 3600*24*30*12; - mms_queue_update(e); - + if (e) { + e->lastaccess = time(NULL); /* No more notifications requests. */ + e->sendt = e->expiryt + 3600*24*30*12; + mms_queue_update(e); + } http_header_add(rh, "Content-Type", "application/vnd.wap.mms-message"); http_send_reply(h->client, HTTP_OK, rh, s); @@ -315,7 +334,8 @@ void fetchmms_proxy(MmsHTTPClientInfo *h) /* Send to access log with success. */ mms_log2("Fetched", e ? e->from : NULL, h->client_addr, - e ? e->msize : 0, e ? e->msgId : NULL, NULL, NULL, "MM1", h->ua); + e ? e->msize : 0, e ? e->msgId : NULL, NULL, NULL, "MM1", + h->ua, (loc == MMS_LOC_MMBOX) ? qf : NULL); goto free_stuff; /* Skip to end. */ @@ -331,7 +351,8 @@ void fetchmms_proxy(MmsHTTPClientInfo *h) /* Send to access log on failure?? */ mms_log2("Failed Fetch", e ? e->from : NULL, h->client_addr, - e ? e->msize : 0, e ? e->msgId : NULL, NULL, NULL, "MM1", h->ua); + e ? e->msize : 0, e ? e->msgId : NULL, NULL, NULL, "MM1", h->ua, + (loc == MMS_LOC_MMBOX) ? qf : NULL); if (!s) { http_header_add(rh, "Content-Type", "text/plain"); @@ -372,7 +393,7 @@ void fetchmms_proxy(MmsHTTPClientInfo *h) /* Make list of recipients and also sender. */ static void collect_senddata(List *mh, List **xto, - Octstr **from, Octstr **subject, + Octstr **subject, Octstr **otransid, time_t *expiryt, time_t *deliveryt) { @@ -417,11 +438,7 @@ static void collect_senddata(List *mh, List **xto, } http_destroy_headers(l); } - - - *from = http_header_value(mh, octstr_imm("From")); - - + /* Find expiry and delivery times */ if (expiryt) { s = http_header_value(mh, octstr_imm("X-Mms-Expiry")); @@ -454,7 +471,7 @@ static void sendmms_proxy(MmsHTTPClientInfo *h) MmsMsg *m, *mresp = NULL; Octstr *reply_body = NULL; int ctype_set = 0; - int mtype = 0; + int mtype = 0, menc; int hstatus = HTTP_OK; char *notify_cmd = NULL; int msize = h->body ? octstr_len(h->body) : 0; @@ -488,11 +505,12 @@ static void sendmms_proxy(MmsHTTPClientInfo *h) debug("proxy.sendinterface", 0, " Client sent us: "); -#if 1 +#if 0 mms_msgdump(m,1); /* octstr_dump(h->body, 0); */ #endif mtype = mms_messagetype(m); + menc = mms_message_enc(m); switch(mtype) { @@ -500,26 +518,59 @@ static void sendmms_proxy(MmsHTTPClientInfo *h) { Octstr *qf; List *mh = mms_message_headers(m); - Octstr *from; + Octstr *from = octstr_duplicate(h->client_addr); List *to = list_create(); Octstr *subject; time_t expiryt, deliveryt; - Octstr *otransid = NULL, *value = NULL; + Octstr *otransid = NULL, *value = NULL, *msgid = NULL; int dlr; + char *mmbox_store_status = NULL; + Octstr *mmbox_loc = NULL; + Octstr *sdf = NULL; + - collect_senddata(mh, &to, &from, &subject, &otransid, &expiryt, &deliveryt); + collect_senddata(mh, &to, &subject, &otransid, &expiryt, &deliveryt); if (!h->client_addr) { - mresp = mms_sendconf("Error-sending-address-unresolved", "None", octstr_get_cstr(otransid),0); + mresp = mms_sendconf("Error-sending-address-unresolved", "None", octstr_get_cstr(otransid),0, + menc); } else { + Octstr *x = mms_get_header_value(m, octstr_imm("X-Mms-Store")); + + mms_remove_headers(m, "X-Mms-Store"); + + msgid = mms_maketransid(NULL, settings->host_alias); + mms_replace_header_value(m, "Message-ID", octstr_get_cstr(msgid)); /* Put in message id -- for later. */ + + + if (menc >= MS_1_2 && + x != NULL && + octstr_case_compare(x, octstr_imm("Yes")) == 0) { + + sdf = mms_mmbox_addmsg(octstr_get_cstr(settings->mmbox_rootdir), + octstr_get_cstr(h->client_addr), m, + NULL, + octstr_imm("Sent")); + + /* XXX perhaps qualify errors better? */ + mmbox_store_status = sdf ? "Success" : "Error-permanent-failure"; + if (sdf) + mmbox_loc = mms_makefetchurl(octstr_get_cstr(sdf), NULL, MMS_LOC_MMBOX, settings); + } + + if (x) + octstr_destroy(x); /*Delete some headers that must be sent on. */ mms_remove_headers(m, "Bcc"); mms_remove_headers(m, "X-Mms-Delivery-Time"); mms_remove_headers(m, "X-Mms-Expiry"); mms_remove_headers(m, "X-Mms-Sender-Visibility"); - + + mms_remove_headers(m, "X-Mms-MM-Flags"); + mms_remove_headers(m, "X-Mms-MM-State"); + value = http_header_value(mh, octstr_imm("X-Mms-Delivery-Report")); if (value && @@ -529,28 +580,47 @@ static void sendmms_proxy(MmsHTTPClientInfo *h) dlr = 0; - qf = mms_queue_add(from, to, NULL, subject, + qf = mms_queue_add(from, to, msgid, subject, NULL, NULL, deliveryt, expiryt, m, NULL, dlr, octstr_get_cstr(settings->global_queuedir)); if (!qf) - mresp = mms_sendconf("Error-transient-failure", "None", octstr_get_cstr(otransid),0); + mresp = mms_sendconf("Error-transient-failure", "None", octstr_get_cstr(otransid),0, + menc); else { - Octstr *transid = mms_maketransid(octstr_get_cstr(qf), settings->host_alias); - mresp = mms_sendconf("Ok", octstr_get_cstr(transid), octstr_get_cstr(otransid),0); + + mresp = mms_sendconf("Ok", octstr_get_cstr(msgid), octstr_get_cstr(otransid),0, + menc); /* Log to access log */ - mms_log("Received", from, to, msize, transid, NULL, NULL, "MM1", h->ua); + mms_log("Received", from, to, msize, msgid, NULL, NULL, "MM1", h->ua, sdf); - octstr_destroy(transid); octstr_destroy(qf); } + + if (mmbox_store_status) /* If saved to mmbox, ... */ + mms_replace_header_value(mresp, + "X-Mms-Store-Status", mmbox_store_status); + if (mmbox_loc) + mms_replace_header_value(mresp, + "X-Mms-Content-Location", + octstr_get_cstr(mmbox_loc)); } if (otransid) octstr_destroy(otransid); if (value) octstr_destroy(value); + + if (msgid) + octstr_destroy(msgid); + + if (mmbox_loc) + octstr_destroy(mmbox_loc); + + if (sdf) + octstr_destroy(sdf); + octstr_destroy(from); octstr_destroy(subject); http_destroy_headers(mh); @@ -564,13 +634,14 @@ static void sendmms_proxy(MmsHTTPClientInfo *h) { Octstr *qf = NULL, *token = NULL; List *mh = mms_message_headers(m); - Octstr *from; + Octstr *from = octstr_duplicate(h->client_addr); List *to = list_create(); Octstr *subject; time_t expiryt, deliveryt; MmsMsg *mfwd = NULL; MmsEnvelope *e = NULL; - + int mloc; + Octstr *otransid; Octstr *url = http_header_value(mh, octstr_imm("X-Mms-Content-Location")); Octstr *read_report = http_header_value(mh, octstr_imm("X-Mms-Read-Report")); @@ -579,47 +650,73 @@ static void sendmms_proxy(MmsHTTPClientInfo *h) Octstr *allow_report = http_header_value(mh, octstr_imm("X-Mms-Report-Allowed")); int dlr; + unsigned long msize; + char *mmbox_store_status = NULL; + Octstr *mmbox_loc = NULL; + Octstr *sdf = NULL; + + collect_senddata(mh, &to, &subject, &otransid, &expiryt, &deliveryt); - collect_senddata(mh, &to, &from, &subject, &otransid, &expiryt, &deliveryt); - - if (mms_decodefetchurl(url, &qf, &token) != 0) { + if (mms_decodefetchurl(url, &qf, &token,&mloc) != 0) { error(0, "MMS Send interface: failed to decode forward url (%s) from %s!", octstr_get_cstr(url), octstr_get_cstr(h->ip)); mresp = mms_sendconf("Error-permanent-message-not-found", "None", - octstr_get_cstr(otransid),1); + octstr_get_cstr(otransid),1,menc); goto forward_done; } - e = mms_queue_readenvelope(octstr_get_cstr(qf), - octstr_get_cstr(settings->mm1_queuedir), 1); + if (mloc == MMS_LOC_MQUEUE) { /* where is the message? */ + e = mms_queue_readenvelope(octstr_get_cstr(qf), + octstr_get_cstr(settings->mm1_queuedir), 1); + + if (!e || + (mfwd = mms_queue_getdata(e)) == NULL) { + error(0, + "MMS Send interface: failed to find envelope/data %s for forward url " + "(%s) from %s (e=%s)!", + octstr_get_cstr(qf), octstr_get_cstr(url), octstr_get_cstr(h->ip), + (e) ? "found" : "not found"); + + mresp = mms_sendconf("Error-permanent-message-not-found", "None", + octstr_get_cstr(otransid),1,menc); + goto forward_done; + } + } else /* it is in mmbox, so get it from there. */ + if ((mfwd = mms_mmbox_get(octstr_get_cstr(settings->mmbox_rootdir), + octstr_get_cstr(h->client_addr), qf, &msize)) == NULL) { + error(0, "MMS Send interface: failed to find data in MMBOX %s, " + "forward_url=%s, from=%s (e=%s)!", + octstr_get_cstr(qf), octstr_get_cstr(h->url), octstr_get_cstr(h->ip), + (e)? "found" : "not found"); + mresp = mms_sendconf("Error-permanent-message-not-found", "None", + octstr_get_cstr(otransid),1,menc); + + goto forward_done; + } + + { /* Found it, etc. */ - if (!e || - (mfwd = mms_queue_getdata(e)) == NULL) { - error(0, - "MMS Send interface: failed to find envelope/data %s for forward url " - "(%s) from %s (e=%s)!", - octstr_get_cstr(qf), octstr_get_cstr(url), octstr_get_cstr(h->ip), - (e) ? "found" : "not found"); - mresp = mms_sendconf("Error-permanent-message-not-found", "None", - octstr_get_cstr(otransid),1); - goto forward_done; - } else { /* Found it, etc. */ - - Octstr *transid; Octstr *pfrom = mms_get_header_value(mfwd, octstr_imm("From")); Octstr *pdate = mms_get_header_value(mfwd, octstr_imm("Date")); + Octstr *pmsgid = mms_get_header_value(mfwd, octstr_imm("Message-ID")); Octstr *pdelivery_report = mms_get_header_value(mfwd, octstr_imm("X-Mms-Delivery-Report")); - Octstr *pmsgid = mms_get_header_value(mfwd, octstr_imm("Message-ID")); + Octstr *msgid = mms_maketransid(NULL, settings->host_alias); Octstr *s; Octstr *qf2; int n = 0; + Octstr *xstate = mms_get_header_value(m, octstr_imm("X-Mms-MM-State")); + List *xflags = mms_get_header_values(m, octstr_imm("X-Mms-MM-Flags")); + + Octstr *x = NULL; + /* Modify the message before sending on as per spec. */ mms_replace_header_value(mfwd, "From", octstr_get_cstr(from)); + mms_replace_header_value(mfwd, "Message-ID", octstr_get_cstr(msgid)); /* Put in message id -- for later. */ mms_remove_headers(mfwd, "X-Mms-Read-Report"); if (read_report) @@ -636,7 +733,7 @@ static void sendmms_proxy(MmsHTTPClientInfo *h) sscanf(octstr_get_cstr(s), "%d", &n); octstr_destroy(s); } - s = octstr_format("%d %S", n+1, pfrom); + s = octstr_format("%d%S", n+1, pfrom); mms_replace_header_value(mfwd, "X-Mms-Previously-Sent-By", octstr_get_cstr(s)); @@ -646,7 +743,7 @@ static void sendmms_proxy(MmsHTTPClientInfo *h) sscanf(octstr_get_cstr(s), "%d", &n); octstr_destroy(s); } - s = octstr_format("%d %S", n+1, pdate); + s = octstr_format("%d%S", n+1, pdate); mms_replace_header_value(mfwd, "X-Mms-Previously-Sent-Date", octstr_get_cstr(s)); @@ -658,27 +755,74 @@ static void sendmms_proxy(MmsHTTPClientInfo *h) else dlr = 0; /* Message to forward is now ready, write it to queue. */ - qf2 = mms_queue_add(from, to, NULL, subject, + qf2 = mms_queue_add(from, to, msgid, subject, NULL, NULL, deliveryt, expiryt, mfwd, NULL, dlr, octstr_get_cstr(settings->global_queuedir)); + + /* Process any requests for writing to mmbox. */ + x = mms_get_header_value(m, octstr_imm("X-Mms-Store")); + mms_remove_headers(m, "X-Mms-Store"); + if (menc >= MS_1_2 && + x != NULL && + octstr_case_compare(x, octstr_imm("Yes")) == 0) { + if (mloc != MMS_LOC_MMBOX) { /* not in mmbox, add it. */ + sdf = mms_mmbox_addmsg(octstr_get_cstr(settings->mmbox_rootdir), + octstr_get_cstr(h->client_addr), mfwd, + xflags, + xstate ? xstate : octstr_imm("Forwarded")); + + /* XXX perhaps qualify errors better? */ + mmbox_store_status = sdf ? "Success" : "Error-permanent-failure"; + if (sdf) + mmbox_loc = mms_makefetchurl(octstr_get_cstr(sdf), NULL, + MMS_LOC_MMBOX, settings); + } else { /* otherwise simply mod it. */ + int xret; + + xret = mms_mmbox_modmsg(octstr_get_cstr(settings->mmbox_rootdir), + octstr_get_cstr(h->client_addr), qf, + xstate ? xstate : octstr_imm("Forwarded"), + xflags); + + /* XXX perhaps qualify errors better? */ + mmbox_store_status = (xret == 0) ? "Success" : "Error-permanent-failure"; + if (xret == 0) + mmbox_loc = mms_makefetchurl(octstr_get_cstr(qf), NULL, + MMS_LOC_MMBOX, settings); + + } + } + + if (x) + octstr_destroy(x); + + if (!qf2) mresp = mms_sendconf("Error-transient-failure", - "None", octstr_get_cstr(otransid),1); + "None", octstr_get_cstr(otransid),1,menc); else { - transid = mms_maketransid(octstr_get_cstr(qf), settings->host_alias); mresp = mms_sendconf("Ok", - octstr_get_cstr(transid), - octstr_get_cstr(otransid),1); + octstr_get_cstr(msgid), + octstr_get_cstr(otransid),1,menc); /* Log to access log */ - mms_log("Forwarded", h->client_addr, to, msize, transid, NULL, NULL, "MM1", h->ua); + mms_log("Forwarded", h->client_addr, to, msize, msgid, NULL, NULL, "MM1", + h->ua, sdf); - octstr_destroy(transid); octstr_destroy(qf2); } + + if (mmbox_store_status) /* If saved to mmbox, ... */ + mms_replace_header_value(mresp, + "X-Mms-Store-Status", mmbox_store_status); + if (mmbox_loc) + mms_replace_header_value(mresp, + "X-Mms-Content-Location", + octstr_get_cstr(mmbox_loc)); + /* You have queued it, now check if the original sender asked for a delivery notify. * if so and this forward has not refused it, then send a notify and we are done for now. @@ -700,13 +844,21 @@ static void sendmms_proxy(MmsHTTPClientInfo *h) octstr_get_cstr(settings->global_queuedir)); octstr_destroy(x); - list_destroy(l, (list_item_destructor_t *)octstr_destroy); - mms_destroy(mrep); + list_destroy(l, NULL); + mms_destroy(mrep); } octstr_destroy(pfrom); octstr_destroy(pdelivery_report); - octstr_destroy(pmsgid); - + if (pmsgid) + octstr_destroy(pmsgid); + + if (msgid) + octstr_destroy(msgid); + + if (xstate) + octstr_destroy(xstate); + if (xflags) + list_destroy(xflags, (list_item_destructor_t *)octstr_destroy); } forward_done: @@ -723,6 +875,7 @@ static void sendmms_proxy(MmsHTTPClientInfo *h) if (qf) octstr_destroy(qf); + if (token) octstr_destroy(token); if (from) @@ -745,6 +898,12 @@ static void sendmms_proxy(MmsHTTPClientInfo *h) if (delivery_report) octstr_destroy(delivery_report); + if (mmbox_loc) + octstr_destroy(mmbox_loc); + + if (sdf) + octstr_destroy(sdf); + reply_body = mms_tobinary(mresp); notify_cmd = "fetched"; } @@ -808,7 +967,7 @@ static void sendmms_proxy(MmsHTTPClientInfo *h) mdone: /* Log to access log */ - mms_log2("NotifyResp", h->client_addr, NULL, msize, transid, NULL, NULL, "MM1", h->ua); + mms_log2("NotifyResp", h->client_addr, NULL, msize, transid, NULL, NULL, "MM1", h->ua, NULL); if (e && mms_queue_update(e) != 1) /* Should be freed. */ @@ -829,21 +988,21 @@ static void sendmms_proxy(MmsHTTPClientInfo *h) case MMS_MSGTYPE_READ_REC_IND: { List *mh = mms_message_headers(m); - Octstr *from; + Octstr *from = octstr_duplicate(h->client_addr); List *to = list_create(); Octstr *x; if (mms_convert_readrec2readorig(m) < 0) goto mdone2; - collect_senddata(mh, &to, &from, NULL, NULL, NULL, NULL); + collect_senddata(mh, &to, NULL, NULL, NULL, NULL); x = mms_queue_add(from, to, NULL, NULL, NULL, NULL, time(NULL), time(NULL) + settings->default_msgexpiry, m, NULL, 0, octstr_get_cstr(settings->global_queuedir)); /* Log to access log */ - mms_log("ReadReport", h->client_addr, NULL, msize, NULL, NULL, NULL, "MM1", h->ua); + mms_log("ReadReport", h->client_addr, NULL, msize, NULL, NULL, NULL, "MM1", h->ua,NULL); octstr_destroy(x); octstr_destroy(from); @@ -858,6 +1017,413 @@ static void sendmms_proxy(MmsHTTPClientInfo *h) notify_cmd = "fetched"; break; } + break; + + /* mmbox transactions. */ + case MMS_MSGTYPE_MBOX_STORE_REQ: + { + Octstr *qf = NULL, *token = NULL; + List *mh = mms_message_headers(m); + MmsMsg *mstore = NULL; + MmsEnvelope *e = NULL; + int mloc; + Octstr *xstate = mms_get_header_value(m, octstr_imm("X-Mms-MM-State")); + List *xflags = mms_get_header_values(m, octstr_imm("X-Mms-MM-Flags")); + + Octstr *otransid = http_header_value(mh, octstr_imm("X-Mms-Transaction-ID")); + Octstr *url = http_header_value(mh, octstr_imm("X-Mms-Content-Location")); + + char *mmbox_store_status = NULL; + Octstr *mmbox_loc = NULL; + Octstr *sdf = NULL; + + + if (mms_decodefetchurl(url, &qf, &token,&mloc) != 0) { + error(0, "MMS Send interface: failed to decode store url (%s) from %s!", + octstr_get_cstr(url), + octstr_get_cstr(h->ip)); + mresp = mms_storeconf("Error-permanent-message-not-found", + octstr_get_cstr(otransid), NULL, 0,menc); + goto store_done; + } + + if (mloc == MMS_LOC_MQUEUE) { /* where is the message? */ + e = mms_queue_readenvelope(octstr_get_cstr(qf), + octstr_get_cstr(settings->mm1_queuedir), 1); + + if (!e || + (mstore = mms_queue_getdata(e)) == NULL) { + error(0, + "MMS Send interface: failed to find envelope/data %s for store url " + "(%s) from %s (e=%s)!", + octstr_get_cstr(qf), octstr_get_cstr(url), octstr_get_cstr(h->ip), + (e) ? "found" : "not found"); + + mresp = mms_storeconf("Error-permanent-message-not-found", + octstr_get_cstr(otransid),NULL, 0,menc); + goto store_done; + } + sdf = mms_mmbox_addmsg(octstr_get_cstr(settings->mmbox_rootdir), + octstr_get_cstr(h->client_addr), mstore, + xflags, + xstate ? xstate : octstr_imm("New")); + + /* XXX perhaps qualify errors better? */ + mmbox_store_status = sdf ? "Success" : "Error-permanent-failure"; + if (sdf) + mmbox_loc = mms_makefetchurl(octstr_get_cstr(sdf), NULL, + MMS_LOC_MMBOX, settings); + + } else { /* it is in mmbox, just update. */ + int xret; + + xret = mms_mmbox_modmsg(octstr_get_cstr(settings->mmbox_rootdir), + octstr_get_cstr(h->client_addr), qf, + xstate, + xflags); + + /* XXX perhaps qualify errors better? */ + mmbox_store_status = (xret == 0) ? "Success" : "Error-permanent-failure"; + if (xret == 0) + mmbox_loc = mms_makefetchurl(octstr_get_cstr(qf), NULL, + MMS_LOC_MMBOX, settings); + + } + + + if (mmbox_loc) { + mresp = mms_storeconf("Success", + octstr_get_cstr(otransid), + mmbox_loc,0,menc); + mms_log("Stored", h->client_addr, NULL, msize, otransid, NULL, NULL, "MM1", + h->ua, sdf ? sdf : qf); + } else + mresp = mms_storeconf("Error-transient-failure", + octstr_get_cstr(otransid),NULL, 0,menc); + + + store_done: + + if (xstate) + octstr_destroy(xstate); + if (xflags) + list_destroy(xflags, (list_item_destructor_t *)octstr_destroy); + + if (mstore) + mms_destroy(mstore); + + if (e) { /* Update the message queue and go. */ + e->lastaccess = time(NULL); + if (mms_queue_update(e) != 1) /* Should be freed. */ + mms_queue_free_env(e); + e = NULL; + } + + if (qf) + octstr_destroy(qf); + if (token) + octstr_destroy(token); + if (mh) + http_destroy_headers(mh); + if (otransid) + octstr_destroy(otransid); + if (url) + octstr_destroy(url); + + + if (mmbox_loc) + octstr_destroy(mmbox_loc); + + if (sdf) + octstr_destroy(sdf); + + reply_body = mms_tobinary(mresp); + notify_cmd = "stored"; + } + break; + + case MMS_MSGTYPE_MBOX_UPLOAD_REQ: + { + List *mh = mms_message_headers(m); + MmsMsg *mstore = NULL; + Octstr *ctype = NULL, *charset = NULL; + Octstr *otransid = http_header_value(mh, octstr_imm("X-Mms-Transaction-ID")); + char *mmbox_store_status = NULL; + Octstr *mmbox_loc = NULL; + Octstr *sdf = NULL; + Octstr *s = NULL; + + http_header_get_content_type(mh, &ctype, &charset); + + if (charset) + octstr_destroy(charset); + + /* If: + * - body type is not mms type, or + * - we are unable to parse it + * we fail. + */ + if (!ctype || + octstr_case_compare(ctype, octstr_imm("application/vnd.wap.mms-message")) != 0 || + (s = mms_msgbody(m)) == NULL || + (mstore = mms_frombinary(s,octstr_imm("anon@anon"))) == NULL) + mresp = mms_storeconf("Error-permanent-message-format-corrupt", + octstr_get_cstr(otransid), + NULL,1,menc); + else { + sdf = mms_mmbox_addmsg(octstr_get_cstr(settings->mmbox_rootdir), + octstr_get_cstr(h->client_addr), mstore, + NULL, + octstr_imm("Draft")); + + /* XXX perhaps qualify errors better? */ + mmbox_store_status = sdf ? "Success" : "Error-permanent-failure"; + if (sdf) + mmbox_loc = mms_makefetchurl(octstr_get_cstr(sdf), NULL, + MMS_LOC_MMBOX, settings); + + if (mmbox_loc) { + mresp = mms_storeconf("Success", + octstr_get_cstr(otransid), + mmbox_loc,1,menc); + mms_log("Stored", h->client_addr, NULL, msize, otransid, NULL, NULL, "MM1", + h->ua, sdf); + } else + mresp = mms_storeconf("Error-transient-failure", + octstr_get_cstr(otransid),NULL, 1,menc); + } + + if (mstore) + mms_destroy(mstore); + + if (mh) + http_destroy_headers(mh); + if (otransid) + octstr_destroy(otransid); + if (s) + octstr_destroy(s); + + if (ctype) + octstr_destroy(ctype); + if (mmbox_loc) + octstr_destroy(mmbox_loc); + + if (sdf) + octstr_destroy(sdf); + + reply_body = mms_tobinary(mresp); + notify_cmd = "uploaded"; + } + break; + + case MMS_MSGTYPE_MBOX_DELETE_REQ: + { + List *lh = mms_get_header_values(m, octstr_imm("X-Mms-Content-Location")); + Octstr *otransid = mms_get_header_value(m, octstr_imm("X-Mms-Transaction-ID")); + int i; + List *cls = list_create(); + List *rss = list_create(); + + mresp = mms_deleteconf(menc, octstr_get_cstr(otransid)); + + for (i = 0; i < list_len(lh); i++) { + Octstr *url = list_get(lh,i); + int mloc; + Octstr *qf = NULL, *token = NULL; + Octstr *cl, *rs = NULL; + int j, m; + + cl = octstr_format("%d%S", i, url); + if (mms_decodefetchurl(url, &qf, &token,&mloc) != 0) { + error(0, "MMS Send interface: failed to decode delete url (%s) from %s!", + octstr_get_cstr(url), + octstr_get_cstr(h->ip)); + rs = octstr_format("%dError-permanent-message-not-found", i); + + } else if (mloc == MMS_LOC_MQUEUE) { + MmsEnvelope *e = mms_queue_readenvelope(octstr_get_cstr(qf), + octstr_get_cstr(settings->mm1_queuedir), 1); + if (!e) + rs = octstr_format("%dError-permanent-message-not-found", i); + else { + for (j = 0, m = (e->to ? list_len(e->to) : 0); j < m; j++) { + MmsEnvelopeTo *x = list_get(e->to,j); + if (x) x->process = 0; + } + if (mms_queue_update(e) != 1) /* Should be freed. */ + mms_queue_free_env(e); + rs = octstr_format("%dOk", i); + } + } else if (mloc == MMS_LOC_MMBOX) { + int ret2 = mms_mmbox_delmsg(octstr_get_cstr(settings->mmbox_rootdir), + octstr_get_cstr(h->client_addr),qf); + if (ret2 == 0) + rs = octstr_format("%dOk", i); + else /* XXX better error reporting... */ + rs = octstr_format("%dError-permanent-message-not-found", i); + } + + if (!rs) + rs = octstr_format("%dError-permanent-message-not-found", i); + + list_append(rss, rs); + list_append(cls, cl); + + if (qf) + octstr_destroy(qf); + if (token) + octstr_destroy(token); + } + + /* put in response codes. */ + mms_replace_header_values(mresp, "X-Mms-Content-Location", cls); + mms_replace_header_values(mresp, "X-Mms-Response-Status", rss); + + + list_destroy(cls, (list_item_destructor_t *)octstr_destroy); + list_destroy(rss, (list_item_destructor_t *)octstr_destroy); + list_destroy(lh, (list_item_destructor_t *)octstr_destroy); + + if (otransid) + octstr_destroy(otransid); + + reply_body = mms_tobinary(mresp); + notify_cmd = "deleted"; + } + break; + + case MMS_MSGTYPE_MBOX_VIEW_REQ: + { + /* Get the search params, search, build response, go. */ + Octstr *otransid = mms_get_header_value(m, octstr_imm("X-Mms-Transaction-ID")); + List *xstates = mms_get_header_values(m, octstr_imm("X-Mms-MM-State")); + List *xflags = mms_get_header_values(m, octstr_imm("X-Mms-MM-Flags")); + List *msgs = mms_get_header_values(m, octstr_imm("X-Mms-Content-Location")); + List *required_headers = mms_get_header_values(m, octstr_imm("X-Mms-Attributes")); + List *otherhdrs = http_create_empty_headers(); + + List *msgrefs = NULL, *msglocs = NULL; + char *err = "Ok"; + Octstr *x; + int start, limit; + + if ((x = mms_get_header_value(m, octstr_imm("X-Mms-Start"))) != NULL) { + sscanf(octstr_get_cstr(x), "%d", &start); + octstr_destroy(x); + } else + start = 0; + + if ((x = mms_get_header_value(m, octstr_imm("X-Mms-Limit"))) != NULL) { + sscanf(octstr_get_cstr(x), "%d", &limit); + octstr_destroy(x); + } else + limit = INT_MAX; + + /* Check for quota and count requests. */ + if ((x = mms_get_header_value(m, octstr_imm("X-Mms-Totals"))) != NULL) { + if (octstr_case_compare(x, octstr_imm("Yes")) == 0) { + unsigned long byte_count = 0, msg_count = 0; + char y[64]; + mms_mmbox_count(octstr_get_cstr(settings->mmbox_rootdir), + octstr_get_cstr(h->client_addr), + &msg_count, &byte_count); + + sprintf(y, "%d bytes", (int)byte_count); + http_header_add(otherhdrs, "X-Mms-Mbox-Totals", y); + + sprintf(y, "%d msgs", (int)msg_count); + http_header_add(otherhdrs, "X-Mms-Mbox-Totals", y); + + } + octstr_destroy(x); + } + + if ((x = mms_get_header_value(m, octstr_imm("X-Mms-Quotas"))) != NULL) { + if (octstr_case_compare(x, octstr_imm("Yes")) == 0) { /* will we ever implement message quota?? */ + char y[64]; + + sprintf(y, "%d bytes", USER_MMBOX_DATA_QUOTA); + http_header_add(otherhdrs, "X-Mms-Mbox-Quotas", y); + } + octstr_destroy(x); + } + + /* Should we add the filter and limit headers to otherhdrs? + * why bother when send knows them? + */ + if (h->prof) { + int i, n; + + for (i = 0, n = msgs ? list_len(msgs) : 0; immbox_rootdir), + octstr_get_cstr(h->client_addr), xstates, + xflags, start, limit, msgs); + /* Make the locations. */ + msglocs = list_create(); + for (i = 0, n = list_len(msgrefs); i < n; i++) { + Octstr *sdf = list_get(msgrefs, i); + list_append(msglocs, + mms_makefetchurl(octstr_get_cstr(sdf), + NULL, MMS_LOC_MMBOX, settings)); + } + } else /* Profile not loaded... */ + err = "Error-transient-network-problem"; + + mresp = mms_viewconf(octstr_get_cstr(otransid), + msgrefs, + msglocs, + err, + required_headers, + (MmsMsgGetFunc_t *)mms_mmbox_get, + octstr_get_cstr(settings->mmbox_rootdir), + octstr_get_cstr(h->client_addr), + mms_ua_maxmsgsize(h->prof), + MS_1_2, + otherhdrs); + + reply_body = mms_tobinary(mresp); + notify_cmd = "deleted"; + + if (xflags) + list_destroy(xflags, (list_item_destructor_t *)octstr_destroy); + if (xstates) + list_destroy(xstates, (list_item_destructor_t *)octstr_destroy); + if (required_headers) + list_destroy(required_headers, (list_item_destructor_t *)octstr_destroy); + + if (msgrefs) + list_destroy(msgrefs, (list_item_destructor_t *)octstr_destroy); + + if (msglocs) + list_destroy(msglocs, (list_item_destructor_t *)octstr_destroy); + + if (msgs) + list_destroy(msgs, (list_item_destructor_t *)octstr_destroy); + + if (otherhdrs) + http_destroy_headers(otherhdrs); + + if (otransid) + octstr_destroy(otransid); + } + break; + default: http_header_add(rh, "Content-Type", "text/plain"); ctype_set = 1; diff --git a/mbuni/mmsc/mmssend.c b/mbuni/mmsc/mmssend.c index eadaf03..a58fc7e 100644 --- a/mbuni/mmsc/mmssend.c +++ b/mbuni/mmsc/mmssend.c @@ -1,5 +1,6 @@ #include #include +#include #include "mms_queue.h" #include "mms_uaprof.h" #include "mms_util.h" @@ -46,7 +47,7 @@ static int find_own(int i, int argc, char *argv[]) ch = octstr_get_char(data, 0); if (isprint(ch)) { MIMEEntity *mime = mime_octstr_to_entity(data); - MmsMsg *mm; + MmsMsg *mm = NULL; if (mime && (mm = mms_frommime(mime)) != NULL) { octstr_destroy(data); data = mms_tobinary(mm); @@ -139,7 +140,7 @@ int main(int argc, char *argv[]) if (data) { m = mms_frombinary(data, from ? from : octstr_imm("anon@anon")); if (m) - mms_msgdump(m,0); + mms_msgdump(m,1); msize = octstr_len(data); } else msize = 0; @@ -152,48 +153,12 @@ int main(int argc, char *argv[]) if (savetommbox) mmbox = mms_mmbox_addmsg(octstr_get_cstr(settings->mmbox_rootdir), - octstr_get_cstr(from), m, octstr_imm("Sent")); + octstr_get_cstr(from), m, NULL, octstr_imm("Sent")); - mms_log("Received", from, to, msize, s, NULL, NULL, "mmssend",NULL); + mms_log("Received", from, to, msize, s, NULL, NULL, "mmssend",NULL,NULL); printf("Queued: %s, mmbox=%s\n", octstr_get_cstr(s), mmbox ? octstr_get_cstr(mmbox) : ""); octstr_destroy(s); - -#if 0 - List *l = list_create(); - - list_append(l, octstr_imm("+testing")); - list_append(l, octstr_imm("-naughty")); - list_append(l, octstr_imm("+adult")); - list_append(l, octstr_imm("+adult")); - list_append(l, octstr_imm("+adult-2")); - int ret = mms_mmbox_modmsg(octstr_get_cstr(settings->mmbox_rootdir), - octstr_get_cstr(from), - octstr_imm("h-cs-df1111155064.1.x898915"), - octstr_imm("Draft"), l); - -#else - - List *l = list_create(); - List *sl = list_create(); - - -// list_append(l, octstr_imm("/naughty")); - - list_append(sl, octstr_imm("Draft")); - l = mms_mmbox_search(octstr_get_cstr(settings->mmbox_rootdir), - octstr_get_cstr(from), sl, l, -1, 2000); - - int ii; - - for (ii = 0; iimmbox_rootdir), - octstr_get_cstr(from), octstr_imm("h-cs-df1111155064.1.x898915")); - if (mm) - mms_msgdump(mm,1); -#endif return 0; }