diff options
author | Aleksey Veresov <aleksey@veresov.pro> | 2019-11-15 18:01:45 +0300 |
---|---|---|
committer | Aleksey Veresov <aleksey@veresov.pro> | 2019-11-15 18:01:45 +0300 |
commit | 32c1fbd2cf779a65e807d0d82412ffffa2401962 (patch) | |
tree | bb0020c18a72c4622e68258d8911956ecaca3765 | |
parent | e6d5f9552e66ee2db3056e810b58b2bf82551356 (diff) | |
download | magi-32c1fbd2cf779a65e807d0d82412ffffa2401962.tar magi-32c1fbd2cf779a65e807d0d82412ffffa2401962.tar.xz magi-32c1fbd2cf779a65e807d0d82412ffffa2401962.zip |
[magi]
-rw-r--r-- | examples/append.c | 64 | ||||
-rw-r--r-- | examples/cookie.c | 12 | ||||
-rw-r--r-- | examples/echo.c | 29 | ||||
-rw-r--r-- | examples/fcgi.c | 21 | ||||
-rw-r--r-- | examples/upload.c | 65 | ||||
-rw-r--r-- | src/cgi.c | 87 | ||||
-rw-r--r-- | src/cgi.h | 9 | ||||
-rw-r--r-- | src/cookie.c | 43 | ||||
-rw-r--r-- | src/cookie.h | 4 | ||||
-rw-r--r-- | src/error.c | 78 | ||||
-rw-r--r-- | src/error.h | 8 | ||||
-rw-r--r-- | src/field.c | 12 | ||||
-rw-r--r-- | src/field.h | 8 | ||||
-rw-r--r-- | src/multipart.c | 40 | ||||
-rw-r--r-- | src/param.c | 12 | ||||
-rw-r--r-- | src/param.h | 8 | ||||
-rw-r--r-- | src/request.h | 1 | ||||
-rw-r--r-- | src/urlencoded.c | 18 | ||||
-rw-r--r-- | src/utils.c | 7 |
19 files changed, 260 insertions, 266 deletions
diff --git a/examples/append.c b/examples/append.c index 0c7df7e..e51745a 100644 --- a/examples/append.c +++ b/examples/append.c @@ -4,46 +4,42 @@ #include <stdlib.h> -void handle_request() +void response_request(struct magi_request * req, struct magi_response * res) +{ + magi_response_content_type(res, magi_xhtml); + magi_response_content( + res, + "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' " + "'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>" + "<html xmlns='http://www.w3.org/1999/xhtml'>" + "<head><title>Append to File</title></head>" + "<body>" + "<form action='/cgi-bin/append' method='get'><fieldset>" + "<input type='text' name='addon' value='Whatever you want to add.'/>" + "<input type='submit' value='Append'/>" + "</fieldset></form>" + "</body>" + "</html>"); + + struct magi_field * a = magi_field_list_get(req->fields, "addon"); + if (a && a->data) { + FILE * file = fopen("file_to_append", "a"); + fputs(a->data, file); + fclose(file); + } +} + +int main(int argc, char const * argv[]) { struct magi_request request; if (magi_cgi(&request, 0, 0)) { - struct magi_field * a = magi_field_list_get(request.fields, "addon"); - if (a && a->data) { - FILE * file = fopen("file_to_append", "a"); - fputs(a->data, file); - fclose(file); - } + struct magi_response response; + response_request(&request, &response); + magi_cgi_response(&response); + magi_response_destroy(); } else { magi_cgi_error(request.error); } magi_request_destroy(&request); -} - -void print_preamble() -{ - puts("Content-type: application/xhtml+xml\r\n\r\n"); -} - -void print_webpage() -{ - puts("<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' " - "'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>" - "<html xmlns='http://www.w3.org/1999/xhtml'>" - "<head><title>Append to File</title></head>" - "<body>" - "<form action='/cgi-bin/append' method='get'><fieldset>" - "<input type='text' name='addon' value='Whatever you want to add.'/>" - "<input type='submit' value='Append'/>" - "</fieldset></form>" - "</body>" - "</html>"); -} - -int main(int argc, char const * argv[]) -{ - handle_request(); - print_preamble(); - print_webpage(); return 0; } diff --git a/examples/cookie.c b/examples/cookie.c index a2b9425..47929cb 100644 --- a/examples/cookie.c +++ b/examples/cookie.c @@ -11,12 +11,12 @@ void response_request(struct magi_request * req, struct magi_response * res) struct magi_cookie_list * cookie; magi_response_content_type(res, magi_xhtml); - magi_response_content(res, - "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' " - "'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>" - "<html xmlns='http://www.w3.org/1999/xhtml'>" - "<head><title>Cookie Listing and Setting</title></head>" - "<body>"); + magi_response_content( + res, "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' " + "'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>" + "<html xmlns='http://www.w3.org/1999/xhtml'>" + "<head><title>Cookie Listing and Setting</title></head>" + "<body>"); for (cookie = req->cookies; cookie; cookie = cookie->next) { printf("[%s] = [%s]<br/>", cookie->item.name, cookie->item.data); diff --git a/examples/echo.c b/examples/echo.c index 853e6ce..6901b71 100644 --- a/examples/echo.c +++ b/examples/echo.c @@ -6,8 +6,8 @@ #include <stdlib.h> -void proceed_cookies( - struct magi_cookie_list * cookies, struct magi_response * response) +void proceed_cookies(struct magi_cookie_list * cookies, + struct magi_response * response) { magi_response_content(response, "<h2>Cookies:</h2>"); while (cookies) { @@ -35,8 +35,8 @@ void proceed_cookies( magi_response_content(response, "<hr/>"); } -void proceed_fields( - struct magi_field_list * fields, struct magi_response * response) +void proceed_fields(struct magi_field_list * fields, + struct magi_response * response) { magi_response_content(response, "<h2>Feilds:</h2>"); while (fields) { @@ -50,8 +50,8 @@ void proceed_fields( magi_response_content(response, "<hr/>"); } -void proceed_params( - struct magi_param_list * params, struct magi_response * response) +void proceed_params(struct magi_param_list * params, + struct magi_response * response) { magi_response_content(response, "<h2>HTTP Parameters:</h2>"); while (params) { @@ -67,9 +67,8 @@ void proceed_params( void process_meta(struct magi_request * req, struct magi_response * res) { - magi_response_content(res, - "<h1>Echo CGI Script</h1>" - "I was called with method ["); + magi_response_content(res, "<h1>Echo CGI Script</h1>" + "I was called with method ["); magi_response_content(res, req->method); if (req->uri) { magi_response_content(res, "] with URL ["); @@ -97,12 +96,12 @@ void process_meta(struct magi_request * req, struct magi_response * res) void response_request(struct magi_request * req, struct magi_response * res) { magi_response_content_type(res, magi_xhtml); - magi_response_content(res, - "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' " - "'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>" - "<html xmlns='http://www.w3.org/1999/xhtml'>" - "<head><title>Echo</title></head>" - "<body>"); + magi_response_content( + res, "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' " + "'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>" + "<html xmlns='http://www.w3.org/1999/xhtml'>" + "<head><title>Echo</title></head>" + "<body>"); process_meta(req, res); proceed_cookies(req->cookies, res); proceed_fields(req->fields, res); diff --git a/examples/fcgi.c b/examples/fcgi.c index 5972cdd..9cdbe90 100644 --- a/examples/fcgi.c +++ b/examples/fcgi.c @@ -1,3 +1,4 @@ +#include <error.h> #include <fastcgi.h> #include <request.h> #include <stdio.h> @@ -8,13 +9,13 @@ void response_request(struct magi_request * req, struct magi_resopnse * res) { magi_response_content_type(res, magi_xhtml); - magi_response_content(res, - "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' " - "'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>" - "<html xmlns='http://www.w3.org/1999/xhtml'>" - "<head><title>Fast CGI</title></head>" - "<body>Hi!</body>" - "</html>"); + magi_response_content( + res, "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' " + "'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>" + "<html xmlns='http://www.w3.org/1999/xhtml'>" + "<head><title>Fast CGI</title></head>" + "<body>Hi!</body>" + "</html>"); } int main(int argc, char const * argv[]) @@ -22,7 +23,7 @@ int main(int argc, char const * argv[]) struct magi_session session; if (magi_fcgi(&session)) { struct magi_request request; - while (magi_accept(&request, &session)) { + while (magi_fcgi_accept(&request, &session)) { if (!request.error) { struct magi_response response; response_request(&request, &response); @@ -33,8 +34,8 @@ int main(int argc, char const * argv[]) } magi_request_destroy(&request); } - /* Fast CGI session error */ } - /* Fast CGI session error */ + puts(session.error->message); + magi_session_destroy(&session); return 0; } diff --git a/examples/upload.c b/examples/upload.c index 06a3cf9..5fe3338 100644 --- a/examples/upload.c +++ b/examples/upload.c @@ -29,47 +29,42 @@ void tempfile_callback(struct magi_field * field, char * buffer, int len) } } -void handle_request() +void response_request(struct magi_request * req, struct magi_response * res) +{ + magi_response_content_type(res, magi_xhtml); + magi_response_content( + res, "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' " + "'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>" + "<html xmlns='http://www.w3.org/1999/xhtml'>" + "<head><title>Upload File</title></head>" + "<body>" + "<form action='/cgi-bin/upload' method='post' " + "enctype='multipart/form-data'><fieldset>" + "<input type='text' name='name' value='filename'/>" + "<input type='file' name='data'/>" + "<input type='submit' value='Upload'/>" + "</fieldset></form>" + "</body>" + "</html>"); + + struct magi_field * name = magi_field_list_get(req->fields, "name"); + struct magi_field * data = magi_field_list_get(req->fields, "data"); + if (name && name->data && data) { + rename("data", name->data); + } +} + +int main(int argc, char const * argv[]) { struct magi_request request; if (magi_cgi(&request, tempfile_callback, 0)) { - struct magi_field * name = magi_field_list_get(request.fields, "name"); - struct magi_field * data = magi_field_list_get(request.fields, "data"); - if (name && name->data && data) { - rename("data", name->data); - } + struct magi_response response; + response_request(&request, &response); + magi_cgi_response(&response); + magi_response_destroy(); } else { magi_cgi_error(request.error); } magi_request_destroy(&request); -} - -void print_preamble() -{ - puts("Content-type: application/xhtml+xml\r\n\r\n"); -} - -void print_webpage() -{ - puts("<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' " - "'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>" - "<html xmlns='http://www.w3.org/1999/xhtml'>" - "<head><title>Upload File</title></head>" - "<body>" - "<form action='/cgi-bin/upload' method='post' " - "enctype='multipart/form-data'><fieldset>" - "<input type='text' name='name' value='filename'/>" - "<input type='file' name='data'/>" - "<input type='submit' value='Upload'/>" - "</fieldset></form>" - "</body>" - "</html>"); -} - -int main(int argc, char const * argv[]) -{ - handle_request(); - print_preamble(); - print_webpage(); return 0; } @@ -1,8 +1,8 @@ #include "cgi.h" #include "cookie.h" +#include "error.h" #include "field.h" -#include "log.h" #include "multipart.h" #include "param.h" #include "request.h" @@ -14,6 +14,7 @@ extern char ** environ; + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * CGI Request Handling */ @@ -73,37 +74,35 @@ static int cgi_http_env(struct magi_request * r) return ok; } -static int cgi_env(struct magi_request * r) +static void cgi_env(struct magi_error ** e, struct magi_request * r) { - int ok = cgi_http_env(r); - ok = ok && lower_env(&r->method, "REQUEST_METHOD"); - ok = ok && plain_env(&r->uri, "REQUEST_URI"); - ok = ok && plain_env(&r->document_root, "DOCUMENT_ROOT"); - ok = ok && plain_env(&r->document_uri, "DOCUMENT_URI"); - ok = ok && plain_env(&r->script_name, "SCRIPT_NAME"); - ok = ok && plain_env(&r->script_filename, "SCRIPT_FILENAME"); - ok = ok && plain_env(&r->remote_addr, "REMOTE_ADDR"); - ok = ok && plain_env(&r->remote_port, "REMOTE_PORT"); - ok = ok && plain_env(&r->server_addr, "SERVER_ADDR"); - ok = ok && lower_env(&r->server_name, "SERVER_NAME"); - ok = ok && plain_env(&r->server_port, "SERVER_PORT"); - ok = ok && lower_env(&r->server_protocol, "SERVER_PROTOCOL"); - ok = ok && plain_env(&r->server_software, "SERVER_SOFTWARE"); - ok = ok && plain_env(&r->path_info, "PATH_INFO"); - return ok; + cgi_http_env(e, r); + lower_env(e, &r->method, "REQUEST_METHOD"); + plain_env(e, &r->uri, "REQUEST_URI"); + plain_env(e, &r->document_root, "DOCUMENT_ROOT"); + plain_env(e, &r->document_uri, "DOCUMENT_URI"); + plain_env(e, &r->script_name, "SCRIPT_NAME"); + plain_env(e, &r->script_filename, "SCRIPT_FILENAME"); + plain_env(e, &r->remote_addr, "REMOTE_ADDR"); + plain_env(e, &r->remote_port, "REMOTE_PORT"); + plain_env(e, &r->server_addr, "SERVER_ADDR"); + lower_env(e, &r->server_name, "SERVER_NAME"); + plain_env(e, &r->server_port, "SERVER_PORT"); + lower_env(e, &r->server_protocol, "SERVER_PROTOCOL"); + plain_env(e, &r->server_software, "SERVER_SOFTWARE"); + plain_env(e, &r->path_info, "PATH_INFO"); } -static int cgi_cookies(struct magi_cookie_list ** list) +static void cgi_cookies(struct magi_error ** e, + struct magi_cookie_list ** list) { - int ok = 1; const char * env = getenv("HTTP_COOKIE"); *list = 0; if (env && *env) { - ok = magi_parse_cookie(list, env); + magi_parse_cookie(e, list, env); } else { *list = 0; } - return ok; } static int cgi_input_get(char ** input) @@ -130,7 +129,7 @@ static int cgi_input_post(char ** input, int max) if (*input) { if (fread(*input, 1, input_len, stdin) != input_len) { ok = 0; - magi_log("[request:cgi] Content-length is not correct."); + magi_error_set("[request:cgi] Content-length is not correct."); } } else { ok = 0; @@ -162,11 +161,15 @@ static int intput_getter(void * any) /* Interfacial CGI Request Handling */ int magi_cgi_request(struct magi_request * request, - void (*callback)(struct magi_field * field, char * buffer, int len), - int max_post) + void (*callback)(struct magi_field * field, char * buffer, + int len), + int max_post) { - int ok = cgi_env(request) && cgi_cookies(&request->cookies); - request->fields = 0; + request->fields = 0; + request->error = 0; + struct magi_error ** e = &request->error; + cgi_env(e, request); + cgi_cookies(e, &request->cookies); if (request->method) { if (!strcmp(request->method, "post")) { const char * t = getenv("CONTENT_TYPE"); @@ -174,37 +177,31 @@ int magi_cgi_request(struct magi_request * request, if (!strncmp(t, "multipart/form-data", 19)) { char * boundary = bound(t); if (boundary && *boundary) { - ok = magi_parse_multipart(&request->fields, - intput_getter, 0, boundary, callback); + magi_parse_multipart(e, &request->fields, + intput_getter, 0, boundary, + callback); } else { - ok = 0; - magi_log("[request:cgi] Multipart bound is not set."); + magi_error_add( + e, "[request:cgi] Multipart bound is not set."); } free(boundary); } else if (!strcmp(t, "application/x-www-form-urlencoded")) { char * in = 0; - ok = cgi_input_post(&in, max_post); - if (ok) { - ok = magi_parse_urlencoded(&request->fields, in); - } + cgi_input_post(e, &in, max_post); + magi_parse_urlencoded(e, &request->fields, in); free(in); } else { - ok = 0; - magi_log("[request:cgi] Unknown content type."); + magi_error_add(e, "[request:cgi] Unknown content type."); } } else { - ok = 0; - magi_log("[request:cgi] Content-type is not set."); + magi_error_add(e, "[request:cgi] Content-type is not set."); } } else if (!strcmp(request->method, "get")) { char * in = 0; - ok = cgi_input_get(&in); - ok = ok && magi_parse_urlencoded(&request->fields, in); + cgi_input_get(e, &in); + magi_parse_urlencoded(e, &request->fields, in); free(in); } } - if (!ok) { - magi_request_destroy(request); - } - return ok; + return !request->error; } @@ -10,10 +10,11 @@ * Returns null if succeed, otherwise error code. */ int magi_cgi(struct magi_request * request, - /* Callback will be used only for fields loaded via multipart. */ - /* Null callback disables callback system. */ - void (*callback)(struct magi_field * field, char * buffer, int len), - int max_post); + /* Callback will be used only for fields loaded via multipart. */ + /* Null callback disables callback system. */ + void (*callback)(struct magi_field * field, char * buffer, + int len), + int max_post); #endif diff --git a/src/cookie.c b/src/cookie.c index 8926d40..d04eccf 100644 --- a/src/cookie.c +++ b/src/cookie.c @@ -1,6 +1,6 @@ #include "cookie.h" -#include "log.h" +#include "error.h" #include <stdlib.h> #include <string.h> @@ -61,7 +61,7 @@ static int buf_add(struct automata * a, char c) a->buf[a->buf_len] = 0; } else { ok = 0; - magi_log("[cookie] Cannot allocate automata buffer."); + magi_error_set("[cookie] Cannot allocate automata buffer."); } return ok; } @@ -119,7 +119,8 @@ static int end_data(struct automata * a) case dt_version: if (strcmp(a->buf, "1")) { ok = 0; - magi_log("[cookie] Version must be '1', readed: %s.", a->buf); + magi_error_set("[cookie] Version must be '1', readed: %s.", + a->buf); } } buf_new(a); @@ -138,7 +139,7 @@ static enum st parse_pre_name(struct automata * a, char c) } } else { state = st_error; - magi_log("[cookie] Pre-name, readed: \\%o (render: %c).", c, c); + magi_error_set("[cookie] Pre-name, readed: \\%o (render: %c).", c, c); } return state; } @@ -163,7 +164,8 @@ static enum st parse_name(struct automata * a, char c) } } else { state = st_error; - magi_log("[cookie] Reading name, readed: \\%o (render: %c).", c, c); + magi_error_set("[cookie] Reading name, readed: \\%o (render: %c).", c, + c); } return state; } @@ -177,9 +179,9 @@ static enum st parse_post_name(struct automata * a, char c) state = st_post_name; } else { state = st_error; - magi_log("[cookie] Waiting for name-value separator, " - "readed: \\%o (render: %c).", - c, c); + magi_error_set("[cookie] Waiting for name-value separator, " + "readed: \\%o (render: %c).", + c, c); } return state; } @@ -199,7 +201,7 @@ static enum st parse_pre_data(struct automata * a, char c) } } else { state = st_error; - magi_log("[cookie] Pre-value, readed: \\%o (render: %c).", c, c); + magi_error_set("[cookie] Pre-value, readed: \\%o (render: %c).", c, c); } return state; } @@ -225,9 +227,9 @@ static enum st parse_not_quoted_data(struct automata * a, char c) } } else { state = st_error; - magi_log("[cookie] Reading not-quoted value, " - "readed: \\%o (render: %c).", - c, c); + magi_error_set("[cookie] Reading not-quoted value, " + "readed: \\%o (render: %c).", + c, c); } return state; } @@ -260,8 +262,9 @@ static enum st parse_post_data(struct automata * a, char c) state = st_post_data; } else { state = st_error; - magi_log("[cookie] Waiting for separator between name-value pairs, " - "readed: \\%o (render: %c).", + magi_error_set( + "[cookie] Waiting for separator between name-value pairs, " + "readed: \\%o (render: %c).", c, c); } return state; @@ -281,13 +284,13 @@ static int parse_end(struct automata * a, enum st s) buf_new(a); } } else { - magi_log("[cookie] No cookies set."); + magi_error_set("[cookie] No cookies set."); } } else { - magi_log("[cookie] In quotation when reached input end."); + magi_error_set("[cookie] In quotation when reached input end."); } } else if (s != st_error) { - magi_log("[cookie] Input ended in not correct state."); + magi_error_set("[cookie] Input ended in not correct state."); } free(a->cookie.name); free(a->cookie.data); @@ -334,8 +337,8 @@ int magi_parse_cookie(struct magi_cookie_list ** list, const char * input) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Cookie List */ -int magi_cookie_list_add( - struct magi_cookie_list ** list, struct magi_cookie * item) +int magi_cookie_list_add(struct magi_cookie_list ** list, + struct magi_cookie * item) { struct magi_cookie_list * old = *list; int ok = 1; @@ -345,7 +348,7 @@ int magi_cookie_list_add( (*list)->item = *item; } else { ok = 0; - magi_log("[cookie:list] Cannot allocate new list node."); + magi_error_set("[cookie:list] Cannot allocate new list node."); *list = old; } return ok; diff --git a/src/cookie.h b/src/cookie.h index f72736b..7a7365e 100644 --- a/src/cookie.h +++ b/src/cookie.h @@ -27,8 +27,8 @@ int magi_parse_cookie(struct magi_cookie_list ** list, const char * input); * Adds *item to the begining of *list, item and list are dereferencable; * Returns null in case of error. */ -int magi_cookie_list_add( - struct magi_cookie_list ** list, struct magi_cookie * item); +int magi_cookie_list_add(struct magi_cookie_list ** list, + struct magi_cookie * item); /* * Searchs for first node in list: node.name == name, name is C-string; diff --git a/src/error.c b/src/error.c index 106ca8c..01fae36 100644 --- a/src/error.c +++ b/src/error.c @@ -1,55 +1,49 @@ #include "error.h" +#include "utils.h" #include <stdarg.h> -enum control { get, set }; - -static struct magi_error * errorctl( - enum control command, struct magi_error_message * err) -{ - static struct magi_error * error = 0; - if (command == set) { - error = err; - } - return error; -} - - -struct magi_error * magi_error_get() +void magi_error_add(struct magi_error ** error, char * format, ...) { - return errorctl(get, 0); -} - -void magi_error_set(char * format, ...) -{ - for (;;) { - Create(len); - /* Try to print in the allocated space. */ - va_list ap; - va_start(ap, format); - int n = vsnprintf(p->buf, len, format, ap); - va_end(ap); - /* If that worked, we're done */ - if (n > -1 && n < len) - break; - /* Else try again with more space. */ - if (n > -1) /* glibc 2.1 */ - len = n + 1; /* precisely what is needed */ - else /* glibc 2.0 */ - len *= 2; /* twice the old size */ + if (error && format) { + struct magi_error * head = malloc(sizeof(*head)); + if (head) { + int size; + va_list args; + + va_start(args, format); + size = vsnprintf(0, 0, format, args); + va_end(args); + + if (size >= 0) { + head->message = malloc(++size); + if (head->message) { + va_start(args, format); + size = vsnprintf(head->message, size, format, args); + va_end(args); + if (size >= 0) { + head->prev = *error; + *error = head; + return; + } else { + free(head->message); + } + } + } + + free(head); + } } - errorctl(); } -void magi_error_rid() +void magi_error_destroy(struct magi_error * error) { - struct magi_error * error = errorctl(get, 0); if (error) { - if (error->message) { - free(error->message); - } - free(error); - errorctl(set, 0); + magi_error_destroy(error->prev); + free(error->prev); + free(error->message); + error->prev = 0; + error->message = 0; } } diff --git a/src/error.h b/src/error.h index 80e176f..b3014c2 100644 --- a/src/error.h +++ b/src/error.h @@ -3,13 +3,13 @@ struct magi_error { - char * message; + struct magi_error * prev; + char * message; /* enum magi_error_type { ... } type; */ }; -struct magi_error * magi_error_get(); -void magi_error_set(char * format, ...); -void magi_error_rid(); +void magi_error_add(struct magi_error ** error, char * format, ...); +void magi_error_destroy(struct magi_error * error); #endif diff --git a/src/field.c b/src/field.c index 7b0b919..6358151 100644 --- a/src/field.c +++ b/src/field.c @@ -1,6 +1,6 @@ #include "field.h" -#include "log.h" +#include "error.h" #include "param.h" #include <stdlib.h> #include <string.h> @@ -9,8 +9,8 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Form Field */ -int magi_field_list_add( - struct magi_field_list ** list, struct magi_field * item) +int magi_field_list_add(struct magi_field_list ** list, + struct magi_field * item) { struct magi_field_list * old = *list; int ok = 1; @@ -20,14 +20,14 @@ int magi_field_list_add( (*list)->item = *item; } else { ok = 0; - magi_log("[field:list] Cannot allocate new list node."); + magi_error_set("[field:list] Cannot allocate new list node."); *list = old; } return ok; } -struct magi_field * magi_field_list_get( - struct magi_field_list * list, const char * name) +struct magi_field * magi_field_list_get(struct magi_field_list * list, + const char * name) { struct magi_field * item = 0; if (list && name) { diff --git a/src/field.h b/src/field.h index 8387863..04c8411 100644 --- a/src/field.h +++ b/src/field.h @@ -22,15 +22,15 @@ struct magi_field_list { * Adds *item to the begining of *list, item and list are dereferencable; * Returns null in case of error. */ -int magi_field_list_add( - struct magi_field_list ** list, struct magi_field * item); +int magi_field_list_add(struct magi_field_list ** list, + struct magi_field * item); /* * Searchs for first node in list: node.name == name, name is C-string; * Returns node itself if succeed, otherwise result is null. */ -struct magi_field * magi_field_list_get( - struct magi_field_list * list, const char * name); +struct magi_field * magi_field_list_get(struct magi_field_list * list, + const char * name); /* * Destroys list; list is not valid after destruction. diff --git a/src/multipart.c b/src/multipart.c index f86a66d..7847a41 100644 --- a/src/multipart.c +++ b/src/multipart.c @@ -1,7 +1,7 @@ /* Support for multifile controls are not provided. */ #include "multipart.h" -#include "log.h" +#include "error.h" #include "param.h" #include <ctype.h> #include <stdio.h> @@ -76,7 +76,8 @@ static int content_disposition(struct automata * a) ok = 0; } else if (a->field.name[0] == 0) { ok = 0; - magi_log("[multipart] Wrong content-disposition quotation."); + magi_error_set( + "[multipart] Wrong content-disposition quotation."); } } else { a->field.name = create_str(name, name + strcspn(name, " \t")); @@ -84,8 +85,9 @@ static int content_disposition(struct automata * a) ok = 0; } else if (!is_str_token(a->field.name)) { ok = 0; - magi_log("[multipart] Content-disposition value is not valid, " - "readed: %s.", + magi_error_set( + "[multipart] Content-disposition value is not valid, " + "readed: %s.", a->field.name); } } @@ -97,7 +99,7 @@ static int content_disposition(struct automata * a) } } else { ok = 0; - magi_log("[multipart] Content-disposition has no '=' symbol."); + magi_error_set("[multipart] Content-disposition has no '=' symbol."); } return ok; } @@ -123,7 +125,7 @@ static int field_end(struct automata * a) int ok; if (a->field.name == 0) { ok = 0; - magi_log("[multipart] Field name is empty or not specified."); + magi_error_set("[multipart] Field name is empty or not specified."); } else { if (a->callback) { a->callback(&a->field, a->buf, a->buf_size); @@ -242,7 +244,8 @@ static enum st parse_pname_pre(struct automata * a, char c) a->boundary_pos = 0; } else { state = st_error; - magi_log("[multipart] Waiting for name, CR is readed alone."); + magi_error_set( + "[multipart] Waiting for name, CR is readed alone."); } } else if (c == '\r') { state = st_pname_pre; @@ -255,7 +258,7 @@ static enum st parse_pname_pre(struct automata * a, char c) } } else { state = st_error; - magi_log( + magi_error_set( "[multipart] Waiting for name, readed: \\%o (render: %c).", c, c); } return state; @@ -278,7 +281,8 @@ static enum st parse_pname(struct automata * a, char c) } } else { state = st_error; - magi_log("[multipart] Reading name, readed: \\%o (render: %c).", c, c); + magi_error_set("[multipart] Reading name, readed: \\%o (render: %c).", + c, c); } return state; } @@ -294,9 +298,9 @@ static enum st parse_pname_end(struct automata * a, char c) state = st_pname_end; } else { state = st_error; - magi_log("[multipart] Waiting for name-value separator, " - "readed: \\%o (render: %c).", - c, c); + magi_error_set("[multipart] Waiting for name-value separator, " + "readed: \\%o (render: %c).", + c, c); } return state; } @@ -429,8 +433,8 @@ static enum st parse_end(struct automata * a, char c) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Automata Runner */ -static int run_automata( - struct automata * a, int (*next)(void * thing), void * thing) +static int run_automata(struct automata * a, int (*next)(void * thing), + void * thing) { int ok = 1; enum st state = st_begin; @@ -468,7 +472,7 @@ static int run_automata( if (state != st_end) { ok = 0; if (state != st_error) { - magi_log("[multipart] Input ended unexpectedly."); + magi_error_set("[multipart] Input ended unexpectedly."); } free(a->field.name); free(a->field.data); @@ -481,8 +485,10 @@ static int run_automata( * Automata Interfaces */ int magi_parse_multipart(struct magi_field_list ** list, - int (*get_next)(void *), void * get_next_arg, char * boundary, - void (*callback)(struct magi_field * field, char * buffer, int len)) + int (*get_next)(void *), void * get_next_arg, + char * boundary, + void (*callback)(struct magi_field * field, + char * buffer, int len)) { struct automata a = { 0, { 0, 0, 0 }, { 0, 0 }, 0, 0, 1, 0, 0, 2, 0, 0, 0 }; diff --git a/src/param.c b/src/param.c index 8921019..d87a610 100644 --- a/src/param.c +++ b/src/param.c @@ -1,6 +1,6 @@ #include "param.h" -#include "log.h" +#include "error.h" #include <stdlib.h> #include <string.h> @@ -8,8 +8,8 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Parameter */ -int magi_param_list_add( - struct magi_param_list ** list, struct magi_param * item) +int magi_param_list_add(struct magi_param_list ** list, + struct magi_param * item) { struct magi_param_list * old = *list; int ok = 1; @@ -19,14 +19,14 @@ int magi_param_list_add( (*list)->item = *item; } else { ok = 0; - magi_log("[param:list] Cannot allocate new list node."); + magi_error_set("[param:list] Cannot allocate new list node."); *list = old; } return ok; } -struct magi_param * magi_param_list_get( - struct magi_param_list * list, const char * name) +struct magi_param * magi_param_list_get(struct magi_param_list * list, + const char * name) { struct magi_param * item = 0; if (list && name) { diff --git a/src/param.h b/src/param.h index ede1586..b06c59f 100644 --- a/src/param.h +++ b/src/param.h @@ -20,15 +20,15 @@ struct magi_param_list { * Adds *item to the begining of *list, item and list are dereferencable; * Returns null in case of error. */ -int magi_param_list_add( - struct magi_param_list ** list, struct magi_param * item); +int magi_param_list_add(struct magi_param_list ** list, + struct magi_param * item); /* * Searchs for first node in list: node.name == name, name is C-string; * Returns node itself if succeed, otherwise result is null. */ -struct magi_param * magi_param_list_get( - struct magi_param_list * list, const char * name); +struct magi_param * magi_param_list_get(struct magi_param_list * list, + const char * name); /* * Destroys list; list is not valid after destruction. diff --git a/src/request.h b/src/request.h index e556125..89181d1 100644 --- a/src/request.h +++ b/src/request.h @@ -30,6 +30,7 @@ * path_info: /foo/bar */ struct magi_request { + /* TODO: struct magi_param_list * url_params; */ struct magi_field_list * fields; struct magi_cookie_list * cookies; char * method; diff --git a/src/urlencoded.c b/src/urlencoded.c index 9d12b84..336dde0 100644 --- a/src/urlencoded.c +++ b/src/urlencoded.c @@ -1,7 +1,7 @@ #include "urlencoded.h" +#include "error.h" #include "field.h" -#include "log.h" #include <ctype.h> #include <stdlib.h> #include <string.h> @@ -47,7 +47,7 @@ static int deurl(char ** data) ci += 2; } else { ok = 0; - magi_log( + magi_error_set( "[urlencoded] Waiting for two hex digits after '%%', " "readed: \\%o\\%o (render: %c%c)", val[ci + 1], val[ci + 2], val[ci + 1], val[ci + 2]); @@ -95,7 +95,7 @@ static enum st parse_name(struct automata * a, char c) } if (!a->field.name) { state = st_error; - magi_log("[urlencoded] Cannot allocate field name."); + magi_error_set("[urlencoded] Cannot allocate field name."); } else { state = st_name; a->len++; @@ -105,8 +105,8 @@ static enum st parse_name(struct automata * a, char c) } } else { state = st_error; - magi_log( - "[urlencoded] Reading name, readed: \\%o (render: %c).", c, c); + magi_error_set("[urlencoded] Reading name, readed: \\%o (render: %c).", + c, c); } return state; } @@ -140,7 +140,7 @@ static enum st parse_data(struct automata * a, char c) } if (!a->field.data) { state = st_error; - magi_log("[urlencoded] Cannot allocate field data."); + magi_error_set("[urlencoded] Cannot allocate field data."); } else { state = st_data; a->len++; @@ -150,8 +150,8 @@ static enum st parse_data(struct automata * a, char c) } } else { state = st_error; - magi_log( - "[urlencoded] Reading data, readed: \\%o (render: %c).", c, c); + magi_error_set("[urlencoded] Reading data, readed: \\%o (render: %c).", + c, c); } return state; } @@ -178,7 +178,7 @@ int magi_parse_urlencoded(struct magi_field_list ** list, const char * input) state = end_data(&a); } else if (state == st_name) { state = st_error; - magi_log("[urlencoded] Input ended while reading name."); + magi_error_set("[urlencoded] Input ended while reading name."); } free(a.field.name); free(a.field.data); diff --git a/src/utils.c b/src/utils.c index 4212561..01969a2 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,5 +1,6 @@ #include "utils.h" +#include "error.h" #include <ctype.h> #include <stdlib.h> @@ -22,7 +23,7 @@ char * magi_str_create_copy(const char * begin, const char * end) memcpy(res, begin, end - begin); res[end - begin] = 0; } else { - magi_log("Cannot allocate string."); + magi_error_set("Cannot allocate string."); } return res; } @@ -33,7 +34,7 @@ char * magi_str_create(int len) if (str) { str[len] = 0; } else { - magi_log("Cannot allocate string."); + magi_error_set("Cannot allocate string."); } return str; } @@ -47,7 +48,7 @@ int magi_str_add(char ** dest, int * len, int * size, char c) } if (*dest == 0) { ok = 0; - magi_log("Cannot allocate string."); + magi_error_set("Cannot allocate string."); } else { (*dest)[*len] = c; ++*len; |