You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by hu...@apache.org on 2012/12/11 18:09:41 UTC
svn commit: r1420286 - /httpd/httpd/trunk/modules/lua/lua_request.c
Author: humbedooh
Date: Tue Dec 11 17:09:40 2012
New Revision: 1420286
URL: http://svn.apache.org/viewvc?rev=1420286&view=rev
Log:
lua_request.c: Add support for parsing multipart form data via r:parsebody. This is a bit RFC-centric, suggestions are most welcome.
Modified:
httpd/httpd/trunk/modules/lua/lua_request.c
Modified: httpd/httpd/trunk/modules/lua/lua_request.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/lua/lua_request.c?rev=1420286&r1=1420285&r2=1420286&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/lua/lua_request.c (original)
+++ httpd/httpd/trunk/modules/lua/lua_request.c Tue Dec 11 17:09:40 2012
@@ -21,6 +21,7 @@
#include "scoreboard.h"
APLOG_USE_MODULE(lua);
+#define POST_MAX_VARS 500
typedef char *(*req_field_string_f) (request_rec * r);
typedef int (*req_field_int_f) (request_rec * r);
@@ -151,6 +152,46 @@ static int req_aprtable2luatable_cb(void
return 1;
}
+
+/*
+ =======================================================================================================================
+ lua_read_body(request_rec *r, const char **rbuf, apr_off_t *size): Reads any additional form data sent in POST/PUT
+ requests. Used for multipart POST data.
+ =======================================================================================================================
+ */
+static int lua_read_body(request_rec *r, const char **rbuf, apr_off_t *size)
+{
+ int rc = OK;
+
+ if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) {
+ return (rc);
+ }
+ if (ap_should_client_block(r)) {
+
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+ char argsbuffer[HUGE_STRING_LEN];
+ apr_off_t rsize, len_read, rpos = 0;
+ apr_off_t length = r->remaining;
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ *rbuf = (const char *) apr_pcalloc(r->pool, (apr_size_t) (length + 1));
+ *size = length;
+ while ((len_read = ap_get_client_block(r, argsbuffer, sizeof(argsbuffer))) > 0) {
+ if ((rpos + len_read) > length) {
+ rsize = length - rpos;
+ }
+ else {
+ rsize = len_read;
+ }
+
+ memcpy((char *) *rbuf + rpos, argsbuffer, (size_t) rsize);
+ rpos += rsize;
+ }
+ }
+
+ return (rc);
+}
+
/* r:parseargs() returning a lua table */
static int req_parseargs(lua_State *L)
{
@@ -163,7 +204,7 @@ static int req_parseargs(lua_State *L)
return 2; /* [table<string, string>, table<string, array<string>>] */
}
-/* r:parsebody() returning a lua table */
+/* r:parsebody(): Parses regular (url-enocded) or multipart POST data and returns two tables*/
static int req_parsebody(lua_State *L)
{
apr_array_header_t *pairs;
@@ -171,21 +212,64 @@ static int req_parsebody(lua_State *L)
int res;
apr_size_t size;
apr_size_t max_post_size;
- char *buffer;
+ char *multipart;
+ const char *contentType;
request_rec *r = ap_lua_check_request_rec(L, 1);
max_post_size = (apr_size_t) luaL_optint(L, 2, MAX_STRING_LEN);
+ multipart = apr_pcalloc(r->pool, 256);
+ contentType = apr_table_get(r->headers_in, "Content-Type");
lua_newtable(L);
- lua_newtable(L); /* [table, table] */
- res = ap_parse_form_data(r, NULL, &pairs, -1, max_post_size);
- if (res == OK) {
- while(pairs && !apr_is_empty_array(pairs)) {
- ap_form_pair_t *pair = (ap_form_pair_t *) apr_array_pop(pairs);
- apr_brigade_length(pair->value, 1, &len);
- size = (apr_size_t) len;
- buffer = apr_palloc(r->pool, size + 1);
- apr_brigade_flatten(pair->value, buffer, &size);
- buffer[len] = 0;
- req_aprtable2luatable_cb(L, pair->name, buffer);
+ lua_newtable(L); /* [table, table] */
+ if (contentType != NULL && (sscanf(contentType, "multipart/form-data; boundary=%250c", multipart) == 1)) {
+ char *buffer, *key, *filename;
+ char *start = 0, *end = 0, *crlf = 0;
+ const char *data;
+ int i, z;
+ size_t vlen = 0;
+ size_t len = 0;
+ if (lua_read_body(r, &data, &size) != OK) {
+ return 2;
+ }
+ len = strlen(multipart);
+ i = 0;
+ for
+ (
+ start = strstr((char *) data, multipart);
+ start != start + size;
+ start = end
+ ) {
+ i++;
+ if (i == POST_MAX_VARS) break;
+ end = strstr((char *) (start + 1), multipart);
+ if (!end) end = start + size;
+ crlf = strstr((char *) start, "\r\n\r\n");
+ if (!crlf) break;
+ key = (char *) apr_pcalloc(r->pool, 256);
+ filename = (char *) apr_pcalloc(r->pool, 256);
+ buffer = (char *) apr_palloc(r->pool, end - crlf);
+ vlen = end - crlf - 8;
+ memcpy(buffer, crlf + 4, vlen);
+ sscanf(start + len + 2,
+ "Content-Disposition: form-data; name=\"%255[^\"]\"; filename=\"%255[^\"]\"",
+ key, filename);
+ if (strlen(key)) {
+ req_aprtable2luatable_cb(L, key, buffer);
+ }
+ }
+ }
+ else {
+ char *buffer;
+ res = ap_parse_form_data(r, NULL, &pairs, -1, max_post_size);
+ if (res == OK) {
+ while(pairs && !apr_is_empty_array(pairs)) {
+ ap_form_pair_t *pair = (ap_form_pair_t *) apr_array_pop(pairs);
+ apr_brigade_length(pair->value, 1, &len);
+ size = (apr_size_t) len;
+ buffer = apr_palloc(r->pool, size + 1);
+ apr_brigade_flatten(pair->value, buffer, &size);
+ buffer[len] = 0;
+ req_aprtable2luatable_cb(L, pair->name, buffer);
+ }
}
}
return 2; /* [table<string, string>, table<string, array<string>>] */