1
0
Fork 0

- Allow Send-MMS port to support HTTP POST from HTML-style forms, including enctype multipart/form-data

This commit is contained in:
bagyenda 2006-06-20 13:32:54 +00:00
parent 4d625f2375
commit 7fd8045dd4
5 changed files with 193 additions and 5 deletions

View File

@ -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

View File

@ -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>

View File

@ -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;
}

View File

@ -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. */

View File

@ -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)