aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--examples/append.c4
-rw-r--r--include/magi/cookie.h5
-rw-r--r--include/magi/error.h22
-rw-r--r--include/magi/response.h11
l---------man/libmagi.31
-rw-r--r--man/magi.369
-rw-r--r--man/magi_cookie.30
-rw-r--r--man/magi_error.30
-rw-r--r--man/magi_file.30
-rw-r--r--man/magi_loadfiles.30
-rw-r--r--man/magi_param.30
-rw-r--r--man/magi_parse.30
-rw-r--r--man/magi_request.30
-rw-r--r--man/magi_response.30
-rw-r--r--man/magi_urlenc.30
-rw-r--r--src/cookie.c33
-rw-r--r--src/cookies.c103
-rw-r--r--src/error.c1
-rw-r--r--src/multipart.c120
-rw-r--r--src/urlenc.c6
-rw-r--r--src/urlencoded.c46
22 files changed, 255 insertions, 170 deletions
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 <magi.h>
#include <stdio.h>
@@ -26,7 +26,7 @@ void response(magi_request *r)
"<body>");
append(r);
printf("<form action='/cgi-bin/append' method='post'><fieldset>"
- "<input type='text' name='addon' value='Whatever you want to add.' />"
+ "<input type='text' name='addon' value='Enter your addon.' />"
"<input type='submit' value='Append' />"
"</fieldset></form>"
"</body></html>");
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 <stdarg.h>
+/* 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 <magi.h>
+.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
--- /dev/null
+++ b/man/magi_cookie.3
diff --git a/man/magi_error.3 b/man/magi_error.3
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/man/magi_error.3
diff --git a/man/magi_file.3 b/man/magi_file.3
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/man/magi_file.3
diff --git a/man/magi_loadfiles.3 b/man/magi_loadfiles.3
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/man/magi_loadfiles.3
diff --git a/man/magi_param.3 b/man/magi_param.3
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/man/magi_param.3
diff --git a/man/magi_parse.3 b/man/magi_parse.3
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/man/magi_parse.3
diff --git a/man/magi_request.3 b/man/magi_request.3
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/man/magi_request.3
diff --git a/man/magi_response.3 b/man/magi_response.3
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/man/magi_response.3
diff --git a/man/magi_urlenc.3 b/man/magi_urlenc.3
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/man/magi_urlenc.3
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 <string.h>
+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);