- Allow Send-MMS port to support HTTP POST from HTML-style forms, including enctype multipart/form-data
This commit is contained in:
parent
4d625f2375
commit
7fd8045dd4
|
@ -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
|
||||
|
||||
|
|
|
@ -2209,7 +2209,8 @@ faked-sender = 100<br>
|
|||
</p>
|
||||
|
||||
<p>
|
||||
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
|
||||
<i>x-www-form-urlencoded</i> and <i>multipart/form-data</i>) requests to the
|
||||
Send MMS port on the VAS Gateway hosts. The interface expects and
|
||||
processes the following CGI paramerters:
|
||||
</p>
|
||||
|
@ -2339,6 +2340,30 @@ faked-sender = 100<br>
|
|||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign=top >
|
||||
<tt>content</tt>
|
||||
</td>
|
||||
<td valign=top >
|
||||
If provided, specifies the arbitrary content for the MM. The Content type of
|
||||
the content is determined either by the <tt>content_type</tt> CGI
|
||||
variable (see below), or if <i>enctype=multipart/form-data</i> is
|
||||
used in the HTTP POST request, then the content type associated with
|
||||
this variable data is used.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign=top >
|
||||
<tt>content_type</tt>
|
||||
</td>
|
||||
<td valign=top >
|
||||
If the <tt>content</tt> variable is provided, this variable
|
||||
specifies the content type of the <tt>content</tt>. The default, if
|
||||
no content type is provided is <i>application/octet-stream</i>.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign=top >
|
||||
<tt>base-url</tt>
|
||||
|
@ -2365,6 +2390,12 @@ faked-sender = 100<br>
|
|||
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Note: </b> You should specify only one
|
||||
of <tt>text</tt>, <tt>smil</tt> or <tt>content</tt>, as only one of
|
||||
them makes sense at any time. specifying more than one causes others
|
||||
to be ignored.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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,9 +1101,15 @@ 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)) {
|
||||
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue