mirror of
https://github.com/cesanta/mongoose.git
synced 2025-06-12 12:42:50 +08:00
Added mg_parse_multipart
This commit is contained in:
parent
56f128514e
commit
73ed83c5e3
@ -453,6 +453,41 @@ static const char *test_server(void) {
|
|||||||
return NULL;
|
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) {
|
static const char *run_all_tests(void) {
|
||||||
RUN_TEST(test_should_keep_alive);
|
RUN_TEST(test_should_keep_alive);
|
||||||
RUN_TEST(test_match_prefix);
|
RUN_TEST(test_match_prefix);
|
||||||
@ -466,6 +501,7 @@ static const char *run_all_tests(void) {
|
|||||||
RUN_TEST(test_get_var);
|
RUN_TEST(test_get_var);
|
||||||
RUN_TEST(test_next_option);
|
RUN_TEST(test_next_option);
|
||||||
RUN_TEST(test_server);
|
RUN_TEST(test_server);
|
||||||
|
RUN_TEST(test_parse_multipart);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
67
mongoose.c
67
mongoose.c
@ -2979,24 +2979,24 @@ static int is_dav_mutation(const struct connection *conn) {
|
|||||||
}
|
}
|
||||||
#endif // NO_AUTH
|
#endif // NO_AUTH
|
||||||
|
|
||||||
int mg_parse_header(const char *str, const char *var_name, char *buf,
|
int parse_header(const char *str, int str_len, const char *var_name, char *buf,
|
||||||
size_t buf_size) {
|
size_t buf_size) {
|
||||||
int ch = ' ', len = 0, n = strlen(var_name);
|
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';
|
if (buf != NULL) buf[0] = '\0';
|
||||||
|
|
||||||
// Find where variable starts
|
// Find where variable starts
|
||||||
while (str != NULL && (s = strstr(str, var_name)) != NULL &&
|
for (s = str; s != NULL && &s[n] < end; s++) {
|
||||||
((s > str && s[-1] != ' ') || s[n] != '=')) {
|
if ((s == str || s[-1] == ' ') && s[n] == '=' &&
|
||||||
str = 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;
|
s += n + 1;
|
||||||
if (*s == '"' || *s == '\'') ch = *s++;
|
if (*s == '"' || *s == '\'') ch = *s++;
|
||||||
p = 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++;
|
if (p[0] == '\\' && p[1] == ch) p++;
|
||||||
buf[len++] = *p++;
|
buf[len++] = *p++;
|
||||||
}
|
}
|
||||||
@ -3004,6 +3004,7 @@ int mg_parse_header(const char *str, const char *var_name, char *buf,
|
|||||||
len = 0;
|
len = 0;
|
||||||
} else {
|
} else {
|
||||||
if (len > 0 && s[len - 1] == ',') len--;
|
if (len > 0 && s[len - 1] == ',') len--;
|
||||||
|
if (len > 0 && s[len - 1] == ';') len--;
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3011,6 +3012,11 @@ int mg_parse_header(const char *str, const char *var_name, char *buf,
|
|||||||
return len;
|
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
|
#ifdef USE_LUA
|
||||||
#include "lua_5.2.1.h"
|
#include "lua_5.2.1.h"
|
||||||
|
|
||||||
@ -3769,6 +3775,51 @@ int mg_get_var(const struct mg_connection *conn, const char *name,
|
|||||||
return len;
|
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) {
|
const char **mg_get_valid_option_names(void) {
|
||||||
return static_config_options;
|
return static_config_options;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
int mg_get_var(const struct mg_connection *conn, const char *var_name,
|
||||||
char *buf, size_t buf_len);
|
char *buf, size_t buf_len);
|
||||||
int mg_parse_header(const char *hdr, const char *var_name, char *buf, size_t);
|
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
|
// Utility functions
|
||||||
void *mg_start_thread(void *(*func)(void *), void *param);
|
void *mg_start_thread(void *(*func)(void *), void *param);
|
||||||
|
Loading…
Reference in New Issue
Block a user