diff --git a/mbuni/doc/examples/mmsbox.conf b/mbuni/doc/examples/mmsbox.conf index 1f680bb..0ad3726 100644 --- a/mbuni/doc/examples/mmsbox.conf +++ b/mbuni/doc/examples/mmsbox.conf @@ -10,6 +10,7 @@ maximum-send-attempts = 50 default-message-expiry = 360000 queue-run-interval = 0.1 send-attempt-back-off = 300 +sendmms-port = 10001 group = mmsc id = local @@ -37,4 +38,8 @@ get-url = http://localhost/~bagyenda/images/apache_pb.gif accept-x-mbuni-headers = true keyword = thixs +group = send-mms-user +username = tester +password = foobar +faked-sender = 100 diff --git a/mbuni/doc/userguide.shtml b/mbuni/doc/userguide.shtml index ad02968..f2cf301 100644 --- a/mbuni/doc/userguide.shtml +++ b/mbuni/doc/userguide.shtml @@ -2209,7 +2209,8 @@ faked-sender = 100

- The Send MMS service can be invoked using HTTP GET or POST requests to the + The Send MMS service can be invoked using HTTP GET or POST (both + x-www-form-urlencoded and multipart/form-data) requests to the Send MMS port on the VAS Gateway hosts. The interface expects and processes the following CGI paramerters:

@@ -2339,6 +2340,30 @@ faked-sender = 100
+ + + content + + + If provided, specifies the arbitrary content for the MM. The Content type of + the content is determined either by the content_type CGI + variable (see below), or if enctype=multipart/form-data is + used in the HTTP POST request, then the content type associated with + this variable data is used. + + + + + + content_type + + + If the content variable is provided, this variable + specifies the content type of the content. The default, if + no content type is provided is application/octet-stream. + + + base-url @@ -2365,6 +2390,12 @@ faked-sender = 100

+

+ Note: You should specify only one + of text, smil or content, as only one of + them makes sense at any time. specifying more than one causes others + to be ignored. +

diff --git a/mbuni/mmlib/mms_util.c b/mbuni/mmlib/mms_util.c index 2604834..55c9a97 100644 --- a/mbuni/mmlib/mms_util.c +++ b/mbuni/mmlib/mms_util.c @@ -939,3 +939,120 @@ void escape_shell_chars(Octstr *str) } octstr_destroy(tmp); } + +int parse_cgivars(List *request_headers, Octstr *request_body, + List **cgivars, List **cgivar_ctypes) +{ + Octstr *ctype = NULL, *charset = NULL; + int ret = 0; + + if (request_body == NULL || + octstr_len(request_body) == 0 || cgivars == NULL) + return 0; /* Nothing to do, this is a normal GET request. */ + + http_header_get_content_type(request_headers, &ctype, &charset); + + if (*cgivars == NULL) + *cgivars = list_create(); + + if (*cgivar_ctypes == NULL) + *cgivar_ctypes = list_create(); + + if (!ctype) { + warning(0, "MMS: Parse CGI Vars: Missing Content Type!"); + ret = -1; + goto done; + } + + if (octstr_case_compare(ctype, octstr_imm("application/x-www-form-urlencoded")) == 0) { + /* This is a normal POST form */ + List *l = octstr_split(request_body, octstr_imm("&")); + Octstr *v; + + while ((v = list_extract_first(l)) != NULL) { + List *r = octstr_split(v, octstr_imm("=")); + + if (list_len(r) == 0) + warning(0, "MMS: Parse CGI Vars: Missing CGI var name/value in POST data: %s", + octstr_get_cstr(request_body)); + else { + HTTPCGIVar *x = gw_malloc(sizeof *x); + x->name = list_extract_first(r); + x->value = list_extract_first(r); + if (!x->value) + x->value = octstr_imm(""); + + octstr_strip_blanks(x->name); + octstr_strip_blanks(x->value); + + octstr_url_decode(x->name); + octstr_url_decode(x->value); + + list_append(*cgivars, x); + } + octstr_destroy(v); + list_destroy(r, octstr_destroy_item); + } + list_destroy(l, NULL); + } else if (octstr_case_compare(ctype, octstr_imm("multipart/form-data")) == 0) { + /* multi-part form data */ + MIMEEntity *m = mime_http_to_entity(request_headers, request_body); + int i, n; + + if (!m) { + warning(0, "MMS: Parse CGI Vars: Failed to parse multipart/form-data body: %s", + octstr_get_cstr(request_body)); + ret = -1; + goto done; + } + /* Go through body parts, pick out what we need. */ + for (i = 0, n = list_len(m->multiparts); i < n; i++) { + MIMEEntity *mp = list_get(m->multiparts, i); + Octstr *cd = http_header_value(mp->headers, octstr_imm("Content-Disposition")); + Octstr *name = http_get_header_parameter(cd, octstr_imm("name")); + Octstr *ct = NULL, *ch = NULL; + + http_header_get_content_type(mp->headers, &ct, &ch); + + if (name) { + HTTPCGIVar *x = gw_malloc(sizeof *x); + + /* Strip quotes */ + if (octstr_get_char(name, 0) == '"') { + octstr_delete(name, 0, 1); + octstr_truncate(name, octstr_len(name) - 1); + } + + x->name = octstr_duplicate(name); + x->value = octstr_duplicate(mp->body); + + list_append(*cgivars, x); + + if (ct) { /* If the content type is set, use it. */ + x = gw_malloc(sizeof *x); + x->name = octstr_duplicate(name); + x->value = octstr_duplicate(ct); + + list_append(*cgivar_ctypes, x); + } + octstr_destroy(name); + } + if (ch) + octstr_destroy(ch); + if (ct) + octstr_destroy(ct); + + if (cd) + octstr_destroy(cd); + } + mime_entity_destroy(m); + + } else /* else it is nothing that we know about, so simply go away... */ + ret = -1; +done: + if (ctype) + octstr_destroy(ctype); + if (charset) + octstr_destroy(charset); + return ret; +} diff --git a/mbuni/mmlib/mms_util.h b/mbuni/mmlib/mms_util.h index 9a14539..2582389 100644 --- a/mbuni/mmlib/mms_util.h +++ b/mbuni/mmlib/mms_util.h @@ -140,6 +140,16 @@ int is_allowed_host(Octstr *host, Octstr *host_list); /* escape (backlash) special shell characters. */ void escape_shell_chars(Octstr *str); +/* Parse CGI variables out of a HTTP POST request. + * This function understands both standard POST and enctype multipart/form-data + * For the latter it puts the content type of each of the variables found into + * cgivars_ctypes (as HTTPCGIVars where name is the field name and value is the content type) + * cgivars argument is the cgivars as passed to us by http_accept_request. For GET + * HTTP requests this is returned unchanged, otherwise it is augmented with the + * variables found. + */ +int parse_cgivars(List *request_headers, Octstr *request_body, + List **cgivars, List **cgivar_ctypes); #define MAXQTRIES 100 #define BACKOFF_FACTOR 5*60 /* In seconds */ #define QUEUERUN_INTERVAL 1*60 /* 1 minutes. */ diff --git a/mbuni/mmsbox/mmsbox.c b/mbuni/mmsbox/mmsbox.c index 510cc40..1f16c50 100644 --- a/mbuni/mmsbox/mmsbox.c +++ b/mbuni/mmsbox/mmsbox.c @@ -20,7 +20,7 @@ #include "mms_uaprof.h" #include "mmsbox.h" -/* XXX warning, do not octstr_destroy cgi variables. They are destroyed by the http module! */ +/* XXX warning, do not octstr_destroy strings in HTTPCGIVar struct. They are destroyed by the http module! */ int rstop = 0; static void quit_now(int notused) @@ -1101,10 +1101,16 @@ static void sendmms_func(void *unused) &ip, &url, &h, &body, &cgivars)) != NULL) { SendMmsUser *u = NULL; List *hh = http_create_empty_headers(); - Octstr *username = http_cgi_variable(cgivars, "username"); - Octstr *password = http_cgi_variable(cgivars, "password"); + Octstr *username; + Octstr *password; Octstr *err = NULL; + List *cgivar_ctypes = NULL; + int tparse = parse_cgivars(h, body, &cgivars, &cgivar_ctypes); + + username = http_cgi_variable(cgivars, "username"); + password = http_cgi_variable(cgivars, "password"); + if ((u = auth_user(username, password)) != NULL && is_allowed_ip(sendmms_port.allow_ip, sendmms_port.deny_ip, ip)) { Octstr *data, *ctype = NULL, *mmc, *to, *from, *dlr_url; @@ -1125,7 +1131,21 @@ static void sendmms_func(void *unused) octstr_format_append(ctype, "; charset=%S", charset); } else if ((data = http_cgi_variable(cgivars, "smil")) != NULL) /* smil. */ ctype = octstr_imm("application/smil"); - else if (body) { /* if all above fails, use send-mms msg body if any. */ + else if ((data = http_cgi_variable(cgivars, "content")) != NULL) { /* any content. */ + Octstr *_xctype = NULL; /* ... because cgi var stuff is destroyed elsewhere, we must dup it !! */ + + /* 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 if (body && tparse != 0) { /* if all above fails, + use send-mms msg body if any. */ data = octstr_duplicate(body); ctype = http_header_value(h, octstr_imm("Content-Type")); } else @@ -1214,8 +1234,13 @@ static void sendmms_func(void *unused) octstr_destroy(body); if (url) octstr_destroy(url); + if (cgivars) http_destroy_cgiargs(cgivars); + + if (cgivar_ctypes) + http_destroy_cgiargs(cgivar_ctypes); + if (h) http_destroy_headers(h); if (hh)