From 8f1e6faa7f548c9a8bcbcac71c8f239a6540b926 Mon Sep 17 00:00:00 2001 From: Aleksey Veresov Date: Wed, 11 Mar 2020 17:54:19 +0300 Subject: [magi] --- src/multipart.c | 262 +++++++++++++++++++++++++------------------------------- 1 file changed, 116 insertions(+), 146 deletions(-) (limited to 'src/multipart.c') diff --git a/src/multipart.c b/src/multipart.c index 001b4d1..72fe607 100644 --- a/src/multipart.c +++ b/src/multipart.c @@ -18,7 +18,7 @@ static int is_token(char c) return 32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={} \t", c); } -static int is_str_token(char * str) +static int is_str_token(char *str) { int is = str && *str; /* Empty string is not valid. */ while (is && *str) { @@ -32,7 +32,7 @@ static int is_str_token(char * str) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Automata for multipart/form-data */ -enum st { +typedef enum st { st_error = 0, st_begin, st_pname_pre, @@ -41,31 +41,31 @@ enum st { st_pdata, st_data, st_end -}; - -struct automata { - struct magi_request * request; - struct magi_file file; - struct magi_param param; - struct magi_param subparam; - char * buf; - int buf_size; - int size; - int len; - char * boundary; - int boundary_pos; - int boundary_len; - int is_end_suspected; - int is_CR_readed; - int is_quoted; - int readed; -}; +} st; + +typedef struct automata { + magi_request *request; + magi_file file; + magi_param param; + magi_param subparam; + char *buf; + int buf_size; + int size; + int len; + char *boundary; + int boundary_pos; + int boundary_len; + int is_end_suspected; + int is_CR_readed; + int is_quoted; + int readed; +} automata; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Automata Shortcuts */ -static char * extract_filename(char * n) +static char *extract_filename(char *n) { n = strchr(n, '='); if (!n) { @@ -80,9 +80,9 @@ static char * extract_filename(char * n) } } -static int content_disposition(struct automata * a) +static int content_disposition(automata *a) { - char * n = strchr(a->subparam.data, '='); + char *n = strchr(a->subparam.data, '='); if (!n) { return 0; } @@ -99,11 +99,11 @@ static int content_disposition(struct automata * a) return 0; } } - a->file.file_name = extract_filename(n); - if (a->file.file_name) { - a->file.param_name = a->param.name; - a->file.params = 0; - a->param.name = 0; + a->file.filename = extract_filename(n); + if (a->file.filename) { + a->file.field = a->param.name; + a->file.params = 0; + a->param.name = 0; } free(a->subparam.name); free(a->subparam.data); @@ -112,53 +112,42 @@ static int content_disposition(struct automata * a) return 1; } -static int subparam_end(struct automata * a) +static int subparam_end(automata *a) { a->size = 1; a->len = 0; magi_str_lowercase(a->subparam.name); if (!strcmp(a->subparam.name, "content-disposition")) { return content_disposition(a); - } else if (magi_param_list_add(&a->file.params, &a->subparam)) { - a->subparam.name = 0; - a->subparam.data = 0; - return 1; } - return 0; + magi_params_add(&a->file.params, &a->subparam); + a->subparam.name = 0; + a->subparam.data = 0; + return 1; } -static int param_end(struct automata * a) +static int param_end(automata *a) { - if (a->file.file_name) { - a->request->file_callback(&a->file, a->buf, a->buf_size, 1, - a->request->file_callback_userdata); - a->readed -= a->buf_size; + if (a->file.filename) { + a->request->callback.act(a->request->callback.userdata, + &a->file, a->buf, a->buf_size); + a->request->callback.act(a->request->callback.userdata, + &a->file, 0, 0); + a->readed -= a->buf_size; a->buf_size = 0; - if (!magi_file_list_add(&a->request->files, &a->file)) { - free(a->file.file_name); - free(a->file.param_name); - magi_param_list_destroy(a->file.params); - free(a->file.params); - a->request->error = magi_error_multipart; - return 0; - } - a->file.file_name = 0; - a->file.param_name = 0; - a->file.params = 0; - a->size = 1; - a->len = 0; + magi_files_add(&a->request->files, &a->file); + a->file.filename = 0; + a->file.field = 0; + a->file.params = 0; + a->size = 1; + a->len = 0; return 1; } if (!a->param.name) { a->request->error = magi_error_multipart; return 0; } - if (!magi_param_list_add(&a->request->params, &a->param)) { - free(a->param.name); - free(a->param.data); - a->request->error = magi_error_multipart; - return 0; - } + magi_params_add(&a->request->body, &a->param); a->param.name = 0; a->param.data = 0; a->size = 1; @@ -170,7 +159,7 @@ static int param_end(struct automata * a) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Boundary Interfaces */ -static char sepget(const struct automata * a) +static char sepget(const automata *a) { char c; const int pos_after = a->boundary_pos - 4 - a->boundary_len; @@ -192,12 +181,9 @@ static char sepget(const struct automata * a) return c; } -static int seplen(const struct automata * a) -{ - return a->boundary_len + 6; -} +static int seplen(const automata *a) { return a->boundary_len + 6; } -static char endget(const struct automata * a) +static char endget(const automata *a) { char c; const int pos_after = a->boundary_pos - 4 - a->boundary_len; @@ -221,13 +207,13 @@ static char endget(const struct automata * a) return c; } -static int endlen(const struct automata * a) +static int endlen(const automata *a) { return a->boundary_len + 8; } -static int is_semiend(const struct automata * a) -{ /* Is end readed, expect last two chars, which are CR LF? */ +static int is_semiend(const automata *a) +{ /* Is end readed, expect last two chars, which are CR LF? */ return a->is_end_suspected && (a->boundary_pos == endlen(a) - 2); } @@ -235,19 +221,18 @@ static int is_semiend(const struct automata * a) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Data Reading */ -static void apply_callback(struct automata * a) +static void apply_callback(automata *a) { - int full = a->buf_size == a->request->file_callback_addon_max; - if (a->file.file_name && full) { - a->request->file_callback(&a->file, a->buf, a->buf_size, 0, - a->request->file_callback_userdata); - a->readed -= a->buf_size; + int full = a->buf_size == a->request->callback.addon_max; + if (a->file.filename && full) { + a->request->callback.act(a->request->callback.userdata, + &a->file, a->buf, a->buf_size); + a->readed -= a->buf_size; a->buf_size = 0; } } -static enum st data_add_act( - struct automata * a, char c, char ** dest, int * len, int * size) +static st data_add_act(automata *a, char c, char **dest, int *len, int *size) { int pos = a->boundary_pos; for (a->boundary_pos = 0; a->boundary_pos < pos; ++a->boundary_pos) { @@ -275,10 +260,10 @@ static enum st data_add_act( } } -static enum st data_add(struct automata * a, char c) +static st data_add(automata *a, char c) { - if (a->file.file_name) { - int max = a->request->file_callback_addon_max + 1; + if (a->file.filename) { + int max = a->request->callback.addon_max + 1; return data_add_act(a, c, &a->buf, &a->buf_size, &max); } else { return data_add_act(a, c, &a->param.data, &a->len, &a->size); @@ -289,20 +274,20 @@ static enum st data_add(struct automata * a, char c) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * State analysers */ -static enum st parse_begin(struct automata * a, char c) +static st parse_begin(automata *a, char c) { - if (sepget(a) != c) { /* 'c' is not wanted character from separator; */ - a->boundary_pos = 0; /* so nullify progress in reading separator. */ + if (sepget(a) != c) { /* 'c' is not wanted character from separator; */ + a->boundary_pos = 0; /* so nullify progress in reading separator. */ } else { a->boundary_pos++; if (a->boundary_pos == seplen(a)) { - return st_pname_pre; /* Separator is completed, so move on. */ + return st_pname_pre; /* Separator is completed, so move on. */ } } return st_begin; } -static enum st parse_pname_pre(struct automata * a, char c) +static st parse_pname_pre(automata *a, char c) { if (a->is_CR_readed) { if (c != '\n') { @@ -314,14 +299,15 @@ static enum st parse_pname_pre(struct automata * a, char c) } else if (c == '\r') { a->is_CR_readed = 1; return st_pname_pre; - } else if (is_token(c) && - magi_str_add(&a->subparam.name, &a->len, &a->size, c)) { - return st_pname; } - return st_error; + if (!is_token(c)) { + return st_error; + } + magi_str_add(&a->subparam.name, &a->len, &a->size, c); + return st_pname; } -static enum st parse_pname(struct automata * a, char c) +static st parse_pname(automata *a, char c) { if (c == ':') { a->len = 0; @@ -329,14 +315,15 @@ static enum st parse_pname(struct automata * a, char c) return st_pdata; } else if (c == ' ' || c == '\t') { return st_pname_end; - } else if (is_token(c) && - magi_str_add(&a->subparam.name, &a->len, &a->size, c)) { - return st_pname; } - return st_error; + if (!is_token(c)) { + return st_error; + } + magi_str_add(&a->subparam.name, &a->len, &a->size, c); + return st_pname; } -static enum st parse_pname_end(struct automata * a, char c) +static st parse_pname_end(automata *a, char c) { if (c == ':') { a->len = 0; @@ -348,7 +335,7 @@ static enum st parse_pname_end(struct automata * a, char c) return st_error; } -static enum st parse_pdata(struct automata * a, char c) +static st parse_pdata(automata *a, char c) { if (a->is_CR_readed) { a->is_CR_readed = 0; @@ -357,21 +344,19 @@ static enum st parse_pdata(struct automata * a, char c) return st_pname_pre; } return st_error; - } else if (magi_str_add(&a->subparam.data, &a->len, &a->size, '\r') && - magi_str_add(&a->subparam.data, &a->len, &a->size, c)) { - return st_pdata; } - return st_error; + magi_str_add(&a->subparam.data, &a->len, &a->size, '\r'); + magi_str_add(&a->subparam.data, &a->len, &a->size, c); + return st_pdata; } else if (c == '\r') { a->is_CR_readed = 1; return st_pdata; - } else if (magi_str_add(&a->subparam.data, &a->len, &a->size, c)) { - return st_pdata; } - return st_error; + magi_str_add(&a->subparam.data, &a->len, &a->size, c); + return st_pdata; } -static enum st parse_data(struct automata * a, char c) +static st parse_data(automata *a, char c) { if (a->is_end_suspected) { if (endget(a) != c) { @@ -398,51 +383,35 @@ static enum st parse_data(struct automata * a, char c) return data_add(a, c); } -static enum st parse_end(struct automata * a, char c) -{ - return st_end; -} +static st parse_end(automata *a, char c) { return st_end; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Automata Runner */ -static void run_automata(struct automata * a, - int (*next)(void * next_userdata), - void * next_userdata) +static void run_automata(automata *a, + int (*next)(void *next_userdata), + void *next_userdata) { - enum st state = st_begin; - int c = next(next_userdata); + st state = st_begin; + int c = next(next_userdata); + int maxr = a->request->limits.params_body; while (state && state != st_end && c != EOF && - (!a->request->params_max || a->readed != a->request->params_max)) { + (!maxr || a->readed != maxr)) { switch (state) { - case st_begin: - state = parse_begin(a, c); - break; - case st_pname_pre: - state = parse_pname_pre(a, c); - break; - case st_pname: - state = parse_pname(a, c); - break; - case st_pname_end: - state = parse_pname_end(a, c); - break; - case st_pdata: - state = parse_pdata(a, c); - break; - case st_data: - state = parse_data(a, c); - break; - case st_end: - state = parse_end(a, c); - default: - break; + case st_begin: state = parse_begin(a, c); break; + case st_pname_pre: state = parse_pname_pre(a, c); break; + case st_pname: state = parse_pname(a, c); break; + case st_pname_end: state = parse_pname_end(a, c); break; + case st_pdata: state = parse_pdata(a, c); break; + case st_data: state = parse_data(a, c); break; + case st_end: state = parse_end(a, c); break; + default: break; } c = next(next_userdata); ++a->readed; } - if (a->request->params_max && a->readed == a->request->params_max) { + if (maxr && a->readed == maxr) { a->request->error = magi_error_limit; return; } @@ -461,17 +430,18 @@ static void run_automata(struct automata * a, /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Automata Interfaces */ -void magi_multipart(struct magi_request * request, - char * boundary, - int (*next)(void * userdata), - void * next_userdata) +void magi_parse_multipart(magi_request *request, + char *boundary, + int (*next)(void *userdata), + void *next_userdata) { - struct automata a = { 0, { 0, 0, 0 }, { 0, 0 }, { 0, 0 }, 0, 0, 1, - 0, 0, 2, 0, 0, 0, 0 }; - a.request = request; - a.boundary = boundary; - a.boundary_len = strlen(boundary); - a.buf = malloc(request->file_callback_addon_max + 1); + automata a = { + 0, { 0, 0, 0 }, { 0, 0 }, { 0, 0 }, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0 + }; + a.request = request; + a.boundary = boundary; + a.boundary_len = strlen(boundary); + a.buf = malloc(request->callback.addon_max + 1); if (a.buf) { run_automata(&a, next, next_userdata); free(a.buf); -- cgit v1.2.3