From 59224e484253b32432743248672d8d8ba69f110b Mon Sep 17 00:00:00 2001 From: Aleksey Veresov Date: Sat, 30 Nov 2019 18:53:03 +0300 Subject: [magi] fix --- examples/upload.c | 1 + src/cookie.c | 5 ++--- src/cookie.h | 3 +-- src/request.c | 11 +++++++++++ src/request.h | 6 ++++++ 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/examples/upload.c b/examples/upload.c index 1947f93..c61562a 100644 --- a/examples/upload.c +++ b/examples/upload.c @@ -48,6 +48,7 @@ int main(int argc, char const * argv[]) } else { magi_error_cgi(request.error); } + magi_tempfiles_destroy(&tmps); magi_request_destroy(&request); return 0; } diff --git a/src/cookie.c b/src/cookie.c index eaa221f..9d2a5ce 100644 --- a/src/cookie.c +++ b/src/cookie.c @@ -16,13 +16,12 @@ int magi_cookie_list_add(struct magi_cookie_list ** list, return !!node; } -struct magi_cookie * magi_cookie_list_get(struct magi_cookie_list * list, - const char * name) +char * magi_cookie_list_get(struct magi_cookie_list * list, const char * name) { if (!list || !name) { return 0; } else if (!strcmp(list->item.name, name)) { - return &list->item; + return list->item.data; } else { return magi_cookie_list_get(list->next, name); } diff --git a/src/cookie.h b/src/cookie.h index 82c914e..764eb53 100644 --- a/src/cookie.h +++ b/src/cookie.h @@ -22,8 +22,7 @@ int magi_cookie_list_add(struct magi_cookie_list ** list, struct magi_cookie * item); /* First node in list: node.name == name; else null. */ -struct magi_cookie * magi_cookie_list_get(struct magi_cookie_list * list, - const char * name); +char * magi_cookie_list_get(struct magi_cookie_list * list, const char * name); /* Freeing and invalidation of list. */ void magi_cookie_list_destroy(struct magi_cookie_list * list); diff --git a/src/request.c b/src/request.c index e905e53..0db1e70 100644 --- a/src/request.c +++ b/src/request.c @@ -21,6 +21,7 @@ void magi_request_setup(struct magi_request * request) } } + void magi_tempfiles_add(struct magi_tempfiles * tmps, const char * name, const char * path, @@ -46,6 +47,16 @@ void magi_tempfiles_add(struct magi_tempfiles * tmps, tmps->maximums[tmps->count - 1] = max; } +void magi_tempfiles_destroy(struct magi_tempfiles * tmps) +{ + if (!tmps) { + return; + } + free(tmps->param_names); + free(tmps->locations); + free(tmps->maximums); +} + static void tempfiles(struct magi_file * file, char * addon, int addon_len, diff --git a/src/request.h b/src/request.h index be92370..0ac7bac 100644 --- a/src/request.h +++ b/src/request.h @@ -82,21 +82,27 @@ struct magi_request { /* Setup request with default settings. */ void magi_request_setup(struct magi_request * request); + struct magi_tempfiles { int count; const char ** param_names; const char ** locations; int * maximums; /* Null maximums[i] <=> unlimited tempfiles[i]. */ }; + void magi_tempfiles_add(struct magi_tempfiles * tmps, const char * name, const char * path, int max); + +void magi_tempfiles_destroy(struct magi_tempfiles * tmps); + /* Setup request callback with files loaded into corresponding to their * parameter names locations; paths are in magi_tempfiles struct. */ void magi_request_setup_tempfiles(struct magi_request * request, struct magi_tempfiles * table); + /* Destroys request. */ void magi_request_destroy(struct magi_request * request); -- cgit v1.2.3 From 727eaf02d93e2ca7f1752d1dfcdba9fa83e83c5b Mon Sep 17 00:00:00 2001 From: Aleksey Veresov Date: Sat, 30 Nov 2019 18:54:03 +0300 Subject: [magi] fix --- src/cookie.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cookie.h b/src/cookie.h index 764eb53..0430226 100644 --- a/src/cookie.h +++ b/src/cookie.h @@ -21,7 +21,7 @@ struct magi_cookie_list { int magi_cookie_list_add(struct magi_cookie_list ** list, struct magi_cookie * item); -/* First node in list: node.name == name; else null. */ +/* Data of the first node in list: node.name == name; else null. */ char * magi_cookie_list_get(struct magi_cookie_list * list, const char * name); /* Freeing and invalidation of list. */ -- cgit v1.2.3 From 928a0a6ab06a345e6cb7485997f4902757aeb4e5 Mon Sep 17 00:00:00 2001 From: Aleksey Veresov Date: Wed, 4 Dec 2019 17:21:42 +0300 Subject: [magi] documentation fix --- src/request.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/request.h b/src/request.h index 0ac7bac..c0ff2f6 100644 --- a/src/request.h +++ b/src/request.h @@ -34,7 +34,7 @@ struct magi_request { /* Parsed */ struct magi_cookie_list * cookies; struct magi_param_list * http_params; /* HTTP Header parameters */ - struct magi_param_list * url_params; /* Urlencoded paramteres from URL */ + struct magi_param_list * url_params; /* Paramteres from URL */ struct magi_param_list * params; /* Parameters from 'post' body */ struct magi_file_list * files; /* 'Post' multipart files */ -- cgit v1.2.3 From 7bf4ef931b5d4007f12a19939b819a4d8fb31802 Mon Sep 17 00:00:00 2001 From: Aleksey Veresov Date: Wed, 4 Dec 2019 17:24:20 +0300 Subject: [magi] fix --- src/cgi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cgi.c b/src/cgi.c index 7563613..59e2ef7 100644 --- a/src/cgi.c +++ b/src/cgi.c @@ -185,6 +185,8 @@ static int next(void * any) /* Interfacial CGI Request Handling */ int magi_request_cgi(struct magi_request * request) { + request->files = 0; + request->params = 0; request->url_params = 0; request->http_params = 0; request->error = magi_error_none; @@ -197,8 +199,6 @@ int magi_request_cgi(struct magi_request * request) int magi_request_resume_cgi(struct magi_request * request) { enum magi_error * e = &request->error; - request->files = 0; - request->params = 0; request->error = magi_error_none; if (request->method && !strcmp(request->method, "post")) { const char * t = getenv("CONTENT_TYPE"); -- cgit v1.2.3 From b9a0844fe25cf717cdd796018bea2ae6eff58896 Mon Sep 17 00:00:00 2001 From: Aleksey Veresov Date: Fri, 6 Dec 2019 15:52:55 +0300 Subject: [magi] change of cookies and tempfile callback --- examples/echo.c | 4 -- examples/upload.c | 2 +- src/cgi.c | 6 +-- src/cookie.c | 14 +++-- src/cookie.h | 10 ++-- src/cookies.c | 22 +++----- src/request.c | 150 ++++++++++++++++++++++++++---------------------------- src/request.h | 23 ++++++--- src/response.c | 10 ++++ src/response.h | 3 ++ 10 files changed, 127 insertions(+), 117 deletions(-) diff --git a/examples/echo.c b/examples/echo.c index e9807f0..ca30ff7 100644 --- a/examples/echo.c +++ b/examples/echo.c @@ -22,10 +22,6 @@ void proceed_cookies(struct magi_cookie_list * cookies, magi_response_add(response, "] for domain ["); magi_response_add(response, cookies->item.domain); } - if (cookies->item.port) { - magi_response_add(response, "] for port ["); - magi_response_add(response, cookies->item.port); - } if (cookies->item.path) { magi_response_add(response, "] for path ["); magi_response_add(response, cookies->item.path); diff --git a/examples/upload.c b/examples/upload.c index c61562a..a880c53 100644 --- a/examples/upload.c +++ b/examples/upload.c @@ -35,7 +35,7 @@ void response_request(struct magi_request * req, struct magi_response * res) int main(int argc, char const * argv[]) { struct magi_request request; - struct magi_tempfiles tmps = { 0, 0, 0, 0 }; + struct magi_tempfiles tmps = { 0, 0 }; magi_request_setup(&request); magi_tempfiles_add(&tmps, "data", "data", 0); magi_request_setup_tempfiles(&request, &tmps); diff --git a/src/cgi.c b/src/cgi.c index 59e2ef7..6e8c98e 100644 --- a/src/cgi.c +++ b/src/cgi.c @@ -259,9 +259,9 @@ void output_cookies(struct magi_cookie_list * list) fputs("; Domain=", stdout); fputs(list->item.domain, stdout); } - if (list->item.port) { - fputs("; Port=", stdout); - fputs(list->item.port, stdout); + if (list->item.max_age) { + fputs("; Max-Age=", stdout); + fputs(list->item.max_age, stdout); } fputs("\r\n", stdout); list = list->next; diff --git a/src/cookie.c b/src/cookie.c index 9d2a5ce..d1d82b3 100644 --- a/src/cookie.c +++ b/src/cookie.c @@ -18,13 +18,17 @@ int magi_cookie_list_add(struct magi_cookie_list ** list, char * magi_cookie_list_get(struct magi_cookie_list * list, const char * name) { + char * res = 0; if (!list || !name) { return 0; - } else if (!strcmp(list->item.name, name)) { - return list->item.data; - } else { - return magi_cookie_list_get(list->next, name); } + while (list) { + if (!strcmp(list->item.name, name)) { + res = list->item.data; + } + list = list->next; + } + return res; } void magi_cookie_list_destroy(struct magi_cookie_list * list) @@ -36,6 +40,6 @@ void magi_cookie_list_destroy(struct magi_cookie_list * list) free(list->item.data); free(list->item.path); free(list->item.domain); - free(list->item.port); + free(list->item.max_age); } } diff --git a/src/cookie.h b/src/cookie.h index 0430226..9419457 100644 --- a/src/cookie.h +++ b/src/cookie.h @@ -6,9 +6,9 @@ struct magi_cookie { /* All pointers must be valid as 'free' arguments. */ char * name; char * data; - char * path; - char * domain; - char * port; + char * path; /* Without '/' at the end. */ + char * domain; /* With dot at the begining. */ + char * max_age; /* In seconds until discard, used only in response. */ }; struct magi_cookie_list { @@ -21,7 +21,9 @@ struct magi_cookie_list { int magi_cookie_list_add(struct magi_cookie_list ** list, struct magi_cookie * item); -/* Data of the first node in list: node.name == name; else null. */ +/* Data of last cookie in list: cookie.name == name, returns null if no such; + * Last cookie in list is first from request, and from RFC 2109 we know that + * first cookie is the most accurate for request's domain and path. */ char * magi_cookie_list_get(struct magi_cookie_list * list, const char * name); /* Freeing and invalidation of list. */ diff --git a/src/cookies.c b/src/cookies.c index 4cbe659..0c5560b 100644 --- a/src/cookies.c +++ b/src/cookies.c @@ -16,7 +16,7 @@ enum st { st_post_data }; -enum data_type { dt_plain = 0, dt_version, dt_path, dt_domain, dt_port }; +enum data_type { dt_plain = 0, dt_version, dt_path, dt_domain }; struct automata { struct magi_cookie_list ** list; @@ -25,7 +25,7 @@ struct automata { int buf_len; int buf_size; int is_first; - int is_cookie2; + int is_advanced; int is_quoted; enum data_type data_t; }; @@ -33,11 +33,11 @@ struct automata { static void nulify_cookie(struct automata * a) { - a->cookie.name = 0; - a->cookie.data = 0; - a->cookie.path = 0; - a->cookie.domain = 0; - a->cookie.port = 0; + a->cookie.name = 0; + a->cookie.data = 0; + a->cookie.path = 0; + a->cookie.domain = 0; + a->cookie.max_age = 0; } static void buf_new(struct automata * a) @@ -53,13 +53,11 @@ static enum data_type what_is_name(const struct automata * a) enum data_type data_t = dt_plain; if (a->is_first && !strcmp(a->buf, "$Version")) { data_t = dt_version; - } else if (a->is_cookie2) { + } else if (a->is_advanced) { if (!strcmp(a->buf, "$Path")) { data_t = dt_path; } else if (!strcmp(a->buf, "$Domain")) { data_t = dt_domain; - } else if (!strcmp(a->buf, "$Port")) { - data_t = dt_port; } } return data_t; @@ -96,9 +94,6 @@ static int end_data(struct automata * a) case dt_domain: a->cookie.domain = a->buf; break; - case dt_port: - a->cookie.port = a->buf; - break; case dt_version: if (strcmp(a->buf, "1")) { ok = 0; @@ -291,6 +286,5 @@ void magi_cookies(struct magi_request * request, const char * data) free(a.cookie.data); free(a.cookie.path); free(a.cookie.domain); - free(a.cookie.port); free(a.buf); } diff --git a/src/request.c b/src/request.c index 0db1e70..d8e6d69 100644 --- a/src/request.c +++ b/src/request.c @@ -22,84 +22,6 @@ void magi_request_setup(struct magi_request * request) } -void magi_tempfiles_add(struct magi_tempfiles * tmps, - const char * name, - const char * path, - int max) -{ - if (!tmps) { - return; - } - if (tmps->count++) { - tmps->param_names = realloc(tmps->param_names, - sizeof(*tmps->param_names) * tmps->count); - tmps->locations = - realloc(tmps->locations, sizeof(*tmps->locations) * tmps->count); - tmps->maximums = - realloc(tmps->maximums, sizeof(*tmps->maximums) * tmps->count); - } else { - tmps->param_names = malloc(sizeof(*tmps->param_names)); - tmps->locations = malloc(sizeof(*tmps->locations)); - tmps->maximums = malloc(sizeof(*tmps->maximums)); - } - tmps->param_names[tmps->count - 1] = name; - tmps->locations[tmps->count - 1] = path; - tmps->maximums[tmps->count - 1] = max; -} - -void magi_tempfiles_destroy(struct magi_tempfiles * tmps) -{ - if (!tmps) { - return; - } - free(tmps->param_names); - free(tmps->locations); - free(tmps->maximums); -} - -static void tempfiles(struct magi_file * file, - char * addon, - int addon_len, - int is_addon_last, - void * userdata) -{ - struct magi_tempfiles * table = userdata; - int pos; - for (pos = 0; pos != table->count; ++pos) { - if (!strcmp(table->param_names[pos], file->param_name)) { - static FILE * f = 0; - static int unlimited; - static int left; - if (!f) { - const char * loc = table->locations[pos]; - f = fopen(loc, "wb"); - left = table->maximums[pos]; - unlimited = !left; - } - if (unlimited) { - fwrite(addon, 1, addon_len, f); - } else { - int min = left < addon_len ? left : addon_len; - fwrite(addon, 1, min, f); - left -= min; - } - if (is_addon_last) { - fclose(f); - f = 0; - } - return; - } - } -} - -void magi_request_setup_tempfiles(struct magi_request * request, - struct magi_tempfiles * table) -{ - request->file_callback = tempfiles; - request->file_callback_userdata = table; -} - - static void request_free(struct magi_request * request) { free(request->cookies); @@ -158,3 +80,75 @@ void magi_request_destroy(struct magi_request * request) request_annul(request); } } + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Tempfiles Callback + */ +void magi_tempfiles_add(struct magi_tempfiles * tmps, + const char * name, + const char * path, + int max) +{ + if (!tmps) { + return; + } + if (tmps->count++) { + tmps->tmps = realloc(tmps->tmps, sizeof(*tmps->tmps) * tmps->count); + } else { + tmps->tmps = malloc(sizeof(*tmps->tmps)); + } + tmps->tmps[tmps->count - 1].param_name = name; + tmps->tmps[tmps->count - 1].location = path; + tmps->tmps[tmps->count - 1].maximum = max; +} + +void magi_tempfiles_destroy(struct magi_tempfiles * tmps) +{ + if (!tmps) { + return; + } + free(tmps->tmps); +} + +static void tempfiles(struct magi_file * file, + char * addon, + int addon_len, + int is_addon_last, + void * userdata) +{ + struct magi_tempfiles * table = userdata; + int pos; + for (pos = 0; pos != table->count; ++pos) { + if (!strcmp(table->tmps[pos].param_name, file->param_name)) { + static FILE * f = 0; + static int unlimited; + static int left; + if (!f) { + const char * loc = table->tmps[pos].location; + f = fopen(loc, "wb"); + left = table->tmps[pos].maximum; + unlimited = !left; + } + if (unlimited) { + fwrite(addon, 1, addon_len, f); + } else { + int min = left < addon_len ? left : addon_len; + fwrite(addon, 1, min, f); + left -= min; + } + if (is_addon_last) { + fclose(f); + f = 0; + } + return; + } + } +} + +void magi_request_setup_tempfiles(struct magi_request * request, + struct magi_tempfiles * table) +{ + request->file_callback = tempfiles; + request->file_callback_userdata = table; +} diff --git a/src/request.h b/src/request.h index c0ff2f6..df9a57c 100644 --- a/src/request.h +++ b/src/request.h @@ -83,11 +83,22 @@ struct magi_request { void magi_request_setup(struct magi_request * request); +/* Destroys request. */ +void magi_request_destroy(struct magi_request * request); + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Tempfiles Callback + */ +struct magi_tempfile { + const char * param_name; /* Form field name, in which file is expected. */ + const char * location; /* Location to load file in. */ + int maximum; /* Null <=> unlimited. */ +}; + struct magi_tempfiles { - int count; - const char ** param_names; - const char ** locations; - int * maximums; /* Null maximums[i] <=> unlimited tempfiles[i]. */ + int count; + struct magi_tempfile * tmps; }; void magi_tempfiles_add(struct magi_tempfiles * tmps, @@ -103,8 +114,4 @@ void magi_request_setup_tempfiles(struct magi_request * request, struct magi_tempfiles * table); -/* Destroys request. */ -void magi_request_destroy(struct magi_request * request); - - #endif diff --git a/src/response.c b/src/response.c index 7e2ec0b..5e2f326 100644 --- a/src/response.c +++ b/src/response.c @@ -82,6 +82,16 @@ void magi_response_cookie_easy(struct magi_response * response, magi_cookie_list_add(&response->cookies, &cookie); } +void magi_response_cookie_discard(struct magi_response * response, + const char * name) +{ + struct magi_cookie cookie = { 0, 0, 0, 0, 0 }; + cookie.name = magi_str_create_copy(name, name + strlen(name)); + cookie.max_age = magi_str_create(1); + cookie.max_age[0] = '0'; + magi_cookie_list_add(&response->cookies, &cookie); +} + void magi_response_http(struct magi_response * response, const char * name, const char * data) diff --git a/src/response.h b/src/response.h index 95f6537..7389637 100644 --- a/src/response.h +++ b/src/response.h @@ -35,6 +35,9 @@ void magi_response_cookie_easy(struct magi_response * response, const char * name, const char * value); +void magi_response_cookie_discard(struct magi_response * response, + const char * name); + void magi_response_http(struct magi_response * response, const char * name, const char * data); -- cgit v1.2.3 From 26405332102756912ab2c175874555d6eb8c332f Mon Sep 17 00:00:00 2001 From: Aleksey Veresov Date: Fri, 6 Dec 2019 16:46:19 +0300 Subject: [magi] fix tempfiles callback --- src/request.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/request.c b/src/request.c index d8e6d69..8c3a101 100644 --- a/src/request.c +++ b/src/request.c @@ -119,6 +119,9 @@ static void tempfiles(struct magi_file * file, { struct magi_tempfiles * table = userdata; int pos; + if (!file->file_name || !strcmp(file->file_name, "")) { + return; + } for (pos = 0; pos != table->count; ++pos) { if (!strcmp(table->tmps[pos].param_name, file->param_name)) { static FILE * f = 0; -- cgit v1.2.3 From c299128eaefc813d1a6acdca8a9c724145686177 Mon Sep 17 00:00:00 2001 From: Aleksey Veresov Date: Mon, 3 Feb 2020 19:43:53 +0300 Subject: [magi] Readme added + fixes. --- license | 2 +- readme | 42 ++++++++++++++++++++++++++++++++++++++++++ src/cgi.c | 6 +++--- src/cookies.c | 2 +- src/inner_tools.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/inner_tools.h | 19 +++++++++++++++++++ src/multipart.c | 10 +++++----- src/response.c | 16 ++++++++-------- src/urlenc.c | 2 +- src/utils.c | 50 -------------------------------------------------- src/utils.h | 15 --------------- 11 files changed, 131 insertions(+), 84 deletions(-) create mode 100644 readme create mode 100644 src/inner_tools.c create mode 100644 src/inner_tools.h delete mode 100644 src/utils.c delete mode 100644 src/utils.h diff --git a/license b/license index 8f83b9c..d89e508 100644 --- a/license +++ b/license @@ -1,4 +1,4 @@ -Copyright 2019 Aleksey Veresov +Copyright 2019-2020 Aleksey Veresov 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 diff --git a/readme b/readme new file mode 100644 index 0000000..8cc3b8b --- /dev/null +++ b/readme @@ -0,0 +1,42 @@ + Description +Magi Library (libmagi) implements Gateway Interfaces, namely CGI and FastCGI. + + Overview +Magi is free and open-source software: legal info is in the 'license' file. +It is written in ANSI C, without any dependecies, except for C standard +library. All source and header files are located in the 'src' directory. +Files with 'inner' part in their names are not intended for external use. +Since filenames in the project are short and simple consider placing +header files in subdirectory 'magi' of your include. + + Compiling +Compilation and its options are described in the 'Makefile'. +Running 'make' produces 'libmagi.a' file, which is precompiled library itself, +ready to be statically linked into your project. + + Examples +Compilation and its options are described in the local 'examples/Makefile'. +Running 'make' in the 'examples' directory produces 'append', 'cookie', +'upload', and 'echo' CGI executables. Descriptions and details are in +corresponding source files. + + Usage +Magi main purpose is to analyse request and provide it in 'struct magi_request' +variable. It is described in 'src/request.h'; to setup defaults before actual +processing run 'magi_request_setup'. Next step is to analyse post-unrelated +part of request via 'magi_request_cgi'. Since post part can be realy big, +it is generally useful to constrain its analysis biased on the rest of request. +Post part analyse is done via 'magi_request_resume_cgi'. You can destroy +request structure via 'magi_request_destroy'. + +Also magi provide output capabilities via 'struct magi_response'. +Similary to request, 'magi_response_setup' is initialisation of response with +defaults. Content type need to be specified for response, to set it run +'magi_response_content_type'. You can set cookie with 'magi_response_cookie', +as well as discard them with 'magi_response_cookie_discard'. You can set HTTP +headers with 'magi_response_http'. For filling response body use +'magi_response_add' and 'magi_response_add_format'. To send response call +'magi_response_cgi'. Desctruction is provided in 'magi_response_destroy'. + + Motivation +Web must be fun. diff --git a/src/cgi.c b/src/cgi.c index 6e8c98e..fac6a4a 100644 --- a/src/cgi.c +++ b/src/cgi.c @@ -4,11 +4,11 @@ #include "cookies.h" #include "error.h" #include "file.h" +#include "inner_tools.h" #include "multipart.h" #include "param.h" #include "request.h" #include "urlenc.h" -#include "utils.h" #include #include #include @@ -169,9 +169,9 @@ static char * bound(const char * type) type += strspn(type, " \t") + 1; if (*type == '"') { ++type; - res = magi_str_create_copy(type, strchr(type, '"')); + res = magi_str_create_copy(type, type - strchr(type, '"')); } else { - res = magi_str_create_copy(type, type + strcspn(type, " \t")); + res = magi_str_create_copy(type, strcspn(type, " \t")); } } return res; diff --git a/src/cookies.c b/src/cookies.c index 0c5560b..f9e84da 100644 --- a/src/cookies.c +++ b/src/cookies.c @@ -1,7 +1,7 @@ /* * * TODO * * */ #include "cookies.h" -#include "utils.h" +#include "inner_tools.h" #include #include diff --git a/src/inner_tools.c b/src/inner_tools.c new file mode 100644 index 0000000..d958851 --- /dev/null +++ b/src/inner_tools.c @@ -0,0 +1,51 @@ +#include "inner_tools.h" + +#include +#include +#include + + +void magi_str_lowercase(char *str) +{ + if (!str) { + return; + } + for (; *str; ++str) { + *str = tolower(*str); + } +} + +char *magi_str_create_copy(const char *first, int len) +{ + char *copy = magi_str_create(len); + if (copy) { + memcpy(copy, first, len); + } + return copy; +} + +char *magi_str_create(int len) +{ + char *str = malloc(len + 1); + if (str) { + str[len] = 0; + } + return str; +} + +int magi_str_add(char **dest, int *len, int *size, char c) +{ + if (!*dest) { + *dest = magi_str_create(1); + } else if (*len + 1 == *size) { + *size *= 2; + *dest = realloc(*dest, *size); + } + if (!*dest) { + return 0; + } + (*dest)[*len] = c; + ++*len; + (*dest)[*len] = 0; + return 1; +} diff --git a/src/inner_tools.h b/src/inner_tools.h new file mode 100644 index 0000000..87489c8 --- /dev/null +++ b/src/inner_tools.h @@ -0,0 +1,19 @@ +#ifndef MAGI_INCLUDED_INNER_TOOLS +#define MAGI_INCLUDED_INNER_TOOLS +/* Magi Inner Tools + * This file must not be included in header files intended for external use, + * it contains some common utility functions for use in source files. + */ + + +void magi_str_lowercase(char *str); + +/* Results of both create functions are malloced, so need to be freed. */ +char *magi_str_create_copy(const char *first, int len); +char *magi_str_create(int len); + +/* Null only in case of error; if *dest is null creates string. */ +int magi_str_add(char **dest, int *len, int *size, char c); + + +#endif diff --git a/src/multipart.c b/src/multipart.c index 7b829d8..aca0fd9 100644 --- a/src/multipart.c +++ b/src/multipart.c @@ -2,8 +2,8 @@ #include "multipart.h" #include "error.h" +#include "inner_tools.h" #include "param.h" -#include "utils.h" #include #include #include @@ -74,9 +74,9 @@ static char * extract_filename(char * n) n += strspn(n, " \t") + 1; if (*n == '"') { ++n; - return magi_str_create_copy(n, strchr(n, '"')); + return magi_str_create_copy(n, n - strchr(n, '"')); } else { - return magi_str_create_copy(n, n + strcspn(n, " \t")); + return magi_str_create_copy(n, strcspn(n, " \t")); } } @@ -89,12 +89,12 @@ static int content_disposition(struct automata * a) n += strspn(n, " \t") + 1; if (*n == '"') { ++n; - a->param.name = magi_str_create_copy(n, strchr(n, '"')); + a->param.name = magi_str_create_copy(n, n - strchr(n, '"')); if (!a->param.name || !*a->param.name) { return 0; } } else { - a->param.name = magi_str_create_copy(n, n + strcspn(n, " \t")); + a->param.name = magi_str_create_copy(n, strcspn(n, " \t")); if (!a->param.name || !is_str_token(a->param.name)) { return 0; } diff --git a/src/response.c b/src/response.c index 5e2f326..914f021 100644 --- a/src/response.c +++ b/src/response.c @@ -1,6 +1,6 @@ #include "response.h" -#include "utils.h" +#include "inner_tools.h" #include #include #include @@ -27,8 +27,8 @@ void magi_response_content_type(struct magi_response * response, "Content-Type: application/xhtml+xml", /* magi_xhtml */ }; if (!response->content_type) { - const char * end = messages[type] + strlen(messages[type]); - response->content_type = magi_str_create_copy(messages[type], end); + response->content_type = magi_str_create_copy(messages[type], + strlen(messages[type])); } } @@ -77,8 +77,8 @@ void magi_response_cookie_easy(struct magi_response * response, const char * value) { struct magi_cookie cookie = { 0, 0, 0, 0, 0 }; - cookie.name = magi_str_create_copy(name, name + strlen(name)); - cookie.data = magi_str_create_copy(value, value + strlen(value)); + cookie.name = magi_str_create_copy(name, strlen(name)); + cookie.data = magi_str_create_copy(value, strlen(value)); magi_cookie_list_add(&response->cookies, &cookie); } @@ -86,7 +86,7 @@ void magi_response_cookie_discard(struct magi_response * response, const char * name) { struct magi_cookie cookie = { 0, 0, 0, 0, 0 }; - cookie.name = magi_str_create_copy(name, name + strlen(name)); + cookie.name = magi_str_create_copy(name, strlen(name)); cookie.max_age = magi_str_create(1); cookie.max_age[0] = '0'; magi_cookie_list_add(&response->cookies, &cookie); @@ -97,8 +97,8 @@ void magi_response_http(struct magi_response * response, const char * data) { struct magi_param param = { 0, 0 }; - param.name = magi_str_create_copy(name, name + strlen(name)); - param.data = magi_str_create_copy(data, data + strlen(data)); + param.name = magi_str_create_copy(name, strlen(name)); + param.data = magi_str_create_copy(data, strlen(data)); magi_param_list_add(&response->http_params, ¶m); } diff --git a/src/urlenc.c b/src/urlenc.c index 8c38a0a..f0a01ca 100644 --- a/src/urlenc.c +++ b/src/urlenc.c @@ -1,6 +1,6 @@ #include "urlenc.h" -#include "utils.h" +#include "inner_tools.h" #include #include #include diff --git a/src/utils.c b/src/utils.c deleted file mode 100644 index 931d1e4..0000000 --- a/src/utils.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "utils.h" - -#include -#include -#include - - -void magi_str_lowercase(char * str) -{ - if (str) { - while (*str) { - *str = tolower(*str); - ++str; - } - } -} - -char * magi_str_create_copy(const char * begin, const char * end) -{ - char * res; - res = malloc(end - begin + 1); - if (res) { - memcpy(res, begin, end - begin); - res[end - begin] = 0; - } - return res; -} - -char * magi_str_create(int len) -{ - char * str = malloc(len + 1); - if (str) { - str[len] = 0; - } - return str; -} - -int magi_str_add(char ** dest, int * len, int * size, char c) -{ - if (*len + 1 == *size) { - *size *= 2; - *dest = realloc(*dest, *size); - } - if (*dest) { - (*dest)[*len] = c; - ++*len; - (*dest)[*len] = 0; - } - return !!*dest; -} diff --git a/src/utils.h b/src/utils.h deleted file mode 100644 index f67c66c..0000000 --- a/src/utils.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef MAGI_INCLUDED_UTILS -#define MAGI_INCLUDED_UTILS - - -void magi_str_lowercase(char * str); - -/* Results of both create functions are malloced, so need to be freed. */ -char * magi_str_create_copy(const char * begin, const char * end); -char * magi_str_create(int len); - -/* Null only in case of error. */ -int magi_str_add(char ** dest, int * len, int * size, char c); - - -#endif -- cgit v1.2.3 From 55e11567a2eabcc1f34955062cef5610d16400fb Mon Sep 17 00:00:00 2001 From: Aleksey Veresov Date: Mon, 3 Feb 2020 21:01:22 +0300 Subject: [magi] Makefile update. --- Makefile | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 1934910..d57c2d1 100644 --- a/Makefile +++ b/Makefile @@ -1,35 +1,58 @@ -# Debug mode: +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Compilation Options +# Debug mode (uncoment to be able to debug the library via gdb): # DEBUG = yes - +# Specify your favourite C compiler here (e.g. tcc): CC = gcc + + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Preparations LIB = libmagi.a +# Compile under the most strict conditions: CFLAGS = -xc -ansi -pedantic -Wall +# Debug and optimisation are not compatible: ifeq '$(DEBUG)' 'yes' CFLAGS += -g -O0 else CFLAGS += -O3 endif +# Object files listing: SRC_DIR = src SRC = $(wildcard $(SRC_DIR)/*.c) OBJ = $(SRC:.c=.o) +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Targets +# 'make' will produce library by default: default: $(LIB) -ifneq "clean" "$(MAKECMDGOALS)" --include deps.mk -endif +# Cleaning means removing everything automatically produced: +clean: + rm -f $(OBJ) $(LIB) deps.mk -deps.mk: $(SRC) - $(CC) -MM $^ > $@ +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Compilation +# Compile object files from corresponding source and header: %.o: %.c %.h $(CC) $(CFLAGS) -c $< -o $@ +# Packing object files into library: $(LIB): $(OBJ) ar rcs $@ $^ -clean: - rm -f $(OBJ) $(LIB) deps.mk + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Dependencies +# Generating dependencies description file: +deps.mk: $(SRC) + $(CC) -MM $^ > $@ + +# While cleaning we need to remove it, not include: +ifneq "clean" "$(MAKECMDGOALS)" +-include deps.mk +endif -- cgit v1.2.3 From 746c3f3076fe5994f08d729aa1b958465231b0c8 Mon Sep 17 00:00:00 2001 From: Aleksey Veresov Date: Tue, 4 Feb 2020 14:57:11 +0300 Subject: [magi] --- Makefile | 4 ++-- examples/Makefile | 31 +++++++++++++++++++++++++------ readme | 42 +++++++++++++++++++++++++----------------- 3 files changed, 52 insertions(+), 25 deletions(-) diff --git a/Makefile b/Makefile index d57c2d1..db1fefd 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Compilation Options -# Debug mode (uncoment to be able to debug the library via gdb): +# Debug mode (allowing to debug the library via gdb): # DEBUG = yes # Specify your favourite C compiler here (e.g. tcc): CC = gcc @@ -27,7 +27,7 @@ OBJ = $(SRC:.c=.o) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Targets -# 'make' will produce library by default: +# 'make' produces library by default: default: $(LIB) # Cleaning means removing everything automatically produced: diff --git a/examples/Makefile b/examples/Makefile index d93176b..2f57b1e 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,29 +1,48 @@ -# Uncomment following to enable debug mode: +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Compilation Options +# Debug mode (allowing to debug the examples via gdb): # DEBUG = yes - +# Specify your favourite C compiler here (e.g. tcc): CC = gcc + + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Preparations EXAMPLES = append cookie upload echo +# Compile under the most strict conditions: CFLAGS = -xc -ansi -pedantic -Wall +# Debug and optimisation are not compatible: ifeq '$(DEBUG)' 'yes' CFLAGS += -g -O0 else CFLAGS += -O3 endif +# Including magi library headers and setting linker to use it: INCLUDE = -I ../src LFLAGS = -L.. -lmagi +# Specification of library file to produce it, if not provided: MAGI = ../libmagi.a +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Targets +# 'make' produces all examples by default: default: $(EXAMPLES) -$(MAGI): - cd ..; $(MAKE) +# Cleaning means removing everything automatically produced: +clean: + rm -f $(EXAMPLES) + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# Compilation +# Compile executables from corresponding sources and library: %: %.c $(MAGI) $(CC) $(CFLAGS) $(INCLUDE) $< $(LFLAGS) -o $@ -clean: - rm -f $(EXAMPLES) +# Run make for library to produce it: +$(MAGI): + cd ..; $(MAKE) diff --git a/readme b/readme index 8cc3b8b..59dfc25 100644 --- a/readme +++ b/readme @@ -2,8 +2,8 @@ Magi Library (libmagi) implements Gateway Interfaces, namely CGI and FastCGI. Overview -Magi is free and open-source software: legal info is in the 'license' file. -It is written in ANSI C, without any dependecies, except for C standard +Magi are free and open-source software: legal info is in the 'license' file. +They are written in ANSI C, without any dependecies, except for C standard library. All source and header files are located in the 'src' directory. Files with 'inner' part in their names are not intended for external use. Since filenames in the project are short and simple consider placing @@ -21,22 +21,30 @@ Running 'make' in the 'examples' directory produces 'append', 'cookie', corresponding source files. Usage -Magi main purpose is to analyse request and provide it in 'struct magi_request' -variable. It is described in 'src/request.h'; to setup defaults before actual -processing run 'magi_request_setup'. Next step is to analyse post-unrelated -part of request via 'magi_request_cgi'. Since post part can be realy big, -it is generally useful to constrain its analysis biased on the rest of request. -Post part analyse is done via 'magi_request_resume_cgi'. You can destroy -request structure via 'magi_request_destroy'. +magi_request analyses incoming request, general workflow is to: +1. Prepare request for analysis, setup defaults via 'magi_request_setup'; +2. Process non-post part of the CGI request via 'magi_request_cgi'; + (The division of post and non-post analysis comes from the fact that + post body can be really huge, so you probably will want to specify + some constraints on it, based on non-post info. For example session id + from non-post part allowes some users (e.g. admins) to load more in post.) +3. Process post part of the CGI request via 'magi_request_resume_cgi'; +4. Now you have the full request analysed, so do your work; +5. And finally, free memory via 'magi_request_destroy'. +For more see 'src/request.h'. -Also magi provide output capabilities via 'struct magi_response'. -Similary to request, 'magi_response_setup' is initialisation of response with -defaults. Content type need to be specified for response, to set it run -'magi_response_content_type'. You can set cookie with 'magi_response_cookie', -as well as discard them with 'magi_response_cookie_discard'. You can set HTTP -headers with 'magi_response_http'. For filling response body use -'magi_response_add' and 'magi_response_add_format'. To send response call -'magi_response_cgi'. Desctruction is provided in 'magi_response_destroy'. +magi_response provides output capabilities. You can form the response with +'magi_response_setup' used to setup defaults, and the following functions to +fill in your data ('...' means 'magi_response_'): + ...content_type: set Content Type (by default XHTML); + ...cookie: set HTTP Cookie; +...cookie_discard: discard HTTP Cookie; + ...http: setup arbitarary HTTP header; + ...add: add something to the body; + ...add_format: add comething to the body, using format (similar to printf); +Outputting itself can be done with 'magi_response_cgi'. +To correctly free all occupied memory call 'magi_response_destroy'. +For more see 'src/response.h'. Motivation Web must be fun. -- cgit v1.2.3