Added mg_parse_multipart

This commit is contained in:
Sergey Lyubka 2014-01-13 16:29:12 +00:00
parent 56f128514e
commit 73ed83c5e3
3 changed files with 99 additions and 8 deletions

View File

@ -453,6 +453,41 @@ static const char *test_server(void) {
return NULL;
}
#define DISP "Content-Disposition: form/data; "
#define CRLF "\r\n"
#define BOUNDARY "--xyz"
static const char *test_parse_multipart(void) {
char a[100], b[100];
const char *p;
static const char f1[] = BOUNDARY CRLF DISP "name=f1" CRLF CRLF
"some_content" CRLF BOUNDARY CRLF
BOUNDARY CRLF DISP "name=f2; filename=\"foo bar.txt\"" CRLF CRLF
"another_content" CRLF BOUNDARY CRLF
"--" CRLF;
int n, n2, len, f1_len = sizeof(f1) - 1;
ASSERT(mg_parse_multipart("", 0, a, sizeof(a), b, sizeof(b), &p, &len) == 0);
ASSERT(mg_parse_multipart("a", 1, a, sizeof(a), b, sizeof(b), &p, &len) == 0);
ASSERT((n = mg_parse_multipart(f1, f1_len, a, sizeof(a),
b, sizeof(b), &p, &len)) > 0);
ASSERT(len == 12);
ASSERT(memcmp(p, "some_content", len) == 0);
ASSERT(strcmp(a, "f1") == 0);
ASSERT(b[0] == '\0');
ASSERT((n2 = mg_parse_multipart(f1 + n, f1_len - n, a, sizeof(a),
b, sizeof(b), &p, &len)) > 0);
ASSERT(len == 15);
ASSERT(memcmp(p, "another_content", len) == 0);
ASSERT(strcmp(a, "f2") == 0);
ASSERT(strcmp(b, "foo bar.txt") == 0);
ASSERT((n2 = mg_parse_multipart(f1 + n + n2, f1_len - (n + n2), a, sizeof(a),
b, sizeof(b), &p, &len)) == 0);
return NULL;
}
static const char *run_all_tests(void) {
RUN_TEST(test_should_keep_alive);
RUN_TEST(test_match_prefix);
@ -466,6 +501,7 @@ static const char *run_all_tests(void) {
RUN_TEST(test_get_var);
RUN_TEST(test_next_option);
RUN_TEST(test_server);
RUN_TEST(test_parse_multipart);
return NULL;
}

View File

@ -2979,24 +2979,24 @@ static int is_dav_mutation(const struct connection *conn) {
}
#endif // NO_AUTH
int mg_parse_header(const char *str, const char *var_name, char *buf,
size_t buf_size) {
int parse_header(const char *str, int str_len, const char *var_name, char *buf,
size_t buf_size) {
int ch = ' ', len = 0, n = strlen(var_name);
const char *p, *s = NULL;
const char *p, *end = str + str_len, *s = NULL;
if (buf != NULL) buf[0] = '\0';
// Find where variable starts
while (str != NULL && (s = strstr(str, var_name)) != NULL &&
((s > str && s[-1] != ' ') || s[n] != '=')) {
str = s + n;
for (s = str; s != NULL && &s[n] < end; s++) {
if ((s == str || s[-1] == ' ') && s[n] == '=' &&
!memcmp(s, var_name, n)) break;
}
if (s != NULL && s[n + 1] != '\0') {
if (s != NULL && &s[n + 1] < end) {
s += n + 1;
if (*s == '"' || *s == '\'') ch = *s++;
p = s;
while (p[0] != '\0' && p[0] != ch && len < (int) buf_size) {
while (p < end && p[0] != ch && len < (int) buf_size) {
if (p[0] == '\\' && p[1] == ch) p++;
buf[len++] = *p++;
}
@ -3004,6 +3004,7 @@ int mg_parse_header(const char *str, const char *var_name, char *buf,
len = 0;
} else {
if (len > 0 && s[len - 1] == ',') len--;
if (len > 0 && s[len - 1] == ';') len--;
buf[len] = '\0';
}
}
@ -3011,6 +3012,11 @@ int mg_parse_header(const char *str, const char *var_name, char *buf,
return len;
}
int mg_parse_header(const char *str, const char *var_name, char *buf,
size_t buf_size) {
return parse_header(str, strlen(str), var_name, buf, buf_size);
}
#ifdef USE_LUA
#include "lua_5.2.1.h"
@ -3769,6 +3775,51 @@ int mg_get_var(const struct mg_connection *conn, const char *name,
return len;
}
static int get_line_len(const char *buf, int buf_len) {
int len = 0;
while (len < buf_len && buf[len] != '\n') len++;
return buf[len] == '\n' ? len + 1: -1;
}
int mg_parse_multipart(const char *buf, int buf_len,
char *var_name, int var_name_len,
char *file_name, int file_name_len,
const char **data, int *data_len) {
static const char cd[] = "Content-Disposition: ";
//struct mg_connection c;
int hl, bl, n, ll, pos, cdl = sizeof(cd) - 1;
//char *p;
if (buf == NULL || buf_len <= 0) return 0;
if ((hl = get_request_len(buf, buf_len)) <= 0) return 0;
if (buf[0] != '-' || buf[1] != '-' || buf[2] == '\n') return 0;
// Get boundary length
bl = get_line_len(buf, buf_len);
// Loop through headers, fetch variable name and file name
var_name[0] = file_name[0] = '\0';
for (n = bl; (ll = get_line_len(buf + n, hl - n)) > 0; n += ll) {
if (mg_strncasecmp(cd, buf + n, cdl) == 0) {
parse_header(buf + n + cdl, ll - (cdl + 2), "name",
var_name, var_name_len);
parse_header(buf + n + cdl, ll - (cdl + 2), "filename",
file_name, file_name_len);
}
}
// Scan body, search for terminating boundary
for (pos = hl; pos + (bl - 2) < buf_len; pos++) {
if (buf[pos] == '-' && !memcmp(buf, &buf[pos], bl - 2)) {
if (data_len != NULL) *data_len = (pos - 2) - hl;
if (data != NULL) *data = buf + hl;
return pos;
}
}
return 0;
}
const char **mg_get_valid_option_names(void) {
return static_config_options;
}

View File

@ -92,6 +92,10 @@ const char *mg_get_mime_type(const char *file_name);
int mg_get_var(const struct mg_connection *conn, const char *var_name,
char *buf, size_t buf_len);
int mg_parse_header(const char *hdr, const char *var_name, char *buf, size_t);
int mg_parse_multipart(const char *buf, int buf_len,
char *var_name, int var_name_len,
char *file_name, int file_name_len,
const char **data, int *data_len);
// Utility functions
void *mg_start_thread(void *(*func)(void *), void *param);