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 default-message-expiry = 360000
queue-run-interval = 0.1 queue-run-interval = 0.1
send-attempt-back-off = 300 send-attempt-back-off = 300
sendmms-port = 10001
group = mmsc group = mmsc
id = local id = local
@ -37,4 +38,8 @@ get-url = http://localhost/~bagyenda/images/apache_pb.gif
accept-x-mbuni-headers = true accept-x-mbuni-headers = true
keyword = thixs 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>
<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 Send MMS port on the VAS Gateway hosts. The interface expects and
processes the following CGI paramerters: processes the following CGI paramerters:
</p> </p>
@ -2339,6 +2340,30 @@ faked-sender = 100<br>
</td> </td>
</tr> </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> <tr>
<td valign=top > <td valign=top >
<tt>base-url</tt> <tt>base-url</tt>
@ -2365,6 +2390,12 @@ faked-sender = 100<br>
</p> </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> <p>

View File

@ -939,3 +939,120 @@ void escape_shell_chars(Octstr *str)
} }
octstr_destroy(tmp); 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. */ /* escape (backlash) special shell characters. */
void escape_shell_chars(Octstr *str); 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 MAXQTRIES 100
#define BACKOFF_FACTOR 5*60 /* In seconds */ #define BACKOFF_FACTOR 5*60 /* In seconds */
#define QUEUERUN_INTERVAL 1*60 /* 1 minutes. */ #define QUEUERUN_INTERVAL 1*60 /* 1 minutes. */

View File

@ -20,7 +20,7 @@
#include "mms_uaprof.h" #include "mms_uaprof.h"
#include "mmsbox.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; int rstop = 0;
static void quit_now(int notused) static void quit_now(int notused)
@ -1101,10 +1101,16 @@ static void sendmms_func(void *unused)
&ip, &url, &h, &body, &cgivars)) != NULL) { &ip, &url, &h, &body, &cgivars)) != NULL) {
SendMmsUser *u = NULL; SendMmsUser *u = NULL;
List *hh = http_create_empty_headers(); List *hh = http_create_empty_headers();
Octstr *username = http_cgi_variable(cgivars, "username"); Octstr *username;
Octstr *password = http_cgi_variable(cgivars, "password"); Octstr *password;
Octstr *err = NULL; 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 && if ((u = auth_user(username, password)) != NULL &&
is_allowed_ip(sendmms_port.allow_ip, sendmms_port.deny_ip, ip)) { is_allowed_ip(sendmms_port.allow_ip, sendmms_port.deny_ip, ip)) {
Octstr *data, *ctype = NULL, *mmc, *to, *from, *dlr_url; 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); octstr_format_append(ctype, "; charset=%S", charset);
} else if ((data = http_cgi_variable(cgivars, "smil")) != NULL) /* smil. */ } else if ((data = http_cgi_variable(cgivars, "smil")) != NULL) /* smil. */
ctype = octstr_imm("application/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); data = octstr_duplicate(body);
ctype = http_header_value(h, octstr_imm("Content-Type")); ctype = http_header_value(h, octstr_imm("Content-Type"));
} else } else
@ -1214,8 +1234,13 @@ static void sendmms_func(void *unused)
octstr_destroy(body); octstr_destroy(body);
if (url) if (url)
octstr_destroy(url); octstr_destroy(url);
if (cgivars) if (cgivars)
http_destroy_cgiargs(cgivars); http_destroy_cgiargs(cgivars);
if (cgivar_ctypes)
http_destroy_cgiargs(cgivar_ctypes);
if (h) if (h)
http_destroy_headers(h); http_destroy_headers(h);
if (hh) if (hh)