aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Veresov <aleksey@veresov.pro>2020-03-11 17:54:19 +0300
committerAleksey Veresov <aleksey@veresov.pro>2020-03-11 17:54:19 +0300
commit8f1e6faa7f548c9a8bcbcac71c8f239a6540b926 (patch)
treedd5dfec60de8e52472fe8db2b5ae66010d5dc1d3
parent5cfe6cdf6af2d630d21871f9193fc1b4a7db24ff (diff)
downloadmagi-8f1e6faa7f548c9a8bcbcac71c8f239a6540b926.tar
magi-8f1e6faa7f548c9a8bcbcac71c8f239a6540b926.tar.xz
magi-8f1e6faa7f548c9a8bcbcac71c8f239a6540b926.zip
[magi]
-rw-r--r--examples/Makefile2
-rw-r--r--examples/append.c2
-rw-r--r--examples/cookie.c2
-rw-r--r--examples/echo.c44
-rw-r--r--examples/upload.c11
-rw-r--r--include/magi.h1
-rw-r--r--include/magi/response.h4
-rw-r--r--src/cgi.c19
-rw-r--r--src/cookies.c171
-rw-r--r--src/multipart.c262
-rw-r--r--src/param.c13
-rw-r--r--src/request.c12
-rw-r--r--src/response.c26
-rw-r--r--src/tools.c34
-rw-r--r--src/tools.h9
-rw-r--r--src/urlencoded.c83
16 files changed, 315 insertions, 380 deletions
diff --git a/examples/Makefile b/examples/Makefile
index 991f936..88af46d 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -3,7 +3,7 @@
# Debug mode (allowing to debug the examples via gdb):
# DEBUG = yes
# Examples to build by default:
-EXAMPLES = append cookie echo upload fastcgi
+EXAMPLES = append cookie echo upload
# Specify your favourite C compiler here (e.g. tcc):
CC = gcc
diff --git a/examples/append.c b/examples/append.c
index 3a32287..c6cfb2b 100644
--- a/examples/append.c
+++ b/examples/append.c
@@ -26,7 +26,7 @@ void response(magi_request *r)
"</html>");
}
-int main(int argc, char const *argv[])
+int main()
{
magi_request request;
magi_request_init(&request);
diff --git a/examples/cookie.c b/examples/cookie.c
index 7c55ba8..601c901 100644
--- a/examples/cookie.c
+++ b/examples/cookie.c
@@ -24,7 +24,7 @@ void response(magi_request *r)
magi_response(r, "</p></body></html>");
}
-int main(int argc, char const *argv[])
+int main()
{
magi_request request;
magi_request_init(&request);
diff --git a/examples/echo.c b/examples/echo.c
index e3b90c7..7c840e2 100644
--- a/examples/echo.c
+++ b/examples/echo.c
@@ -38,33 +38,29 @@ void list_files(magi_request *r)
for (current = r->files; current; current = current->next) {
magi_file *f = &current->item;
magi_response_format(r, "[%s] was [%s] on clientside<br/>",
- f->param_name, f->file_name);
+ f->field, f->filename);
}
}
void show_meta(magi_request *r)
{
- magi_response(r, "I was called with method [");
- magi_response(r, r->method);
- if (r->uri) {
- magi_response(r, "] with URL [");
- magi_response(r, r->uri);
- }
- if (r->server_name) {
- magi_response(r, "] for server [");
- magi_response(r, r->server_name);
+ magi_response(r, "I was called ");
+ if (r->is_secure) {
+ magi_response(r, "securely ");
}
- if (r->server_port) {
- magi_response(r, "] on port [");
- magi_response(r, r->server_port);
+ magi_response(r, "with method [");
+ magi_response(r, r->method);
+ if (r->host) {
+ magi_response(r, "] on server [");
+ magi_response(r, r->host);
}
- if (r->server_protocol) {
- magi_response(r, "] with protocol [");
- magi_response(r, r->server_protocol);
+ if (r->script) {
+ magi_response(r, "] being script on [");
+ magi_response(r, r->script);
}
- if (r->server_software) {
- magi_response(r, "] and I am running on software [");
- magi_response(r, r->server_software);
+ if (r->path) {
+ magi_response(r, "] with requested path [");
+ magi_response(r, r->path);
}
magi_response(r, "]<br/>");
}
@@ -85,13 +81,13 @@ void response(magi_request *r)
list_cookies(r);
magi_response(r, "<h2>Parameters:</h2>");
- list_params(r, r->params);
+ list_params(r, r->meta);
magi_response(r, "<h2>URL Parameters:</h2>");
- list_params(r, r->url_params);
+ list_params(r, r->head);
- magi_response(r, "<h2>HTTP Parameters:</h2>");
- list_params(r, r->http_params);
+ magi_response(r, "<h2>Body Parameters:</h2>");
+ list_params(r, r->body);
magi_response(r, "<h2>Files:</h2>");
list_files(r);
@@ -99,7 +95,7 @@ void response(magi_request *r)
magi_response(r, "</body></html>");
}
-int main(int argc, char const *argv[])
+int main()
{
magi_request request;
magi_request_init(&request);
diff --git a/examples/upload.c b/examples/upload.c
index 54d3a48..a8503ea 100644
--- a/examples/upload.c
+++ b/examples/upload.c
@@ -29,18 +29,17 @@ void response(magi_request *r)
void get(magi_request *r)
{
- magi_loadfiles rules;
- magi_loadfiles_init(&rules);
+ magi_loadfiles rules = { 0, 0 };
magi_loadfiles_add(&rules, "data", "data", 0);
- magi_loadfiles_set(&r, &rules);
- magi_cgi(&r);
+ magi_loadfiles_set(r, &rules);
+ magi_cgi(r);
magi_loadfiles_free(&rules);
}
-int main(int argc, char const *argv[])
+int main()
{
magi_request request;
- magi_request_init(request);
+ magi_request_init(&request);
get(&request);
if (request.error) {
magi_response_error(&request);
diff --git a/include/magi.h b/include/magi.h
index 0089878..a5b047d 100644
--- a/include/magi.h
+++ b/include/magi.h
@@ -8,6 +8,7 @@
#include "magi/error.h"
#include "magi/fastcgi.h"
#include "magi/file.h"
+#include "magi/loadfile.h"
#include "magi/param.h"
#include "magi/request.h"
#include "magi/response.h"
diff --git a/include/magi/response.h b/include/magi/response.h
index 52b1c9d..a9854d4 100644
--- a/include/magi/response.h
+++ b/include/magi/response.h
@@ -32,7 +32,9 @@ typedef struct magi_response_methods {
typedef struct magi_response_implementation {
const magi_response_methods *methods;
void *userdata;
- magi_params *head[3];
+ magi_params *head_response;
+ magi_params *head_general;
+ magi_params *head_entity;
int head_done;
} magi_response_implementation;
diff --git a/src/cgi.c b/src/cgi.c
index 00b0a06..291a57f 100644
--- a/src/cgi.c
+++ b/src/cgi.c
@@ -75,6 +75,9 @@ static void cgi_env(magi_request *r)
if (getenv("SERVER_PORT")) {
r->port = atoi(getenv("SERVER_PORT"));
r->is_secure = r->port == 443;
+ } else {
+ r->port = 0;
+ r->is_secure = 0;
}
r->path = plain_env("PATH_INFO");
}
@@ -191,13 +194,15 @@ static void setup_response(magi_request *r)
mfile,
mclose
};
- r->response = malloc(sizeof(*r->response));
- r->response->methods = &m;
- r->response->userdata = 0;
- r->response->head[0] = 0;
- r->response->head[1] = 0;
- r->response->head[2] = 0;
- r->response->head_done = 0;
+ r->response = malloc(sizeof(*r->response));
+ r->response->methods = &m;
+ r->response->userdata = 0;
+ r->response->head_response = 0;
+ r->response->head_general = 0;
+ r->response->head_entity = 0;
+ r->response->head_done = 0;
+ magi_response_content_type(r, "application/xhtml+xml");
+ magi_response_status(r, 200, "OK");
}
/* Interfacial CGI Request Handling */
diff --git a/src/cookies.c b/src/cookies.c
index 8b610d4..7e8248b 100644
--- a/src/cookies.c
+++ b/src/cookies.c
@@ -6,7 +6,7 @@
#include <string.h>
-enum st {
+typedef enum st {
st_error = 0,
st_pre_name,
st_name,
@@ -14,24 +14,24 @@ enum st {
st_pre_data,
st_data,
st_post_data
-};
+} st;
-enum data_type { dt_plain = 0, dt_version, dt_path, dt_domain };
+typedef enum dt { dt_plain = 0, dt_version, dt_path, dt_domain } dt;
-struct automata {
- struct magi_cookie_list ** list;
- struct magi_cookie cookie;
- char * buf;
- int buf_len;
- int buf_size;
- int is_first;
- int is_advanced;
- int is_quoted;
- enum data_type data_t;
-};
+typedef struct automata {
+ magi_cookies **list;
+ magi_cookie cookie;
+ char *buf;
+ int buf_len;
+ int buf_size;
+ int is_first;
+ int is_advanced;
+ int is_quoted;
+ dt datatype;
+} automata;
-static void nulify_cookie(struct automata * a)
+static void nulify_cookie(automata *a)
{
a->cookie.name = 0;
a->cookie.data = 0;
@@ -40,7 +40,7 @@ static void nulify_cookie(struct automata * a)
a->cookie.max_age = 0;
}
-static void buf_new(struct automata * a)
+static void buf_new(automata *a)
{
a->buf = 0;
a->buf_len = 0;
@@ -48,29 +48,28 @@ static void buf_new(struct automata * a)
}
-static enum data_type what_is_name(const struct automata * a)
+static dt what_is_name(const automata *a)
{
- enum data_type data_t = dt_plain;
+ dt datatype = dt_plain;
if (a->is_first && !strcmp(a->buf, "$Version")) {
- data_t = dt_version;
+ datatype = dt_version;
} else if (a->is_advanced) {
if (!strcmp(a->buf, "$Path")) {
- data_t = dt_path;
+ datatype = dt_path;
} else if (!strcmp(a->buf, "$Domain")) {
- data_t = dt_domain;
+ datatype = dt_domain;
}
}
- return data_t;
+ return datatype;
}
-static int end_name(struct automata * a)
+static void end_name(automata *a)
{
- int ok = 1;
- a->data_t = what_is_name(a);
- if (a->data_t == dt_plain) {
+ a->datatype = what_is_name(a);
+ if (a->datatype == dt_plain) {
if (a->cookie.name) {
- ok = magi_cookie_list_add(a->list, &a->cookie);
+ magi_cookies_add(a->list, &a->cookie);
}
nulify_cookie(a);
a->cookie.name = a->buf;
@@ -78,75 +77,56 @@ static int end_name(struct automata * a)
free(a->buf);
}
buf_new(a);
- return ok;
}
-static int end_data(struct automata * a)
+static int end_data(automata *a)
{
- int ok = 1;
- switch (a->data_t) {
- case dt_plain:
- a->cookie.data = a->buf;
- break;
- case dt_path:
- a->cookie.path = a->buf;
- break;
- case dt_domain:
- a->cookie.domain = a->buf;
- break;
- case dt_version:
- if (strcmp(a->buf, "1")) {
- ok = 0;
- }
+ switch (a->datatype) {
+ case dt_plain: a->cookie.data = a->buf; break;
+ case dt_path: a->cookie.path = a->buf; break;
+ case dt_domain: a->cookie.domain = a->buf; break;
+ case dt_version: if (strcmp(a->buf, "1")) { return 0; }
}
buf_new(a);
- return ok;
+ return 1;
}
-static enum st parse_pre_name(struct automata * a, char c)
+static st parse_pre_name(automata *a, char c)
{
- enum st state;
+ st state;
if (c == ' ' || c == '\t') {
state = st_name;
} else if (32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={}", c)) {
state = st_name;
- if (!magi_str_add(&a->buf, &a->buf_len, &a->buf_size, c)) {
- state = st_error;
- }
+ magi_str_add(&a->buf, &a->buf_len, &a->buf_size, c);
} else {
state = st_error;
}
return state;
}
-static enum st parse_name(struct automata * a, char c)
+static st parse_name(automata *a, char c)
{
- enum st state;
+ st state;
if (c == '=') {
state = st_pre_data;
- if (!end_name(a)) {
- state = st_error;
- }
+ end_name(a);
} else if (c == ' ' || c == '\t') {
state = st_post_name;
- if (!end_name(a)) {
- state = st_error;
- }
+ end_name(a);
} else if (32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={}", c)) {
state = st_name;
- if (!magi_str_add(&a->buf, &a->buf_len, &a->buf_size, c)) {
- state = st_error;
- }
+ magi_str_add(&a->buf, &a->buf_len, &a->buf_size, c);
} else {
state = st_error;
}
return state;
}
-static enum st parse_post_name(struct automata * a, char c)
+static st parse_post_name(automata *a, char c)
{
- enum st state;
+ st state;
if (c == '=') {
state = st_pre_data;
} else if (c == ' ' || c == '\t') {
@@ -157,9 +137,9 @@ static enum st parse_post_name(struct automata * a, char c)
return state;
}
-static enum st parse_pre_data(struct automata * a, char c)
+static st parse_pre_data(automata *a, char c)
{
- enum st state;
+ st state;
if (c == ' ' || c == '\t') {
state = st_pre_data;
} else if (c == '"') {
@@ -167,18 +147,16 @@ static enum st parse_pre_data(struct automata * a, char c)
a->is_quoted = 1;
} else if (32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={}", c)) {
state = st_data;
- if (!magi_str_add(&a->buf, &a->buf_len, &a->buf_size, c)) {
- state = st_error;
- }
+ magi_str_add(&a->buf, &a->buf_len, &a->buf_size, c);
} else {
state = st_error;
}
return state;
}
-static enum st parse_not_quoted_data(struct automata * a, char c)
+static st parse_not_quoted_data(automata *a, char c)
{
- enum st state;
+ st state;
if (c == ';' || (c == ',' && a->is_first)) {
state = st_pre_name;
a->is_first = 0;
@@ -192,18 +170,16 @@ static enum st parse_not_quoted_data(struct automata * a, char c)
}
} else if (32 <= c && c <= 126 && !strchr("()<>@,;:\\\"/[]?={}", c)) {
state = st_data;
- if (!magi_str_add(&a->buf, &a->buf_len, &a->buf_size, c)) {
- state = st_error;
- }
+ magi_str_add(&a->buf, &a->buf_len, &a->buf_size, c);
} else {
state = st_error;
}
return state;
}
-static enum st parse_data(struct automata * a, char c)
+static st parse_data(automata *a, char c)
{
- enum st state;
+ st state;
if (a->is_quoted) {
if (c == '"') {
state = st_post_data;
@@ -220,9 +196,9 @@ static enum st parse_data(struct automata * a, char c)
return state;
}
-static enum st parse_post_data(struct automata * a, char c)
+static st parse_post_data(automata *a, char c)
{
- enum st state;
+ st state;
if (c == ';' || (c == ',' && a->is_first)) {
state = st_pre_name;
} else if (c == ' ' || c == '\t') {
@@ -234,14 +210,15 @@ static enum st parse_post_data(struct automata * a, char c)
}
-static void parse_end(enum magi_error * e, struct automata * a, enum st s)
+static void parse_end(magi_error *e, automata *a, st s)
{
if (s == st_data) {
if (a->is_quoted || !a->cookie.name) {
*e = magi_error_cookies;
return;
}
- if (end_data(a) && magi_cookie_list_add(a->list, &a->cookie)) {
+ if (end_data(a)) {
+ magi_cookies_add(a->list, &a->cookie);
nulify_cookie(a);
} else {
*e = magi_error_cookies;
@@ -252,33 +229,21 @@ static void parse_end(enum magi_error * e, struct automata * a, enum st s)
}
-void magi_cookies(struct magi_request * request, const char * data)
+void magi_parse_cookies(magi_request *request, const char *data)
{
- enum st state;
- struct automata a = { 0, { 0, 0, 0, 0, 0 }, 0, 0, 1, 1, 0, 0, 0 };
- a.list = &request->cookies;
- request->cookies = 0;
+ st state;
+ automata a = { 0, { 0, 0, 0, 0, 0 }, 0, 0, 0, 1, 0, 0, 0 };
+ a.list = &request->cookies;
+ request->cookies = 0;
for (state = st_pre_name; state && *data; ++data) {
switch (state) {
- case st_pre_name:
- state = parse_pre_name(&a, *data);
- break;
- case st_name:
- state = parse_name(&a, *data);
- break;
- case st_post_name:
- state = parse_post_name(&a, *data);
- break;
- case st_pre_data:
- state = parse_pre_data(&a, *data);
- break;
- case st_data:
- state = parse_data(&a, *data);
- break;
- case st_post_data:
- state = parse_post_data(&a, *data);
- default:
- break;
+ case st_pre_name: state = parse_pre_name(&a, *data); break;
+ case st_name: state = parse_name(&a, *data); break;
+ case st_post_name: state = parse_post_name(&a, *data); break;
+ case st_pre_data: state = parse_pre_data(&a, *data); break;
+ case st_data: state = parse_data(&a, *data); break;
+ case st_post_data: state = parse_post_data(&a, *data); break;
+ default: break;
}
}
parse_end(&request->error, &a, state);
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);
diff --git a/src/param.c b/src/param.c
index 42785fc..dd89a48 100644
--- a/src/param.c
+++ b/src/param.c
@@ -10,7 +10,18 @@ void magi_params_add(magi_params **params, magi_param *newitem)
if (node) {
node->next = *params;
node->item = *newitem;
- *params = node;
+ *params = node;
+ }
+}
+
+void magi_params_set(magi_params **params, magi_param *newitem)
+{
+ if (!*params) {
+ magi_params_add(params, newitem);
+ } else if (!strcmp((*params)->item.name, newitem->name)) {
+ (*params)->item.data = newitem->data;
+ } else {
+ magi_params_set(&(*params)->next, newitem);
}
}
diff --git a/src/request.c b/src/request.c
index 4132458..41b77fe 100644
--- a/src/request.c
+++ b/src/request.c
@@ -56,12 +56,12 @@ void magi_request_free(magi_request *request)
magi_files_free(request->files);
request->response->methods->close(request->response->userdata);
free(request->response->userdata);
- magi_params_free(request->response->head[0]);
- magi_params_free(request->response->head[1]);
- magi_params_free(request->response->head[2]);
- free(request->response->head[0]);
- free(request->response->head[1]);
- free(request->response->head[2]);
+ magi_params_free(request->response->head_response);
+ magi_params_free(request->response->head_general);
+ magi_params_free(request->response->head_entity);
+ free(request->response->head_response);
+ free(request->response->head_general);
+ free(request->response->head_entity);
request_free(request);
request_annul(request);
}
diff --git a/src/response.c b/src/response.c
index aea64b4..d7d2c86 100644
--- a/src/response.c
+++ b/src/response.c
@@ -21,7 +21,7 @@ void magi_response_status(magi_request *r, int code, const char *description)
addon.data[2] = '0' + code % 10;
addon.data[3] = ' ';
memcpy(addon.data + 4, description, dlen + 1);
- magi_params_set(r->response->head, &addon);
+ magi_params_set(&r->response->head_response, &addon);
}
void magi_response_cookie(magi_request *r, const char *name, const char *data)
@@ -32,7 +32,7 @@ void magi_response_cookie(magi_request *r, const char *name, const char *data)
}
addon.name = magi_str_create_copy("Set-Cookie", 10);
/* TODO */
- magi_params_add(r->response->head + 1, &addon);
+ magi_params_add(&r->response->head_general, &addon);
}
void magi_response_cookie_complex(magi_request *r, magi_cookie *c)
@@ -43,7 +43,7 @@ void magi_response_cookie_complex(magi_request *r, magi_cookie *c)
}
addon.name = magi_str_create_copy("Set-Cookie", 10);
/* TODO */
- magi_params_add(r->response->head + 1, &addon);
+ magi_params_add(&r->response->head_general, &addon);
}
void magi_response_cookie_discard(magi_request *r, const char *name)
@@ -54,7 +54,7 @@ void magi_response_cookie_discard(magi_request *r, const char *name)
}
addon.name = magi_str_create_copy("Set-Cookie", 10);
/* TODO */
- magi_params_add(r->response->head + 1, &addon);
+ magi_params_add(&r->response->head_general, &addon);
}
void magi_response_header(magi_request *r, const char *name, const char *data)
@@ -65,7 +65,7 @@ void magi_response_header(magi_request *r, const char *name, const char *data)
}
addon.name = magi_str_create_copy(name, strlen(name));
addon.data = magi_str_create_copy(data, strlen(data));
- magi_params_add(r->response->head + 1, &addon);
+ magi_params_add(&r->response->head_general, &addon);
}
void magi_response_content_length(magi_request *r, int length)
@@ -85,18 +85,18 @@ void magi_response_content_length(magi_request *r, int length)
++len;
}
addon.data[len] = 0;
- magi_params_set(r->response->head + 2, &addon);
+ magi_params_set(&r->response->head_entity, &addon);
}
void magi_response_content_type(magi_request *r, const char *type)
{
magi_param addon;
- if (r->response->head_done) {
+ if (r->response->head_done || !type) {
return;
}
addon.name = magi_str_create_copy("Content-Type", 12);
addon.data = magi_str_create_copy(type, strlen(type));
- magi_params_set(r->response->head + 2, &addon);
+ magi_params_set(&r->response->head_entity, &addon);
}
static void response_headers(magi_response_implementation *r, magi_params *p)
@@ -108,13 +108,12 @@ static void response_headers(magi_response_implementation *r, magi_params *p)
void magi_response_head(magi_request *r)
{
- magi_params *current;
if (r->response->head_done) {
return;
}
- response_headers(r->response, r->response->head[0]);
- response_headers(r->response, r->response->head[1]);
- response_headers(r->response, r->response->head[2]);
+ response_headers(r->response, r->response->head_response);
+ response_headers(r->response, r->response->head_general);
+ response_headers(r->response, r->response->head_entity);
r->response->methods->start_body(r->response->userdata);
r->response->head_done = 1;
}
@@ -122,6 +121,9 @@ void magi_response_head(magi_request *r)
void magi_response(magi_request *r, const char *addon)
{
magi_response_head(r);
+ if (!addon) {
+ return;
+ }
r->response->methods->body(r->response->userdata, addon, strlen(addon));
}
diff --git a/src/tools.c b/src/tools.c
index d7a90ce..d6170bc 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -19,37 +19,27 @@ char *magi_str_lowercase(char *str)
char *magi_str_create_copy(const char *first, int len)
{
char *copy = magi_str_create(len);
- if (copy) {
- memcpy(copy, first, len);
- }
+ memcpy(copy, first, len);
return copy;
}
char *magi_str_create(int len)
{
char *str = malloc(len + 1);
- if (str) {
- str[len] = 0;
- }
+ str[len] = 0;
return str;
}
-int magi_str_add(magi_str *str, char c)
+void magi_str_add(char **str, int *len, int *size, char c)
{
- if (!str->data) {
- str->len = 0;
- str->size = 2;
- str->data = malloc(2);
- } else if (str->len + 1 == str->size) {
- str->size *= 2;
- str->data = realloc(str->data, str->size);
- }
- if (!str->dest) {
- str->len = 0;
- str->size = 0;
- return 0;
+ if (!*str) {
+ *len = 0;
+ *size = 2;
+ *str = malloc(2);
+ } else if (*len + 1 == *size) {
+ *size *= 2;
+ *str = realloc(*str, *size);
}
- str->data[str->len++] = c;
- str->data[str->len] = 0;
- return 1;
+ *str[*len] = c;
+ *str[++*len] = 0;
}
diff --git a/src/tools.h b/src/tools.h
index 49513e8..0152f35 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -8,14 +8,7 @@ char *magi_str_lowercase(char *str);
char *magi_str_create_copy(const char *first, int len);
char *magi_str_create(int len);
-
-typedef struct magi_str {
- char *data;
- int size;
- int len;
-} magi_str;
-
-int magi_str_add(magi_str *str, char c);
+void magi_str_add(char **str, int *len, int *size, char c);
#endif
diff --git a/src/urlencoded.c b/src/urlencoded.c
index 9d596ed..4f9efe8 100644
--- a/src/urlencoded.c
+++ b/src/urlencoded.c
@@ -61,76 +61,77 @@ static int deurl(char **data)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Urlencoded Automata
*/
-typedef struct automata {
- magi_param_list **list;
- magi_str name;
- magi_str data;
-} automata;
-typedef void *(*state)(automata *a, char c);
+typedef struct automata automata;
+typedef void (*state)(automata *a, char c);
+struct automata {
+ state s;
+ magi_params **list;
+ char *name;
+ int nlen;
+ int nsize;
+ char *data;
+ int dlen;
+ int dsize;
+};
-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 == ';') {
- return 0;
+ a->s = 0;
+ return;
}
if (c == '=') {
- if (!deurl(&a->name.data)) {
- return 0;
+ if (!deurl(&a->name)) {
+ a->s = 0;
+ return;
}
- return state_parse_name;
+ a->s = state_parse_data;
}
- magi_str_add(&a->name, c);
- return a->name.size ? state_parse_name : 0;
+ magi_str_add(&a->name, &a->nlen, &a->nsize, c);
}
-static int add_to_list(automata *a)
+static void add_to_list(automata *a)
{
magi_param param;
- param.name = a->name.data;
- param.data = a->data.data;
- if (!magi_param_list_add(a->list, param)) {
- return 0;
- }
- a->name.data = 0;
- a->data.data = 0;
- return 1;
+ param.name = a->name;
+ param.data = a->data;
+ magi_params_add(a->list, &param);
+ a->name = 0;
+ a->data = 0;
}
static void state_parse_data(automata *a, char c)
{
if (c == '=') {
- return 0;
+ a->s = 0;
+ return;
}
if (c == '&' || c == ';') {
- if (!deurl(&a->data.data) || !add_to_list(a)) {
- return 0;
+ if (!deurl(&a->data)) {
+ a->s = 0;
+ return;
}
- return state_parse_name;
+ add_to_list(a);
+ a->s = state_parse_name;
}
- magi_str_add(&a->data, c);
- return a->data.size ? state_parse_data : 0;
+ magi_str_add(&a->data, &a->dlen, &a->dsize, c);
}
-magi_error magi_urlencoded(magi_param_list **list, const char *encoded)
+magi_error magi_parse_urlencoded(magi_params **list, const char *encoded)
{
- st state;
- automata a = { 0, { 0, 0 }, 1, 0 };
+ automata a = { state_parse_name, 0, 0, 0, 0, 0, 0, 0 };
a.list = list;
*list = 0;
if (!encoded || !*encoded) {
return 0;
}
- for (; *encoded; ++encoded) {
- s = s(&a, *encoded);
- if (!s) {
- return auto_free(a);
- }
+ for (; *encoded && a.s; ++encoded) {
+ a.s(&a, *encoded);
}
- if (state == st_name || !state || !end_data(&a)) {
- free(a.param.name);
- free(a.param.data);
- return auto_free(a);
+ if (a.s == state_parse_name || !a.s || !deurl(&a.data)) {
+ return magi_error_urlenc;
}
+ add_to_list(&a);
return 0;
}