aboutsummaryrefslogtreecommitdiff
path: root/src/multipart.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/multipart.c')
-rw-r--r--src/multipart.c262
1 files changed, 116 insertions, 146 deletions
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);