diff --git a/mbuni/mmlib/mms_util.c b/mbuni/mmlib/mms_util.c index 7baf082..a06efc4 100644 --- a/mbuni/mmlib/mms_util.c +++ b/mbuni/mmlib/mms_util.c @@ -514,7 +514,7 @@ void base64_mimeparts(MIMEEntity *m, int all) } } -static void addmmscname(Octstr *s, Octstr *myhostname) +void addmmscname(Octstr *s, char *myhostname) { int j; int len = octstr_len(s); @@ -524,7 +524,7 @@ static void addmmscname(Octstr *s, Octstr *myhostname) j = octstr_case_search(s, octstr_imm("/TYPE=PLMN"), 0); if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len) /* A proper number. */ - octstr_format_append(s, "@%S", myhostname); + octstr_format_append(s, "@%s", myhostname); } @@ -554,7 +554,7 @@ static int send2email(List *xto, Octstr *from, Octstr *subject, List *lcc = http_header_find_all(headers, "Cc"); if (xfrom) { - addmmscname(xfrom, myhostname); + addmmscname(xfrom, octstr_get_cstr(myhostname)); http_header_add(l, "From", octstr_get_cstr(xfrom)); octstr_destroy(xfrom); } @@ -569,7 +569,7 @@ static int send2email(List *xto, Octstr *from, Octstr *subject, octstr_case_compare(name, octstr_imm("To")) != 0) goto loop; - addmmscname(value, myhostname); + addmmscname(value, octstr_get_cstr(myhostname)); http_header_add(l, "To", octstr_get_cstr(value)); loop: octstr_destroy(value); @@ -588,7 +588,7 @@ static int send2email(List *xto, Octstr *from, Octstr *subject, octstr_case_compare(name, octstr_imm("Cc")) != 0) goto loop2; - addmmscname(value, myhostname); + addmmscname(value, octstr_get_cstr(myhostname)); http_header_add(l, "Cc", octstr_get_cstr(value)); loop2: octstr_destroy(value); @@ -643,7 +643,7 @@ static int send2email(List *xto, Octstr *from, Octstr *subject, case 'f': if (append_hostname) { Octstr *xfrom = octstr_duplicate(from); - addmmscname(xfrom, myhostname); + addmmscname(xfrom, octstr_get_cstr(myhostname)); escape_shell_chars(xfrom); octstr_append(cmd, xfrom); @@ -757,7 +757,7 @@ static int smtp_send(char *relay_host, int port, Octstr *from, List *to, Octstr if (code != (val) && !(cont)) \ goto done; \ } while (0) \ - + SANDC("HELO %s\r\n", tbuf, 250,0); SANDC("MAIL FROM:<%S>\r\n", from, 250,0); @@ -2677,3 +2677,484 @@ done: octstr_destroy(q); return res; } + +/* little dirty method to see if file begins with url scheme. */ +static int has_url_scheme(char *url, int *supported_scheme) +{ + char *p = strstr(url, "://"); + + *supported_scheme = 1; + + if (strstr(url, "data:") == url || /* data: url scheme */ + strstr(url, "http://") == url || +#ifdef HAVE_LIBSSL + strstr(url, "https://") == url || +#endif + strstr(url, "file://") == url) + return 1; + + if (p) { + + for (p--; p >= url; p--) + if (!isalpha(*p)) + break; + if (p < url) { + *supported_scheme = 0; /* we don't support this one. */ + return 1; + } else + return 0; + } else + return 0; +} + +static int add_msg_part(MIMEEntity *res, xmlNodePtr node, Octstr *base_url, + Octstr *top_url, + int type, Octstr *svc_name, + Octstr *mmc_id, + Dict *url_map, Octstr *xmhdr, Octstr *xmhdr_val, + int (*filter)(MIMEEntity **msg, Octstr *loc_url, Octstr *mmc_id)) +{ + Octstr *curl = NULL, *ctype = NULL, *body = NULL, *xcid = NULL; + char *src = NULL; + int isurl, slash_prefix; + Octstr *cid = NULL; + int supported_url_scheme = 0; + + /* For each node in the smil doc, if it has an src attribute, then: + * - if our type of base_url is FILE *and the src attribute does not look + * like a url, then file the file referenced, load it into the message and go + * - if our type is URL and the url scheme is http/https (or has no scheme) + * then fetch it and put into message. + */ + + if (!node || node->type != XML_ELEMENT_NODE || + (src = (char *)xmlGetProp(node, (unsigned char *)"src")) == NULL) + return 0; /* Nothing to do. */ + + if (src[0] == '\\') { /* User can escape url to prevent substitution. */ + xmlSetProp(node, (xmlChar *)"src", (xmlChar *)(src + 1)); + goto done; + } + + isurl = has_url_scheme(src, &supported_url_scheme); + slash_prefix = (src[0] == '/'); + + if (isurl && !supported_url_scheme) + goto done; + else if (isurl) + curl = octstr_create(src); + else if (slash_prefix) { + if (type == URL_TYPE) + curl = octstr_format("%S%s", + top_url, src); + else + curl = octstr_create(src); + } else + curl = octstr_format("%S/%s",base_url, src); + + if ((cid = dict_get(url_map, curl)) != NULL) { /* We've seen it before. */ + xmlSetProp(node, (xmlChar *)"src", (xmlChar *)octstr_get_cstr(cid)); + /* Don't delete cid! */ + goto done; + } + + isurl |= (type == URL_TYPE); /* From now on, this flag tells us whether we are fetching a url.*/ + + if (isurl) { + List *rh = http_create_empty_headers(), *rph = NULL; + + http_header_add(rh, "User-Agent", MM_NAME "/" VERSION); + if (mms_url_fetch_content(HTTP_METHOD_GET, curl, rh, NULL, &rph, &body) == HTTP_OK) { + ctype = http_header_value(rph, octstr_imm("Content-Type")); + xcid = http_header_value(rph, octstr_imm("Content-ID")); + } else + mms_error(0, "mmsbox", NULL, "Failed to load url %s within SMIL content from service %s!", + octstr_get_cstr(curl), + svc_name ? octstr_get_cstr(svc_name) : "unknown"); + if (rph) + http_destroy_headers(rph); + http_destroy_headers(rh); + } else { + body = octstr_read_file(octstr_get_cstr(curl)); + ctype = filename2content_type(src); + } + + if (ctype && body) { /* If we got it, put it in. */ + static int cntr; /* For generating cids */ + char _fext[5] = {0}, *fext = make_file_ext(curl, ctype, _fext); + Octstr *attr = xcid ? octstr_format("cid:%S", xcid) : octstr_format("cid:%06d.%s", ++cntr,fext); + char *p = octstr_get_cstr(attr) + 4; + Octstr *cid_header_val = octstr_format("<%s>", p); + MIMEEntity *x = mime_entity_create(); + List *headers = http_create_empty_headers(); + + http_header_add(headers, "Content-Type", octstr_get_cstr(ctype)); + http_header_add(headers, "Content-ID", octstr_get_cstr(cid_header_val)); + http_header_add(headers, "Content-Location", p); + + if (xmhdr) + http_header_add(headers, octstr_get_cstr(xmhdr), octstr_get_cstr(xmhdr_val)); + + mime_replace_headers(x, headers); + mime_entity_set_body(x, body); + + + if (filter && mmc_id) + filter(&x, curl, mmc_id); + + mime_entity_add_part(res, x); + mime_entity_destroy(x); + + dict_put_once(url_map, curl, octstr_duplicate(attr)); /* Store the cid. */ + + xmlSetProp(node, (xmlChar *)"src", (xmlChar *)octstr_get_cstr(attr)); + + octstr_destroy(attr); + octstr_destroy(cid_header_val); + http_destroy_headers(headers); + } + +done: + + octstr_destroy(curl); + octstr_destroy(ctype); + octstr_destroy(body); + octstr_destroy(xcid); + xmlFree(src); + return 0; +} + +/* Traverse the tree doing the above. */ +static void add_msg_parts(MIMEEntity *res, xmlNodePtr node, Octstr *base_url, + Octstr *top_url, + int type, Octstr *svc_name, + Octstr *mmc_id, + Dict *url_map, Octstr *xmhdr, Octstr *xmhdr_val, + int (*filter)(MIMEEntity **msg, Octstr *loc_url, Octstr *mmc_id)) +{ + xmlNodePtr n; + /* Do all the children recursively, then come back and do parent. */ + for (n = node; n; n = n->next) + if (n->type != XML_COMMENT_NODE) { + add_msg_part(res, n, base_url, top_url, type, svc_name, mmc_id, url_map, xmhdr, + xmhdr_val, filter); + add_msg_parts(res, n->xmlChildrenNode, base_url, top_url, type, + svc_name, mmc_id, url_map, xmhdr, xmhdr_val, filter); + } +} +/* Get's just the host:port part, leaving out UrI */ +static Octstr *get_toplevel_url(Octstr *url) +{ + int i, len = octstr_len(url); + char *p = octstr_get_cstr(url); + + i = octstr_search(url, octstr_imm("://"),0); + + if (i > 0) + i += 3; + else + i = 0; + + for ( ; i < len; i++) + if (p[i] == '/') + break; + + return octstr_copy(url, 0, i); +} + +static Octstr *url_path_prefix(Octstr *url, int type) +{ + int i, j, len = octstr_len(url); + char *p = octstr_get_cstr(url); + + /* Set lower/upper limit of search. */ + if (type == URL_TYPE) { /* then skip first slashes. */ + char *x; + i = octstr_search(url, octstr_imm("://"),0); + if (i > 0) + i += 3; + else + i = 0; + x = rindex(p, '#'); /* look for fragment if any. */ + + if (x) + j = x - p - 1; + else + j = len - 1; + } else { + i = 0; + j = len - 1; + } + + /* Now search backwards for the last '/'. + * if you don't find one, set to end of string. + */ + + for (;j > i; j--) + if (p[j] == '/') + break; + if (j <= i) + j = len; + + return octstr_copy(url, 0, j); +} + + +void get_content_from_sendmms_request(Octstr *body, List *headers, List *cgivars, List *cgivar_ctypes, + List **rh, Octstr **ctype, Octstr **data, + Octstr **rb, + Octstr **base_url, Octstr **data_url) +{ + Octstr *s; + /* Now get the data. */ + if ((*data = http_cgi_variable(cgivars, "text")) != NULL) { /* text. */ + Octstr *charset = http_cgi_variable(cgivars, "charset"); + + *ctype = octstr_format("text/plain"); + if (charset) + octstr_format_append(*ctype, "; charset=%S", charset); + } else if ((s = http_cgi_variable(cgivars, "smil")) != NULL) { /* smil. */ + *ctype = octstr_create("application/smil"); + *data = octstr_duplicate(s); + } else if ((s = http_cgi_variable(cgivars, "content-url")) != NULL) { /* arbitrary content. */ + List *reqh = http_create_empty_headers(), *rph = NULL; + Octstr *reply = NULL, *params = NULL; + + http_header_add(reqh, "User-Agent", MM_NAME "/" VERSION); + + if (mms_url_fetch_content(HTTP_METHOD_GET, s, reqh, NULL, &rph, &reply) == HTTP_OK) + get_content_type(rph, ctype, ¶ms); + else + *rb = octstr_format("failed to fetch content from url [%S]!", s); + *base_url = url_path_prefix(s, URL_TYPE); + + *data_url = octstr_duplicate(s); /* the URL of the message. */ + *data = reply; + + http_destroy_headers(reqh); + http_destroy_headers(*rh); + *rh = rph ? rph : http_create_empty_headers(); /* replace as real reply headers. */ + *ctype = http_header_value(*rh, octstr_imm("Content-Type")); + octstr_destroy(params); + } else if ((s = http_cgi_variable(cgivars, "content")) != NULL) { /* any content. */ + Octstr *_xctype = NULL; /* ... because cgi var stuff is destroyed elsewhere, we must dup it !! */ + + *data = octstr_duplicate(s); + /* If the user sent us a content element, then they should have + * sent us its type either as part of the HTTP POST (multipart/form-data) + * or as CGI VAR called content_type + */ + if ((_xctype = http_cgi_variable(cgivars, "content_type")) == NULL) + if (cgivar_ctypes) + _xctype = http_cgi_variable(cgivar_ctypes, "content"); + if (_xctype) + *ctype = octstr_duplicate(_xctype); + else + *ctype = octstr_create("application/octet-stream"); + } else if (body) { /* if all above fails, + use send-mms msg body if any. */ + *data = octstr_duplicate(body); + *ctype = http_header_value(headers, octstr_imm("Content-Type")); + } else + *rb = octstr_create("Missing content"); +} + +MmsMsg *make_msg_from_sendmms_request(Octstr *from, List *to, + Octstr *msgId, + Octstr *subject, + Octstr *data, Octstr *ctype, + List *reply_headers, + Octstr *msg_url, + Octstr *base_url, int type, + Octstr *mmc, + Octstr *svc_name, + time_t expiryt, + int do_multipart, + int do_rr, + int do_dlr, + char *allow_adaptations, + int (*filter)(MIMEEntity **msg, Octstr *loc_url, Octstr *mmc_id), + Octstr **err) +{ + Octstr *mclass = http_header_value(reply_headers, octstr_imm("X-Mbuni-MessageClass")); + Octstr *prio = http_header_value(reply_headers, octstr_imm("X-Mbuni-Priority")); + Octstr *turl = get_toplevel_url(base_url); + MmsMsg *m = NULL; + MIMEEntity *me = mime_entity_create(); + Octstr *xmhdr = NULL, *xmhdr_val = NULL; + List *xheaders = NULL; + int i, n; + + if (octstr_str_case_compare(ctype, "application/vnd.wap.mms-message") == 0) + m = mms_frombinary(data, from); + else if (octstr_case_search(ctype, octstr_imm("multipart/"), 0) == 0) { /* treat it differently. */ + MIMEEntity *mime = mime_http_to_entity(reply_headers, data); + if (mime) { + mime_entity_destroy(me); + me = mime; + } + } else if (octstr_case_search(ctype, + octstr_imm(MBUNI_MULTIPART_TYPE), 0) == 0) { /* Mbuni multipart.*/ + List *l = octstr_split_words(data); + MIMEEntity *mime = multipart_from_urls(l); + + if (mime) { + mime_entity_destroy(me); + me = mime; + } + gwlist_destroy(l, (void *)octstr_destroy); + } else if (octstr_case_search(ctype, octstr_imm("application/smil"), 0) == 0) { + xmlDocPtr smil; + xmlChar *buf = NULL; + int bsize = 0; + Dict *url_map = dict_create(97, (void (*)(void *))octstr_destroy); + List *xh = http_create_empty_headers(); + + /* This is the hard bit: Fetch each external reference in smil, add it to message! */ + http_header_add(xh, "Content-Type", "multipart/related; " + "type=\"application/smil\"; start=\"\""); + mime_replace_headers(me,xh); + http_destroy_headers(xh); + + /* Parse the smil as XML. */ + smil = xmlParseMemory(octstr_get_cstr(data), octstr_len(data)); + if (!smil || !smil->xmlChildrenNode) { + *err = octstr_format("MMSBox: Error parsing SMIL response from service[%s], " + " msgid %s!", octstr_get_cstr(svc_name), + msgId ? octstr_get_cstr(msgId) : "(none)"); + dict_destroy(url_map); + goto done; + } + + add_msg_parts(me, smil->xmlChildrenNode, + base_url, turl, type, svc_name, + mmc, url_map, xmhdr, xmhdr_val, + filter); + + dict_destroy(url_map); + /* SMIL has been modified, convert it to text, put it in. */ + xmlDocDumpFormatMemory(smil, &buf, &bsize, 1); + xmlFreeDoc(smil); + if (buf) { + MIMEEntity *sm = mime_entity_create(); + List *xh = http_create_empty_headers(); + Octstr *s; + + http_header_add(xh, "Content-Type", "application/smil"); + http_header_add(xh, "Content-ID", ""); /* identify it as start element. */ + if (xmhdr) + http_header_add(xh, octstr_get_cstr(xmhdr), octstr_get_cstr(xmhdr_val)); + s = octstr_create_from_data((char *)buf, bsize); + + mime_replace_headers(sm, xh); + mime_entity_set_body(sm, s); + + mime_entity_add_part(me, sm); + + mime_entity_destroy(sm); + http_destroy_headers(xh); + octstr_destroy(s); + + xmlFree(buf); + } else { + *err = octstr_format("MMSBox: Error writing converted SMIL " + "for response from service[%s], " + " msgid %s!", + octstr_get_cstr(svc_name), + (msgId) ? octstr_get_cstr(msgId) : "(none)"); + goto done; + } + } else { /* all others, make the message as-is and hope for the best! */ + List *xh = http_create_empty_headers(); + + if (do_multipart) { /* if it's going to be multi-part, add some headers. */ + static int cntr = 0; + char _fext[5] = {0}, *fext = make_file_ext(msg_url, ctype, _fext); + Octstr *attr = octstr_format("%06d.%s", ++cntr,fext); + Octstr *cid_header_val = octstr_format("<%S>", attr); + + http_header_add(xh, "Content-ID", octstr_get_cstr(cid_header_val)); + http_header_add(xh, "Content-Location", octstr_get_cstr(attr)); + + octstr_destroy(attr); + octstr_destroy(cid_header_val); + } + + http_header_add(xh, "Content-Type", octstr_get_cstr(ctype)); + if (xmhdr) + http_header_add(xh, octstr_get_cstr(xmhdr), octstr_get_cstr(xmhdr_val)); + + mime_replace_headers(me, xh); + + http_destroy_headers(xh); + mime_entity_set_body(me, data); + + if (filter && mmc) /* filter it too. */ + filter(&me, msg_url, mmc); + + if (do_multipart && + octstr_case_search(ctype, octstr_imm("multipart/"), 0) != 0) { /* requires multipart but this one is not, wrap it */ + MIMEEntity *xm = mime_entity_create(); + List *h1 = http_create_empty_headers(); + + http_header_add(h1, "Content-Type", "multipart/related"); + mime_replace_headers(xm, h1); + mime_entity_add_part(xm, me); + + http_destroy_headers(h1); + + me = xm; + } + } + + /* Add some nice headers. */ + xheaders = mime_entity_headers(me); + http_header_add(xheaders, "From", octstr_get_cstr(from)); + + for (i = 0, n = gwlist_len(to); i < n; i++) { + Octstr *v; + v = gwlist_get(to, i); + http_header_add(xheaders, "To", octstr_get_cstr(v)); + } + + if (do_dlr) + http_header_add(xheaders, "X-Mms-Delivery-Report", "Yes"); + if (do_rr) + http_header_add(xheaders, "X-Mms-Read-Report", "Yes"); + if (allow_adaptations) + http_header_add(xheaders, "X-Mms-Allow-Adaptations", + (strcasecmp(allow_adaptations, "true") == 0) ? "true" : "false"); + + if (mclass) + http_header_add(xheaders, "X-Mms-Message-Class", octstr_get_cstr(mclass)); + + if (prio) + http_header_add(xheaders, "X-Mms-Priority", octstr_get_cstr(prio)); + + if (subject) + http_header_add(xheaders, "Subject", octstr_get_cstr(subject)); + + if (expiryt > 0) { + Octstr *x = date_format_http(expiryt); + http_header_add(xheaders, "X-Mms-Expiry", octstr_get_cstr(x)); + octstr_destroy(x); + } + mime_replace_headers(me, xheaders); + + + if (me && !m) /* Set m if it hasn't been set yet. */ + m = mms_frommime(me); + if (!m) + *err = octstr_format("MMSBox: Failed to convert Mms Message from service %s!", + octstr_get_cstr(svc_name)); + +done: + octstr_destroy(mclass); + octstr_destroy(prio); + if (me) + mime_entity_destroy(me); + octstr_destroy(xmhdr_val); + octstr_destroy(turl); + http_destroy_headers(xheaders); + return m; +} diff --git a/mbuni/mmlib/mms_util.h b/mbuni/mmlib/mms_util.h index 2be29c2..6cf76c5 100644 --- a/mbuni/mmlib/mms_util.h +++ b/mbuni/mmlib/mms_util.h @@ -267,8 +267,34 @@ void mygw_free(void *); /* Authenticate using HTTP Basic auth */ int http_auth_check(char *user, char *pass, List *headers, int *has_auth_hdr); +/* Add @host to an mms address */ +void addmmscname(Octstr *address, char *myhostname); + /* Get (copy of) keyword from mime thingie */ Octstr *get_keyword_from_mime(MIMEEntity *me); + +enum _xurltype {FILE_TYPE, URL_TYPE}; +void get_content_from_sendmms_request(Octstr *body, List *headers, List *cgivars, List *cgivar_ctypes, + List **rh, Octstr **ctype, Octstr **data, + Octstr **rb, + Octstr **base_url, Octstr **data_url); + +MmsMsg *make_msg_from_sendmms_request(Octstr *from, List *to, + Octstr *msgId, + Octstr *subject, + Octstr *data, Octstr *ctype, + List *reply_headers, + Octstr *msg_url, + Octstr *base_url, int type, + Octstr *mmc, + Octstr *svc_name, + time_t expiryt, + int do_multipart, + int do_rr, + int do_dlr, + char *allow_adaptations, + int (*filter)(MIMEEntity **msg, Octstr *loc_url, Octstr *mmc_id), + Octstr **err); #define US_ASCII_MIB_VAL 3 #define UTF8_MIB_VAL 106 diff --git a/mbuni/mmsbox/Makefile.am b/mbuni/mmsbox/Makefile.am index a6b70b5..af17131 100644 --- a/mbuni/mmsbox/Makefile.am +++ b/mbuni/mmsbox/Makefile.am @@ -1,8 +1,8 @@ -libmms = $(top_builddir)/mmlib/libmms.a +libmms = $(top_builddir)/mmlib/libmms.la lib_LTLIBRARIES = libmmsbox.la -libmmsbox_la_SOURCES = mmsbox_cdr.c mmsbox_cfg.c dlr.c bearerbox.c mmsbox_resolve.c mmsbox_resolve_shell.c +libmmsbox_la_SOURCES = mmsbox_cdr.c mmsbox_cfg.h mmsbox_cfg.c dlr.c bearerbox.c mmsbox_resolve.c mmsbox_resolve_shell.c bin_PROGRAMS = mmsbox -mmsbox_SOURCES = mmsbox.c -mmsbox_LDADD = libmmsbox.a $(libmms) +mmsbox_SOURCES = mmsbox.c mmsbox.h +mmsbox_LDADD = libmmsbox.la $(libmms) EXTRA_DIST = mmsbox_cdr.h mmsbox_cfg.h mmsbox.h mmsbox_mt_filter.h mmsbox_resolve_shell.h mmsbox_resolve.h mmsbox_mmsc.h diff --git a/mbuni/mmsbox/bearerbox.c b/mbuni/mmsbox/bearerbox.c index 2de4c18..deaa13c 100644 --- a/mbuni/mmsbox/bearerbox.c +++ b/mbuni/mmsbox/bearerbox.c @@ -2062,7 +2062,7 @@ static Octstr *handle_msg(MIMEEntity *mm, Octstr *from, List *to, MmscGrp *mmc) octstr_destroy(y); } } - if (mm4_type == NULL) { /* else assume a normal send message. */ + if (mm4_type == NULL && mtype < 0) { /* else assume a normal send message. */ http_header_add(headers, "X-Mms-Message-Type", "m-send-req"); mm1_type = MMS_MSGTYPE_SEND_REQ; mtype = MM4_FORWARD_REQ; diff --git a/mbuni/mmsbox/mmsbox.c b/mbuni/mmsbox/mmsbox.c index 42d37b5..ef6e868 100644 --- a/mbuni/mmsbox/mmsbox.c +++ b/mbuni/mmsbox/mmsbox.c @@ -97,137 +97,8 @@ static MmsService *get_service(Octstr *keyword, Octstr *mmc_id, Octstr *receiver return catch_all; } -static void add_all_matching_parts(MIMEEntity *plist, MmsServiceUrlParam *pm, - Octstr *keyword, - MIMEEntity *me, - MmsMsg *msg, int lev, int count) -{ - int i, n; - List *headers = NULL; - Octstr *data = NULL, *ctype = NULL, *xctype = NULL, *params = NULL; - Octstr *s; - - headers = mime_entity_headers(me); - if (pm->type == WHOLE_BINARY && lev == 0) { - data = mms_tobinary(msg); - ctype = octstr_create("application/vnd.wap.mms-message"); - } else if (pm->type == NO_PART && lev == 0) { - data = octstr_create(""); /* We'll add value below. */ - goto done; - } else if (pm->type == KEYWORD_PART && lev == 0) { - data = keyword ? octstr_duplicate(keyword) : octstr_create(""); - ctype = octstr_create("text/plain"); - goto done; - } - - if ((n = mime_entity_num_parts(me)) > 0) { /* Recurse over multi-parts. */ - for (i = 0; i < n; i++) { - MIMEEntity *x = mime_entity_get_part(me,i); - add_all_matching_parts(plist, pm, NULL, x, msg, lev+1,i); - mime_entity_destroy(x); - } - goto done; - } - - get_content_type(headers, &xctype, ¶ms); - -#define BEGINSWITH(s, prefix) (octstr_case_search(s, octstr_imm(prefix),0) == 0) -#define TYPE_MATCH(typ, prefix) ((pm->type) == (typ) && \ - BEGINSWITH(xctype, prefix)) - if (xctype) - if (TYPE_MATCH(IMAGE_PART,"image/") || - TYPE_MATCH(AUDIO_PART,"audio/") || - TYPE_MATCH(VIDEO_PART,"video/") || - TYPE_MATCH(TEXT_PART,"text/") || - TYPE_MATCH(SMIL_PART,"application/smil") || - pm->type == ANY_PART || /* Skip top-level for 'any' parts. */ - (pm->type == OTHER_PART && - (!BEGINSWITH(xctype, "text/") && - !BEGINSWITH(xctype, "video/") && - !BEGINSWITH(xctype, "image/") && - !BEGINSWITH(xctype, "application/smil")))) { - - ctype = http_header_value(headers, octstr_imm("Content-Type")); - data = mime_entity_body(me); - } - -done: - if (data) { - MIMEEntity *p = mime_entity_create(); - Octstr *cd = octstr_format("form-data; name=\"%S\"", pm->name); - List *xh; - - if (ctype && pm->type != KEYWORD_PART) { - /* If Content-Location header or name (content-type) parameter given, pass it as filename. */ - Octstr *c = NULL, *q = NULL; - Octstr *cloc = http_header_value(headers, - octstr_imm("Content-Location")); - split_header_value(ctype, &c, &q); - - if (q || cloc) { - List *ph = q ? get_value_parameters(q) : http_create_empty_headers(); - Octstr *v = cloc ? cloc : http_header_value(ph, octstr_imm("name")); - - if (!v) /* make up a fake name if none is given */ - v = octstr_format("part-%d-%d", lev, count); - - octstr_format_append(cd, "; filename=\"%S\"", v); - http_header_remove_all(ph, "name"); - - if (v != cloc) - octstr_destroy(v); - octstr_destroy(ctype); - - v = make_value_parameters(ph); - if (v && octstr_len(v) > 0) - ctype = octstr_format("%S; %S", c, v); - else - ctype = octstr_duplicate(c); - - octstr_destroy(v); - - http_destroy_headers(ph); - - octstr_destroy(q); - } - - - octstr_destroy(c); - octstr_destroy(cloc); - } - - xh = http_create_empty_headers(); - http_header_add(xh, "Content-Disposition", octstr_get_cstr(cd)); - if (ctype) /* This header must come after the above it seems. */ - http_header_add(xh, "Content-Type", octstr_get_cstr(ctype)); - - mime_replace_headers(p, xh); - http_destroy_headers(xh); - - s = octstr_duplicate(data); /* data for the parameter */ - if (pm->value) /* add value part as needed. */ - octstr_append(s, pm->value); - mime_entity_set_body(p, s); - octstr_destroy(s); -#if 0 - base64_mimeparts(p); -#endif - mime_entity_add_part(plist, p); /* add it to list so far. */ - mime_entity_destroy(p); - - octstr_destroy(cd); - } - octstr_destroy(xctype); - octstr_destroy(params); - octstr_destroy(ctype); - octstr_destroy(data); - - http_destroy_headers(headers); -} - -enum _xurltype {FILE_TYPE, URL_TYPE}; static Octstr *url_path_prefix(Octstr *url, int type); /* this function constructs and sends the message -- a bit too many params XXX! */ @@ -787,167 +658,6 @@ static Octstr *get_toplevel_url(Octstr *url) return octstr_copy(url, 0, i); } -/* little dirty method to see if file begins with url scheme. */ -static int has_url_scheme(char *url, int *supported_scheme) -{ - char *p = strstr(url, "://"); - - *supported_scheme = 1; - - if (strstr(url, "data:") == url || /* data: url scheme */ - strstr(url, "http://") == url || -#ifdef HAVE_LIBSSL - strstr(url, "https://") == url || -#endif - strstr(url, "file://") == url) - return 1; - - if (p) { - - for (p--; p >= url; p--) - if (!isalpha(*p)) - break; - if (p < url) { - *supported_scheme = 0; /* we don't support this one. */ - return 1; - } else - return 0; - } else - return 0; -} - -static int add_msg_part(MIMEEntity *res, xmlNodePtr node, Octstr *base_url, - Octstr *top_url, - int type, Octstr *svc_name, - Octstr *mmc_id, - Dict *url_map, Octstr *xmhdr, Octstr *xmhdr_val) -{ - Octstr *curl = NULL, *ctype = NULL, *body = NULL, *xcid = NULL; - char *src = NULL; - int isurl, slash_prefix; - Octstr *cid = NULL; - int supported_url_scheme = 0; - - /* For each node in the smil doc, if it has an src attribute, then: - * - if our type of base_url is FILE *and the src attribute does not look - * like a url, then file the file referenced, load it into the message and go - * - if our type is URL and the url scheme is http/https (or has no scheme) - * then fetch it and put into message. - */ - - if (!node || node->type != XML_ELEMENT_NODE || - (src = (char *)xmlGetProp(node, (unsigned char *)"src")) == NULL) - return 0; /* Nothing to do. */ - - if (src[0] == '\\') { /* User can escape url to prevent substitution. */ - xmlSetProp(node, (xmlChar *)"src", (xmlChar *)(src + 1)); - goto done; - } - - isurl = has_url_scheme(src, &supported_url_scheme); - slash_prefix = (src[0] == '/'); - - if (isurl && !supported_url_scheme) - goto done; - else if (isurl) - curl = octstr_create(src); - else if (slash_prefix) { - if (type == URL_TYPE) - curl = octstr_format("%S%s", - top_url, src); - else - curl = octstr_create(src); - } else - curl = octstr_format("%S/%s",base_url, src); - - if ((cid = dict_get(url_map, curl)) != NULL) { /* We've seen it before. */ - xmlSetProp(node, (xmlChar *)"src", (xmlChar *)octstr_get_cstr(cid)); - /* Don't delete cid! */ - goto done; - } - - isurl |= (type == URL_TYPE); /* From now on, this flag tells us whether we are fetching a url.*/ - - if (isurl) { - List *rh = http_create_empty_headers(), *rph = NULL; - - http_header_add(rh, "User-Agent", MM_NAME "/" VERSION); - if (mmsbox_url_fetch_content(HTTP_METHOD_GET, curl, rh, NULL, &rph, &body) == HTTP_OK) { - ctype = http_header_value(rph, octstr_imm("Content-Type")); - xcid = http_header_value(rph, octstr_imm("Content-ID")); - } else - mms_error(0, "mmsbox", NULL, "Failed to load url %s within SMIL content from service %s!", - octstr_get_cstr(curl), - svc_name ? octstr_get_cstr(svc_name) : "unknown"); - if (rph) - http_destroy_headers(rph); - http_destroy_headers(rh); - } else { - body = octstr_read_file(octstr_get_cstr(curl)); - ctype = filename2content_type(src); - } - - if (ctype && body) { /* If we got it, put it in. */ - static int cntr; /* For generating cids */ - char _fext[5] = {0}, *fext = make_file_ext(curl, ctype, _fext); - Octstr *attr = xcid ? octstr_format("cid:%S", xcid) : octstr_format("cid:%06d.%s", ++cntr,fext); - char *p = octstr_get_cstr(attr) + 4; - Octstr *cid_header_val = octstr_format("<%s>", p); - MIMEEntity *x = mime_entity_create(); - List *headers = http_create_empty_headers(); - - http_header_add(headers, "Content-Type", octstr_get_cstr(ctype)); - http_header_add(headers, "Content-ID", octstr_get_cstr(cid_header_val)); - http_header_add(headers, "Content-Location", p); - - if (xmhdr) - http_header_add(headers, octstr_get_cstr(xmhdr), octstr_get_cstr(xmhdr_val)); - - mime_replace_headers(x, headers); - mime_entity_set_body(x, body); - - - if (mt_filter && mmc_id) - mt_filter->filter(&x, curl, mmc_id); - - mime_entity_add_part(res, x); - mime_entity_destroy(x); - - dict_put_once(url_map, curl, octstr_duplicate(attr)); /* Store the cid. */ - - xmlSetProp(node, (xmlChar *)"src", (xmlChar *)octstr_get_cstr(attr)); - - octstr_destroy(attr); - octstr_destroy(cid_header_val); - http_destroy_headers(headers); - } - -done: - - octstr_destroy(curl); - octstr_destroy(ctype); - octstr_destroy(body); - octstr_destroy(xcid); - xmlFree(src); - return 0; -} - -/* Traverse the tree doing the above. */ -static void add_msg_parts(MIMEEntity *res, xmlNodePtr node, Octstr *base_url, - Octstr *top_url, - int type, Octstr *svc_name, - Octstr *mmc_id, - Dict *url_map, Octstr *xmhdr, Octstr *xmhdr_val) -{ - xmlNodePtr n; - /* Do all the children recursively, then come back and do parent. */ - for (n = node; n; n = n->next) - if (n->type != XML_COMMENT_NODE) { - add_msg_part(res, n, base_url, top_url, type, svc_name, mmc_id, url_map, xmhdr, xmhdr_val); - add_msg_parts(res, n->xmlChildrenNode, base_url, top_url, type, - svc_name, mmc_id, url_map, xmhdr, xmhdr_val); - } -} /* Given content, make a message. We'll also use this for send-mms-user! */ static int make_and_queue_msg(Octstr *data, Octstr *ctype, List *reply_headers, @@ -963,7 +673,6 @@ static int make_and_queue_msg(Octstr *data, Octstr *ctype, List *reply_headers, Octstr *allow_adaptations = NULL, *mclass = NULL, *prio = NULL, *distro = NULL, *chargedparty = NULL; MmsMsg *m = NULL; MIMEEntity *me = mime_entity_create(); - List *xheaders = NULL; List *hdrs = http_create_empty_headers(); Octstr *otransid = NULL; Octstr *xmhdr = NULL, *xmhdr_val = NULL; @@ -971,7 +680,12 @@ static int make_and_queue_msg(Octstr *data, Octstr *ctype, List *reply_headers, time_t expiryt = time(NULL) + DEFAULT_EXPIRE; Octstr *x; List *xto = gwlist_create(); - int i, n, res = -1; + int res = -1; + +#if 0 + int i, n; + List *xheaders = NULL; +#endif gw_assert(svc_name); @@ -1073,6 +787,7 @@ static int make_and_queue_msg(Octstr *data, Octstr *ctype, List *reply_headers, if (from) _mms_fixup_address(&from, NULL, NULL, 1); /* Don't normalise. */ +#if 0 /* Now get the data. */ if (octstr_str_case_compare(ctype, "application/vnd.wap.mms-message") == 0) m = mms_frombinary(data, from); @@ -1117,7 +832,8 @@ static int make_and_queue_msg(Octstr *data, Octstr *ctype, List *reply_headers, add_msg_parts(me, smil->xmlChildrenNode, base_url, turl, type, svc_name, - mmc, url_map, xmhdr, xmhdr_val); + mmc, url_map, xmhdr, xmhdr_val, + mt_filter ? mt_filter->filter : NULL); dict_destroy(url_map); /* SMIL has been modified, convert it to text, put it in. */ @@ -1236,7 +952,22 @@ static int make_and_queue_msg(Octstr *data, Octstr *ctype, List *reply_headers, octstr_get_cstr(svc_name)); goto done; } - +#else + m = make_msg_from_sendmms_request(from, xto, e ? e->msgId : NULL, + subject, data, ctype, reply_headers, msg_url, + base_url, type, + mmc, svc_name, expiryt, + mt_multipart, + rr_url != NULL, + dlr_url != NULL, + allow_adaptations ? + octstr_get_cstr(allow_adaptations) : "true", + mt_filter ? mt_filter->filter : NULL, + err); + if (m == NULL) + goto done; +#endif + if (otransid) /* always add transid */ http_header_add(hdrs, "X-Mbuni-TransactionID", octstr_get_cstr(otransid)); @@ -1348,7 +1079,9 @@ static void dispatch_sendmms_recv(List *rl) List *cgivar_ctypes = NULL; char *etype = NULL; - int res = 0, tparse = parse_cgivars(h->headers, h->body, &h->cgivars, &cgivar_ctypes); + int res = 0; + + parse_cgivars(h->headers, h->body, &h->cgivars, &cgivar_ctypes); username = http_cgi_variable(h->cgivars, "username"); password = http_cgi_variable(h->cgivars, "password"); @@ -1358,11 +1091,11 @@ static void dispatch_sendmms_recv(List *rl) octstr_strip_blanks(password); if ((u = auth_user(username, password)) != NULL && is_allowed_ip(sendmms_port.allow_ip, sendmms_port.deny_ip, h->ip)) { - Octstr *data, *external_data = NULL, *ctype = NULL, *mmc, *to, *from, *dlr_url; + Octstr *data, *ctype = NULL, *mmc, *to, *from, *dlr_url; Octstr *rr_url, *allow_adaptations, *subject = NULL; List *lto = NULL, *rh = http_create_empty_headers(); Octstr *rb = NULL, *base_url; - int i, n, skip_ctype = 0; + int i, n; Octstr *vasid = http_cgi_variable(h->cgivars, "vasid"); Octstr *service_code = http_cgi_variable(h->cgivars, "servicecode"); Octstr *mclass = http_cgi_variable(h->cgivars, "mclass"); @@ -1373,6 +1106,7 @@ static void dispatch_sendmms_recv(List *rl) Octstr *validity = http_cgi_variable(h->cgivars, "validityperiod"); Octstr *chargedparty = http_cgi_variable(h->cgivars, "charged-party"); Octstr *data_url = NULL; + Octstr *xs; dlr_url = http_cgi_variable(h->cgivars, "dlr-url"); rr_url = http_cgi_variable(h->cgivars, "rr-url"); @@ -1390,6 +1124,7 @@ static void dispatch_sendmms_recv(List *rl) base_url = octstr_duplicate(base_url); /* because we need to delete it below. */ /* Now get the data. */ +#if 0 if ((data = http_cgi_variable(h->cgivars, "text")) != NULL) { /* text. */ Octstr *charset = http_cgi_variable(h->cgivars, "charset"); @@ -1439,16 +1174,22 @@ static void dispatch_sendmms_recv(List *rl) } else rb = octstr_create("Missing content"); - +#else + get_content_from_sendmms_request(h->body, h->headers, h->cgivars, + cgivar_ctypes, + &rh, &ctype, &data, &rb, &base_url, &data_url); +#endif if ((to = http_cgi_variable(h->cgivars, "to")) == NULL) rb = octstr_create("Missing recipient!"); else lto = octstr_split_words(to); /* Build the fake reply headers. */ - if (ctype && !skip_ctype) + if ((xs = http_header_value(rh, octstr_imm("Content-Type"))) == NULL && ctype) http_header_add(rh, "Content-Type", octstr_get_cstr(ctype)); - + else + octstr_destroy(xs); + if ((from = http_cgi_variable(h->cgivars, "from")) != NULL) { from = octstr_duplicate(from); _mms_fixup_address(&from, NULL, NULL, 1); @@ -1541,7 +1282,7 @@ static void dispatch_sendmms_recv(List *rl) octstr_destroy(rb); octstr_destroy(base_url); octstr_destroy(data_url); - octstr_destroy(external_data); + octstr_destroy(data); /* get_content_from_sendmms now gives us a copy of it */ } else { http_send_reply(h->client, HTTP_UNAUTHORIZED, hh, octstr_imm("Authentication failed")); diff --git a/mbuni/mmsbox/mmsbox.h b/mbuni/mmsbox/mmsbox.h index 98d9e74..4836966 100644 --- a/mbuni/mmsbox/mmsbox.h +++ b/mbuni/mmsbox/mmsbox.h @@ -27,7 +27,6 @@ void mmsc_receive_func(MmscGrp *m); void mmsbox_outgoing_queue_runner(volatile sig_atomic_t *rstop); void mm4_receive_func(int *sock); void handle_mm1_mt_requests(MmscGrp *m); /* MM1 loop */ - /* Just a convenience, should go away in future! */ #define mmsbox_url_fetch_content mms_url_fetch_content #endif diff --git a/mbuni/mmsbox/mmsbox_cfg.c b/mbuni/mmsbox/mmsbox_cfg.c index ed6eea0..3a6128c 100644 --- a/mbuni/mmsbox/mmsbox_cfg.c +++ b/mbuni/mmsbox/mmsbox_cfg.c @@ -438,64 +438,10 @@ int mms_load_mmsbox_settings(struct mCfgImpFuncs *cfg_funcs, Octstr *init, gwlist_append(m->keywords, s); if ((s = mms_cfg_get(cfg, x, octstr_imm("http-post-parameters"))) != NULL) { - List *r = octstr_split(s, octstr_imm("&")); - int i, n; - m->params = gwlist_create(); + m->params = parse_service_url_params(s, m->name); if (m->type != TRANS_TYPE_POST_URL) mms_warning(0, "mmsbox", NULL,"Service [%s] specifies HTTP Post parameters " - "without specifying post-url type/url!", octstr_get_cstr(m->name)); - for (i = 0, n = gwlist_len(r); i < n; i++) { - Octstr *y = gwlist_get(r, i); - int ii = octstr_search_char(y, '=', 0); - if (ii < 0) - ii = octstr_len(y); - - if (ii > 0) { - MmsServiceUrlParam *p = gw_malloc(sizeof *p); - int ch; - p->name = octstr_copy(y, 0, ii); - p->value = NULL; - - if (octstr_get_char(y, ii+1) == '%') { - switch(ch = octstr_get_char(y, ii+2)) { - case 'a': - p->type = AUDIO_PART; break; - case 'b': - p->type = WHOLE_BINARY; break; - case 'i': - p->type = IMAGE_PART; break; - case 'v': - p->type = VIDEO_PART; break; - case 't': - p->type = TEXT_PART; break; - case 's': - p->type = SMIL_PART; break; - case 'o': - p->type = OTHER_PART; break; - case 'z': - p->type = ANY_PART; break; - case 'k': - p->type = KEYWORD_PART; break; - case '%': - p->type = NO_PART; break; - default: - mms_warning(0, "mmsbox", NULL, "Unknown conversion character %c " - "in http-post-parameters. Service [%s]!", - ch, octstr_get_cstr(m->name)); - p->type = NO_PART; - break; - } - p->value = octstr_copy(y, ii+3, octstr_len(y)); - } else { /* No conversion spec. */ - p->type = NO_PART; - p->value = octstr_copy(y, ii+1, octstr_len(y)); - } - gwlist_append(m->params, p); - } else - mms_warning(0, "mmsbox", NULL, "Missing http-post-parameter name? Service [%s]!", - octstr_get_cstr(m->name)); - } - gwlist_destroy(r, (gwlist_item_destructor_t *)octstr_destroy); + "without specifying post-url type/url!", octstr_get_cstr(m->name)); octstr_destroy(s); } else m->params = NULL; @@ -1365,3 +1311,255 @@ static void free_mmsc_struct (MmscGrp *m) gw_free(m); } + +List *parse_service_url_params(Octstr *input, Octstr *id) +{ + List *l = gwlist_create(); + List *r = octstr_split(input, octstr_imm("&")); + int i; + + for (i = 0; i < gwlist_len(r); i++) { + Octstr *y = gwlist_get(r, i); + int ii = octstr_search_char(y, '=', 0); + if (ii < 0) + ii = octstr_len(y); + + if (ii > 0) { + MmsServiceUrlParam *p = gw_malloc(sizeof *p); + int ch; + p->name = octstr_copy(y, 0, ii); + p->value = NULL; + + if (octstr_get_char(y, ii+1) == '%') { + switch(ch = octstr_get_char(y, ii+2)) { + case 'a': + p->type = AUDIO_PART; break; + case 'b': + p->type = WHOLE_BINARY; break; + case 'i': + p->type = IMAGE_PART; break; + case 'v': + p->type = VIDEO_PART; break; + case 't': + p->type = TEXT_PART; break; + case 's': + p->type = SMIL_PART; break; + case 'o': + p->type = OTHER_PART; break; + case 'z': + p->type = ANY_PART; break; + case 'k': + p->type = KEYWORD_PART; break; + case 'r': + p->type = RCPT_PART; break; + case 'f': + p->type = FROM_PART; break; + case 'S': + p->type = SUBJECT_PART; break; + case 'm': + p->type = MMSCID_PART; break; + case 'T': + p->type = MSGTYPE_PART; break; + case 'I': + p->type = MSGID_PART; break; + case '%': + p->type = NO_PART; break; + default: + mms_warning(0, "mmsbox", id, "Unknown conversion character %c " + "in http-post-parameters.", + ch); + p->type = NO_PART; + break; + } + p->value = octstr_copy(y, ii+3, octstr_len(y)); + } else { /* No conversion spec. */ + p->type = NO_PART; + p->value = octstr_copy(y, ii+1, octstr_len(y)); + } + gwlist_append(l, p); + } else + mms_warning(0, "mmsbox", id, "Missing http-post-parameter name?!"); + } + + gwlist_destroy(r, (void *)octstr_destroy); + return l; +} + +void add_all_matching_parts_real(MIMEEntity *plist, MmsServiceUrlParam *pm, + Octstr *keyword, + MIMEEntity *me, + MmsMsg *msg, int lev, int count, + Octstr *from, List *lto, char *subject, + char *mmsc_id, int mtype, Octstr *msgid) +{ + int i, n; + List *headers = NULL; + Octstr *data = NULL, *ctype = NULL, *xctype = NULL, *params = NULL; + Octstr *s; + + headers = mime_entity_headers(me); + if (lev == 0) { + if (pm->type == WHOLE_BINARY) { + data = mms_tobinary(msg); + ctype = octstr_create("application/vnd.wap.mms-message"); /* we drop through ? */ + } else if (pm->type == NO_PART) { + data = octstr_create(""); /* We'll add value below. */ + goto done; + } else if (pm->type == KEYWORD_PART) { + data = keyword ? octstr_duplicate(keyword) : octstr_create(""); + ctype = octstr_create("text/plain"); + goto done; + } else if (pm->type == RCPT_PART && lto) { + LINEARISE_STR_LIST(data,lto," "); + ctype = octstr_create("text/plain"); + goto done; + } else if (pm->type == FROM_PART && from) { + data = octstr_duplicate(from); + ctype = octstr_create("text/plain"); + goto done; + } else if (pm->type == SUBJECT_PART && subject) { + data = octstr_format("%.256s", subject); + ctype = octstr_create("text/plain"); + goto done; + } else if (pm->type == MMSCID_PART && mmsc_id) { + data = octstr_format("%.256s", mmsc_id); + ctype = octstr_create("text/plain"); + goto done; + } else if (pm->type == MSGTYPE_PART && mtype >= 0) { + char *s = (void *)mms_message_type_to_cstr(mtype); + data = octstr_create(s ? s : "n/a"); + ctype = octstr_create("text/plain"); + goto done; + } else if (pm->type == MSGID_PART && msgid) { + data = octstr_duplicate(msgid); + ctype = octstr_create("text/plain"); + goto done; + } + } + + if ((n = mime_entity_num_parts(me)) > 0) { /* Recurse over multi-parts. */ + for (i = 0; i < n; i++) { + MIMEEntity *x = mime_entity_get_part(me,i); + add_all_matching_parts(plist, pm, NULL, x, msg, lev+1,i); + mime_entity_destroy(x); + } + goto done; + } + + get_content_type(headers, &xctype, ¶ms); + +#define BEGINSWITH(s, prefix) (octstr_case_search(s, octstr_imm(prefix),0) == 0) +#define TYPE_MATCH(typ, prefix) ((pm->type) == (typ) && \ + BEGINSWITH(xctype, prefix)) + if (xctype) + if (TYPE_MATCH(IMAGE_PART,"image/") || + TYPE_MATCH(AUDIO_PART,"audio/") || + TYPE_MATCH(VIDEO_PART,"video/") || + TYPE_MATCH(TEXT_PART,"text/") || + TYPE_MATCH(SMIL_PART,"application/smil") || + pm->type == ANY_PART || /* Skip top-level for 'any' parts. */ + (pm->type == OTHER_PART && + (!BEGINSWITH(xctype, "text/") && + !BEGINSWITH(xctype, "video/") && + !BEGINSWITH(xctype, "image/") && + !BEGINSWITH(xctype, "application/smil")))) { + + ctype = http_header_value(headers, octstr_imm("Content-Type")); + data = mime_entity_body(me); + } + +done: + if (data) { + MIMEEntity *p = mime_entity_create(); + Octstr *cd = octstr_format("form-data; name=\"%S\"", pm->name); + List *xh; + + if (ctype && pm->type != KEYWORD_PART) { + /* If Content-Location header or name (content-type) parameter given, pass it as filename. */ + Octstr *c = NULL, *q = NULL; + Octstr *cloc = http_header_value(headers, + octstr_imm("Content-Location")); + split_header_value(ctype, &c, &q); + + if (q || cloc) { + List *ph = q ? get_value_parameters(q) : http_create_empty_headers(); + Octstr *v = cloc ? cloc : http_header_value(ph, octstr_imm("name")); + + if (!v) /* make up a fake name if none is given */ + v = octstr_format("part-%d-%d", lev, count); + + octstr_format_append(cd, "; filename=\"%S\"", v); + http_header_remove_all(ph, "name"); + + if (v != cloc) + octstr_destroy(v); + octstr_destroy(ctype); + + v = make_value_parameters(ph); + if (v && octstr_len(v) > 0) + ctype = octstr_format("%S; %S", c, v); + else + ctype = octstr_duplicate(c); + + octstr_destroy(v); + + http_destroy_headers(ph); + + octstr_destroy(q); + } + + + octstr_destroy(c); + octstr_destroy(cloc); + } + + xh = http_create_empty_headers(); + http_header_add(xh, "Content-Disposition", octstr_get_cstr(cd)); + if (ctype) /* This header must come after the above it seems. */ + http_header_add(xh, "Content-Type", octstr_get_cstr(ctype)); + + mime_replace_headers(p, xh); + http_destroy_headers(xh); + + s = octstr_duplicate(data); /* data for the parameter */ + if (pm->value) /* add value part as needed. */ + octstr_append(s, pm->value); + mime_entity_set_body(p, s); + octstr_destroy(s); +#if 0 + base64_mimeparts(p); +#endif + mime_entity_add_part(plist, p); /* add it to list so far. */ + mime_entity_destroy(p); + + octstr_destroy(cd); + } + + + octstr_destroy(xctype); + octstr_destroy(params); + octstr_destroy(ctype); + octstr_destroy(data); + + http_destroy_headers(headers); +} + +MIMEEntity *mmsbox_add_service_url_params(List *params, + Octstr *from, List *lto, char *subject, + char *mmsc_id, int mtype, Octstr *msgid, + MmsMsg *m) +{ + int i; + MIMEEntity *x = mime_entity_create(); + MIMEEntity *me = mms_tomime(m, 0); + Octstr *keyword = get_keyword_from_mime(me); + for (i = 0; i