From 4570daec42c1e38c2df88facc23743f45f907b3d Mon Sep 17 00:00:00 2001 From: Aleksey Veresov Date: Sun, 21 Jun 2020 21:27:46 +0000 Subject: Documentation started. --- Makefile | 4 +- examples/append.c | 4 +- include/magi/cookie.h | 5 +- include/magi/error.h | 22 +++++---- include/magi/response.h | 11 +++++ man/libmagi.3 | 1 + man/magi.3 | 69 ++++++++++++++++++++++++++++ man/magi_cookie.3 | 0 man/magi_error.3 | 0 man/magi_file.3 | 0 man/magi_loadfiles.3 | 0 man/magi_param.3 | 0 man/magi_parse.3 | 0 man/magi_request.3 | 0 man/magi_response.3 | 0 man/magi_urlenc.3 | 0 src/cookie.c | 33 +++++++------ src/cookies.c | 103 +++++++++++++++++++++-------------------- src/error.c | 1 - src/multipart.c | 120 ++++++++++++++++++++++++------------------------ src/urlenc.c | 6 +-- src/urlencoded.c | 46 +++++++++---------- 22 files changed, 255 insertions(+), 170 deletions(-) create mode 120000 man/libmagi.3 create mode 100644 man/magi.3 create mode 100644 man/magi_cookie.3 create mode 100644 man/magi_error.3 create mode 100644 man/magi_file.3 create mode 100644 man/magi_loadfiles.3 create mode 100644 man/magi_param.3 create mode 100644 man/magi_parse.3 create mode 100644 man/magi_request.3 create mode 100644 man/magi_response.3 create mode 100644 man/magi_urlenc.3 diff --git a/Makefile b/Makefile index 6d2c8bc..6803d5a 100644 --- a/Makefile +++ b/Makefile @@ -8,8 +8,8 @@ CC ?= gcc # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Preparations -# Compile under the most strict conditions: -CFLAGS = -xc -ansi -pedantic -Wall -Wextra +# Compile as ANSI C code: +CFLAGS = -xc -ansi -Wall # Specify linker to use the library: LFLAGS = -L$(BUILD) -lmagi # Debug and optimisation (as well as -static for valgrind) are not compatible: diff --git a/examples/append.c b/examples/append.c index fe85492..f1b8f96 100644 --- a/examples/append.c +++ b/examples/append.c @@ -1,5 +1,5 @@ /* This is the very basic example, showing work with form fields to append - * specified by user in form addon into some file (i.e. "file_to_append"). + * addon specified by user in form into some file (i.e. "file_to_append"). */ #include #include @@ -26,7 +26,7 @@ void response(magi_request *r) ""); append(r); printf("
" - "" + "" "" "
" ""); diff --git a/include/magi/cookie.h b/include/magi/cookie.h index 4760b75..7573747 100644 --- a/include/magi/cookie.h +++ b/include/magi/cookie.h @@ -27,9 +27,8 @@ void magi_cookies_free(magi_cookies *cookies); /* Add newitem onto top of cookies. */ void magi_cookies_add(magi_cookies **cookies, magi_cookie *newitem); -/* Get last from top of cookies cookie with name, null if no such cookie. - * Cookies are in reversed request order, and first cookie from request is - * the most accurate in terms of domain and path. */ +/* Get first cookie with given name, null if no such cookie. + * First cookie is the most accurate in terms of domain and path. */ const magi_cookie *magi_cookies_get(const magi_cookies *cookies, const char *name); diff --git a/include/magi/error.h b/include/magi/error.h index 19538ae..6f64228 100644 --- a/include/magi/error.h +++ b/include/magi/error.h @@ -5,22 +5,24 @@ */ +/* Magi error codes. */ typedef enum magi_error { - magi_error_none = 0, - magi_error_nobound, - magi_error_unknown, - magi_error_notype, - magi_error_length, - magi_error_memory, - magi_error_cookies, - magi_error_urlenc, - magi_error_multipart, - magi_error_limit + magi_error_none = 0, /* No error, all is ok. */ + magi_error_nobound, /* No boundary provided for multipart/form-data. */ + magi_error_unknown, /* Unknown Content Type. */ + magi_error_notype, /* No Content Type provided. */ + magi_error_length, /* Wrong Content Length. */ + magi_error_cookies, /* Bad Cookies header. */ + magi_error_urlenc, /* Wrong url encoding. */ + magi_error_multipart, /* Malformed multipart/form-data. */ + magi_error_limit /* One of specified limits reached. */ } magi_error; +/* Get description message of given error. */ const char *magi_error_message(magi_error error); +/* Response default error page for given error. */ void magi_error_response(magi_error error); diff --git a/include/magi/response.h b/include/magi/response.h index e67b279..9364fd4 100644 --- a/include/magi/response.h +++ b/include/magi/response.h @@ -13,6 +13,7 @@ #include +/* Response headers as three sequential groups. */ typedef struct magi_response { magi_params *head_response; magi_params *head_general; @@ -20,21 +21,31 @@ typedef struct magi_response { } magi_response; +/* Response initialiser, setup defaults. */ void magi_response_init(magi_response *r); +/* Send response headers and free memory used by it. */ void magi_response_free(magi_response *r); +/* Just response defaults. (text/html, 200 Ok) */ void magi_response_default(); +/* Change resposne status header. */ void magi_response_status(magi_response *r, int code, const char *description); +/* Add cookie to response. */ void magi_response_cookie(magi_response *r, const char *n, const char *d); +/* Add cookie with additional information to response. */ void magi_response_cookie_complex(magi_response *r, magi_cookie *c); +/* Add request to discard cookie to response. */ void magi_response_cookie_discard(magi_response *r, const char *name); +/* Just add some general custom header. */ void magi_response_header(magi_response *r, const char *n, const char *d); +/* Change Content-Length header. */ void magi_response_content_length(magi_response *r, int length); +/* Change Content-Type header. */ void magi_response_content_type(magi_response *r, const char *type); diff --git a/man/libmagi.3 b/man/libmagi.3 new file mode 120000 index 0000000..e341a9a --- /dev/null +++ b/man/libmagi.3 @@ -0,0 +1 @@ +magi.3 \ No newline at end of file diff --git a/man/magi.3 b/man/magi.3 new file mode 100644 index 0000000..fcf6679 --- /dev/null +++ b/man/magi.3 @@ -0,0 +1,69 @@ +.TH MAGI 3 2020-05-02 v0.0.1 "Library Manual" +.SH NAME +.B magi +\- Common Gateway Interface (CGI) library +.SH SYNOPSIS +.B #include +.SH DESCRIPTION +The +.B magi +library gives the user a way to interact with the web server +through CGI as described in +.IR "RFC 3875" . +The library is free and open source software. +.SS Usage +A program using +.B magi +library must be linked with the +.B -lmagi +option. +.P +Main task of the +.B magi +library is to analyse CGI request and represent it to the user in +.B magi_request +data structure. This is done by calling +.B magi_parse +on initialized via +.B magi_request_init +request variable. After initialization the user is able to configure +limits on the input and setup callback to process files loaded as +.IR multipart/form-data . +The +.B magi +library comes with +.B magi_loadfiles +callback usable for the majority of cases. +.P +CGI response utilities are also provided. The CGI headers are +outputted with +.B magi_response +and its methods. You can output defaults (Content-Type: text/html; +Status: 200 Ok) by calling +.BR magi_response_default . +Utility to form urlencoded strings is provided via +.BR magi_urlenc . +.SS Error handling +If function is returning pointer, error is only in case of null returned. +If function is returning +.I int +as success mark it will be null only in case of error, and one otherwise. +Exact +.B magi_error +code is in +.B error +field of +.B magi_request +structure. For other modules error codes seem to be overkill. +.SH AUTHORS AND LICENSE +Copyrigth 2019-2020 +.B Aleksey Veresov +.RI < aleksey@veresov.pro > +.P +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from +the use of this software. +.P +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. diff --git a/man/magi_cookie.3 b/man/magi_cookie.3 new file mode 100644 index 0000000..e69de29 diff --git a/man/magi_error.3 b/man/magi_error.3 new file mode 100644 index 0000000..e69de29 diff --git a/man/magi_file.3 b/man/magi_file.3 new file mode 100644 index 0000000..e69de29 diff --git a/man/magi_loadfiles.3 b/man/magi_loadfiles.3 new file mode 100644 index 0000000..e69de29 diff --git a/man/magi_param.3 b/man/magi_param.3 new file mode 100644 index 0000000..e69de29 diff --git a/man/magi_parse.3 b/man/magi_parse.3 new file mode 100644 index 0000000..e69de29 diff --git a/man/magi_request.3 b/man/magi_request.3 new file mode 100644 index 0000000..e69de29 diff --git a/man/magi_response.3 b/man/magi_response.3 new file mode 100644 index 0000000..e69de29 diff --git a/man/magi_urlenc.3 b/man/magi_urlenc.3 new file mode 100644 index 0000000..e69de29 diff --git a/src/cookie.c b/src/cookie.c index a64f5cb..fc66428 100644 --- a/src/cookie.c +++ b/src/cookie.c @@ -4,6 +4,19 @@ #include +void magi_cookies_free(magi_cookies *cookies) +{ + if (cookies) { + magi_cookies_free(cookies->next); + free(cookies->next); + free(cookies->item.name); + free(cookies->item.data); + free(cookies->item.path); + free(cookies->item.domain); + free(cookies->item.max_age); + } +} + void magi_cookies_add(magi_cookies **cookies, magi_cookie *newitem) { magi_cookies *node = malloc(sizeof(*node)); @@ -17,27 +30,13 @@ void magi_cookies_add(magi_cookies **cookies, magi_cookie *newitem) const magi_cookie *magi_cookies_get(const magi_cookies *cookies, const char *name) { - const magi_cookie *res = 0; - if (!cookies || !name) { + if (!name) { return 0; } for (; cookies; cookies = cookies->next) { if (!strcmp(cookies->item.name, name)) { - res = &cookies->item; + return &cookies->item; } } - return res; -} - -void magi_cookies_free(magi_cookies *cookies) -{ - if (cookies) { - magi_cookies_free(cookies->next); - free(cookies->next); - free(cookies->item.name); - free(cookies->item.data); - free(cookies->item.path); - free(cookies->item.domain); - free(cookies->item.max_age); - } + return 0; } diff --git a/src/cookies.c b/src/cookies.c index 88ed67a..d1aeb46 100644 --- a/src/cookies.c +++ b/src/cookies.c @@ -7,10 +7,7 @@ typedef enum dt { dt_plain = 0, dt_version, dt_path, dt_domain } dt; -typedef struct automata automata; -typedef void (*state)(automata *a, char c); -struct automata { - state s; +typedef struct automata { magi_cookies **list; magi_cookie cookie; char *buf; @@ -20,7 +17,8 @@ struct automata { int is_advanced; int is_quoted; dt datatype; -}; +} automata; +typedef void *(*state)(automata *a, char c); static void nulify_cookie(automata *a) @@ -62,6 +60,7 @@ static void end_name(automata *a) if (a->datatype == dt_plain) { if (a->cookie.name) { magi_cookies_add(a->list, &a->cookie); + a->list = &(*a->list)->next; } nulify_cookie(a); a->cookie.name = a->buf; @@ -83,95 +82,100 @@ static int end_data(automata *a) return 1; } -static void state_name(automata *a, char c); -static void state_pre_name(automata *a, char c) +static void *state_name(automata *a, char c); +static void *state_pre_name(automata *a, char c) { - if (32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={}", c)) { - a->s = state_name; + if (c == ' ' || c == '\t'){ + return state_pre_name; + } else if (32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={}", c)) { magi_str_add(&a->buf, &a->buf_len, &a->buf_size, c); - } else if (c != ' ' && c != '\t'){ - a->s = 0; + return state_name; } + return 0; } -static void state_pre_data(automata *a, char c); -static void state_post_name(automata *a, char c); -static void state_name(automata *a, char c) +static void *state_pre_data(automata *a, char c); +static void *state_post_name(automata *a, char c); +static void *state_name(automata *a, char c) { if (c == '=') { - a->s = state_pre_data; end_name(a); + return state_pre_data; } else if (c == ' ' || c == '\t') { - a->s = state_post_name; end_name(a); + return state_post_name; } else if (32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={}", c)) { magi_str_add(&a->buf, &a->buf_len, &a->buf_size, c); - } else { - a->s = 0; + return state_name; } + return 0; } -static void state_post_name(automata *a, char c) +static void *state_post_name(automata *a, char c) { if (c == '=') { - a->s = state_pre_data; - } else if (c != ' ' && c != '\t') { - a->s = 0; + return state_pre_data; + } else if (c == ' ' || c == '\t') { + return state_post_name; } + return 0; } -static void state_data(automata *a, char c); -static void state_data_quoted(automata *a, char c); -static void state_pre_data(automata *a, char c) +static void *state_data(automata *a, char c); +static void *state_data_quoted(automata *a, char c); +static void *state_pre_data(automata *a, char c) { if (c == '"') { - a->s = state_data_quoted; + return state_data_quoted; + } else if (c == ' ' || c == '\t') { + return state_pre_data; } else if (32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={}", c)) { - a->s = state_data; magi_str_add(&a->buf, &a->buf_len, &a->buf_size, c); - } else if (c != ' ' && c != '\t') { - a->s = 0; + return state_data; } + return 0; } -static void state_post_data(automata *a, char c); -static void state_data(automata *a, char c) +static void *state_post_data(automata *a, char c); +static void *state_data(automata *a, char c) { if (c == ';' || (c == ',' && a->is_first)) { a->is_first = 0; - a->s = end_data(a) ? state_pre_name : 0; + return end_data(a) ? state_pre_name : 0; } else if (c == ' ' || c == '\t') { - a->s = end_data(a) ? state_post_data : 0; + return end_data(a) ? state_post_data : 0; } else if (32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={}", c)) { magi_str_add(&a->buf, &a->buf_len, &a->buf_size, c); - } else { - a->s = 0; + return state_data; } + return 0; } -static void state_data_quoted(automata *a, char c) +static void *state_data_quoted(automata *a, char c) { if (c == '"') { - a->s = end_data(a) ? state_post_data : 0; + return end_data(a) ? state_post_data : 0; } + return state_data_quoted; } -static void state_post_data(automata *a, char c) +static void *state_post_data(automata *a, char c) { if (c == ';' || (c == ',' && a->is_first)) { a->is_first = 0; - a->s = state_pre_name; - } else if (c != ' ' && c != '\t') { - a->s = 0; + return state_pre_name; + } else if (c == ' ' || c == '\t') { + return state_post_data; } + return 0; } -static void parse_end(magi_error *e, automata *a) +static void parse_end(magi_error *e, automata *a, state s) { - if (a->s == state_data_quoted) { + if (s == state_data_quoted) { *e = magi_error_cookies; - } else if (a->s == state_data) { + } else if (s == state_data) { if (!a->cookie.name) { *e = magi_error_cookies; } else if (end_data(a)) { @@ -180,7 +184,7 @@ static void parse_end(magi_error *e, automata *a) } else { *e = magi_error_cookies; } - } else if (a->s != state_post_data) { + } else if (s != state_post_data) { *e = magi_error_cookies; } } @@ -188,13 +192,14 @@ static void parse_end(magi_error *e, automata *a) void magi_parse_cookies(magi_request *request, const char *data) { - automata a = { 0, 0, { 0, 0, 0, 0, 0 }, 0, 0, 0, 1, 0, 0, 0 }; + state s; + automata a = { 0, { 0, 0, 0, 0, 0 }, 0, 0, 0, 1, 0, 0, 0 }; a.list = &request->cookies; request->cookies = 0; - for (a.s = state_pre_name; a.s && *data; ++data) { - a.s(&a, *data); + for (s = state_pre_name; s && *data; ++data) { + s = s(&a, *data); } - parse_end(&request->error, &a); + parse_end(&request->error, &a, s); free(a.cookie.name); free(a.cookie.data); free(a.cookie.path); diff --git a/src/error.c b/src/error.c index eb16eb6..0bb553b 100644 --- a/src/error.c +++ b/src/error.c @@ -11,7 +11,6 @@ const char *magi_error_message(magi_error error) "Content-Type is unknown.", /* magi_error_unknown */ "Content-Type is not given.", /* magi_error_notype */ "Mismatch of content length.", /* magi_error_length */ - "Cannot allocate memory.", /* magi_error_memory */ "Cannot read cookies.", /* magi_error_cookies */ "Cannot decode URL.", /* magi_error_urlenc */ "Cannot read multipart body.", /* magi_error_multipart */ diff --git a/src/multipart.c b/src/multipart.c index d2a1c7f..a265184 100644 --- a/src/multipart.c +++ b/src/multipart.c @@ -32,10 +32,7 @@ static int is_str_token(char *str) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Automata for multipart/form-data */ -typedef struct automata automata; -typedef void (*state)(automata *a, char c); -struct automata { - state s; +typedef struct automata { magi_request *request; magi_file file; magi_param param; @@ -51,7 +48,8 @@ struct automata { int is_CR_readed; int is_quoted; int readed; -}; +} automata; +typedef void *(*state)(automata *a, char c); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -224,15 +222,16 @@ static void apply_callback(automata *a) } } -static void state_pname_pre(automata *a, char c); -static void data_add_act(automata *a, char c, char **dest, int *len, int *size) +static void *state_pname_pre(automata *a, char c); +static void *state_data(automata *a, char c); +static void *data_add_act(automata *a, char c, char **dest, int *l, int *s) { int pos = a->boundary_pos; for (a->boundary_pos = 0; a->boundary_pos < pos; ++a->boundary_pos) { if (a->is_end_suspected) { - magi_str_add(dest, len, size, endget(a)); + magi_str_add(dest, l, s, endget(a)); } else { - magi_str_add(dest, len, size, sepget(a)); + magi_str_add(dest, l, s, sepget(a)); } apply_callback(a); } @@ -240,24 +239,25 @@ static void data_add_act(automata *a, char c, char **dest, int *len, int *size) a->is_end_suspected = 0; if (sepget(a) != c) { - magi_str_add(dest, len, size, c); + magi_str_add(dest, l, s, c); apply_callback(a); } else { a->boundary_pos++; if (a->boundary_pos == seplen(a)) { param_end(a); - a->s = state_pname_pre; + return state_pname_pre; } } + return state_data; } -static void data_add(automata *a, char c) +static void *data_add(automata *a, char c) { if (a->file.filename) { int max = a->request->callback.addon_max + 1; - data_add_act(a, c, &a->buf, &a->buf_size, &max); + return data_add_act(a, c, &a->buf, &a->buf_size, &max); } else { - data_add_act(a, c, &a->param.data, &a->len, &a->size); + return data_add_act(a, c, &a->param.data, &a->len, &a->size); } } @@ -265,113 +265,114 @@ static void data_add(automata *a, char c) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * State analysers */ -static void state_begin(automata *a, char c) +static void *state_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. */ } else { a->boundary_pos++; if (a->boundary_pos == seplen(a)) { - a->s = state_pname_pre; /* Separator is completed, so move on. */ + return state_pname_pre; /* Separator is completed, so move on. */ } } + return state_begin; } -static void state_data(automata *a, char c); -static void state_pname(automata *a, char c); -static void state_pname_pre(automata *a, char c) +static void *state_pname(automata *a, char c); +static void *state_pname_pre(automata *a, char c) { if (a->is_CR_readed) { - if (c == '\n') { - a->is_CR_readed = 0; - a->boundary_pos = 0; - a->s = state_data; - } else { - a->s = 0; + if (c != '\n') { + return 0; } + a->is_CR_readed = 0; + a->boundary_pos = 0; + return state_data; } else if (c == '\r') { a->is_CR_readed = 1; + return state_pname_pre; } else if (is_token(c)) { - a->s = state_pname; magi_str_add(&a->subparam.name, &a->len, &a->size, c); - } else { - a->s = 0; + return state_pname; } + return 0; } -static void state_pdata(automata *a, char c); -static void state_pname_end(automata *a, char c); -static void state_pname(automata *a, char c) +static void *state_pdata(automata *a, char c); +static void *state_pname_end(automata *a, char c); +static void *state_pname(automata *a, char c) { if (c == ':') { a->len = 0; a->size = 1; - a->s = state_pdata; + return state_pdata; } else if (c == ' ' || c == '\t') { - a->s = state_pname_end; + return state_pname_end; } else if (is_token(c)) { magi_str_add(&a->subparam.name, &a->len, &a->size, c); - } else { - a->s = 0; + return state_pname; } + return 0; } -static void state_pname_end(automata *a, char c) +static void *state_pname_end(automata *a, char c) { if (c == ':') { a->len = 0; a->size = 1; - a->s = state_pdata; - } else if (c != ' ' && c != '\t') { - a->s = 0; + return state_pdata; + } else if (c == ' ' || c == '\t') { + return state_pname_end; } + return 0; } -static void state_pdata(automata *a, char c) +static void *state_pdata(automata *a, char c) { if (a->is_CR_readed) { a->is_CR_readed = 0; if (c == '\n') { - a->s = subparam_end(a) ? state_pname_pre : 0; - } else { - magi_str_add(&a->subparam.data, &a->len, &a->size, '\r'); - magi_str_add(&a->subparam.data, &a->len, &a->size, c); + return subparam_end(a) ? state_pname_pre : 0; } + magi_str_add(&a->subparam.data, &a->len, &a->size, '\r'); + magi_str_add(&a->subparam.data, &a->len, &a->size, c); } else if (c == '\r') { a->is_CR_readed = 1; } else { magi_str_add(&a->subparam.data, &a->len, &a->size, c); } + return state_pdata; } -static void state_end(automata *a, char c); -static void state_data(automata *a, char c) +static void *state_end(automata *a, char c); +static void *state_data(automata *a, char c) { if (a->is_end_suspected) { if (endget(a) != c) { - data_add(a, c); + return data_add(a, c); } else { a->boundary_pos++; if (a->boundary_pos == endlen(a)) { param_end(a); - a->s = state_end; + return state_end; } } } else if (sepget(a) == c) { a->boundary_pos++; if (a->boundary_pos == seplen(a)) { param_end(a); - a->s = state_pname_pre; + return state_pname_pre; } } else if ((a->boundary_pos == seplen(a) - 2) && endget(a) == c) { a->is_end_suspected = 1; a->boundary_pos++; } else { - data_add(a, c); + return data_add(a, c); } + return state_data; } -static void state_end(automata *a, char c) { (void)a; (void)c; } +static void *state_end(automata *a, char c) { return state_end; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -381,19 +382,20 @@ static void run_automata(automata *a, int (*next)(void *next_userdata), void *next_userdata) { - int c = next(next_userdata); - int maxr = a->request->limits.params_body; - for (a->s = state_begin; - a->s && a->s != state_end && c != EOF && (!maxr || a->readed != maxr); + state s; + int c = next(next_userdata); + int maxr = a->request->limits.params_body; + for (s = state_begin; + s && s != state_end && c != EOF && (!maxr || a->readed != maxr); c = next(next_userdata)) { - a->s(a, c); + s = s(a, c); ++a->readed; } if (maxr && a->readed == maxr) { a->request->error = magi_error_limit; - } else if (a->s == state_data && is_semiend(a)) { + } else if (s == state_data && is_semiend(a)) { param_end(a); - } else if (a->s != state_end) { + } else if (s != state_end) { a->request->error = magi_error_multipart; free(a->subparam.name); free(a->subparam.data); @@ -410,7 +412,7 @@ void magi_parse_multipart(magi_request *request, void *next_userdata) { automata a = { - 0, 0, { 0, 0, 0 }, { 0, 0 }, { 0, 0 }, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0 + 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; diff --git a/src/urlenc.c b/src/urlenc.c index 28fbd48..eb65c81 100644 --- a/src/urlenc.c +++ b/src/urlenc.c @@ -11,7 +11,7 @@ /* Call only if 0 <= num && num <= 15. */ static char to_hex(int num) { - static const char * const hex = "0123456789ABCDEF"; + static const char *const hex = "0123456789ABCDEF"; return hex[num]; } @@ -24,7 +24,7 @@ static int is_url(char c) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * URL Encoding */ -int magi_urlenc_size(const char * plain) +int magi_urlenc_size(const char *plain) { int size; if (!plain) { @@ -38,7 +38,7 @@ int magi_urlenc_size(const char * plain) return size; } -void magi_urlencode(const char * plain, char * code) +void magi_urlenc(const char *plain, char *code) { if (!plain || !code) { return; diff --git a/src/urlencoded.c b/src/urlencoded.c index 755b059..27c9c21 100644 --- a/src/urlencoded.c +++ b/src/urlencoded.c @@ -61,10 +61,7 @@ static int deurl(char **data) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Urlencoded Automata */ -typedef struct automata automata; -typedef void (*state)(automata *a, char c); -struct automata { - state s; +typedef struct automata { magi_params **list; char *name; int nlen; @@ -72,18 +69,19 @@ struct automata { char *data; int dlen; int dsize; -}; +} automata; +typedef void *(*state)(automata *a, char c); -static void state_parse_data(automata *a, char c); -static void state_parse_name(automata *a, char c) +static void *state_parse_data(automata *a, char c); +static void *state_parse_name(automata *a, char c) { if (c == '&' || c == ';') { - a->s = 0; + return 0; } else if (c == '=') { - a->s = deurl(&a->name) ? state_parse_data : 0; - } else { - magi_str_add(&a->name, &a->nlen, &a->nsize, c); + return deurl(&a->name) ? state_parse_data : 0; } + magi_str_add(&a->name, &a->nlen, &a->nsize, c); + return state_parse_name; } static void add_to_list(automata *a) @@ -96,34 +94,34 @@ static void add_to_list(automata *a) a->data = 0; } -static void state_parse_data(automata *a, char c) +static void *state_parse_data(automata *a, char c) { if (c == '=') { - a->s = 0; + return 0; } else if (c == '&' || c == ';') { - if (deurl(&a->data)) { - a->s = state_parse_name; - add_to_list(a); - } else { - a->s = 0; + if (!deurl(&a->data)) { + return 0; } - } else { - magi_str_add(&a->data, &a->dlen, &a->dsize, c); + add_to_list(a); + return state_parse_name; } + magi_str_add(&a->data, &a->dlen, &a->dsize, c); + return state_parse_data; } magi_error magi_parse_urlencoded(magi_params **list, const char *encoded) { - automata a = { state_parse_name, 0, 0, 0, 0, 0, 0, 0 }; + state s; + automata a = { 0, 0, 0, 0, 0, 0, 0 }; a.list = list; *list = 0; if (!encoded || !*encoded) { return 0; } - for (; *encoded && a.s; ++encoded) { - a.s(&a, *encoded); + for (s = state_parse_name; s && *encoded; ++encoded) { + s = s(&a, *encoded); } - if (a.s == state_parse_name || !a.s || !deurl(&a.data)) { + if (s == state_parse_name || !s || !deurl(&a.data)) { return magi_error_urlenc; } add_to_list(&a); -- cgit v1.2.3